2014

Results 30 issues of 2014

### 记录一下这次用docker遇到的一些问题 先提供一个我用的包含[puppeteer的docker镜像](https://github.com/alekzonder/docker-puppeteer) puppeteer可以使用Network.emulateNetworkConditions和Emulation.setCPUThrottlingRate轻松地模拟不同的网络请求。但是,这一个CPU节流器只是相对延缓你的CPU,在不同的机器我们会得到不同的结果,所以我们必须要统一一个环境来运行我们的程序。 于是docker出现在了我的视野中。记录一下docker的常用命令 ```bash docker info docker run -v /host/path:/container/path -v /path:/path -dit z2014/detector_docker:0.1 /bin/bash docker ps docker stop id docker rm id docker build -f Dockerfile -t...

继上一篇[探索----面向单元测试编写React组件](https://github.com/z2014/Blog/issues/18)之后,笔者开始探索如何能保证我们播放中的落地页进行高质量的产品迭代。 先来[体验](https://h5.gdt.qq.com/xjviewer/nemo/1055311?_wv=1)一下我们的业务,目前我们的平台每天会服务于广告主制作各种各样的落地页,那么我们希望在发布新功能的同时,同时能够快速验证老的特性能够不受影响。 那么为了完成这个目标,我们可以让测试同学回归下本次修改可能涉及到的特性,来确保功能的正常, - 解决方案一: 如果每一次代码合并master之后就要验证一次,这样的工作可能会让测试同学感到厌烦,因为会有大量重复性的工作 - 解决方案二: 但是如果只验证最后将要发布的master代码时,一旦出现了问题,不能马上定位到具体是哪一次merge所带来的影响,因此不能快速修复该问题。 看来上述两种方案都不是最好的,我们希望能够通过机器自动化的帮我们回归已有功能,因此,我们的自动化测试也因此而诞生。 ### 首先,我们先来思考下我们业务中哪些功能需要回归 1. 样式ui 我们给广告主提供了强大的自定义ui样式功能,能够快速的帮助广告主创建出精美的落地页,那么我们一定希望以往的ui不会受到影响 2. 样式按钮交互,在点击之后,能够符合预期 ### 解决问题一:样式ui问题 **_我们如何能够让机器知道这个组件的样式是渲染正常的呢?_** 之前分享jest的snapshot给了启发,那就是**快照**的概念,如果我们能够保存一份正确渲染的组件图片,那么我们只需要在每次merge进master之后,对比上一次的快照图片,如果图片一致,就说明功能是正常的。 那么基于此,我们引入了puppeteer的截图功能,在我们每一次代码merge进入master之后,触发了我们的ci流程后,就调用puppeteer,对我们已经创建好的一份最全的组件功能页面进行截图,与上一次保存的图片进行比较,看似实现到这里,已经没有了什么问题,那有serverless什么事呢,难道又是标题党蹭热度? 但是我们会发现,我们调用ci执行的docker环境中需要拉取我们自己创建的docker镜像,这个镜像里面需要包含puppeteer和一些基础库,那么拉取镜像这个过程本身比执行我们的测试用例耗时的多,那么有没有方法去缩短这段时间呢? 这个时候,serverless就横空出世了! serverless可以理解成运行在云上的一个函数,它由事件所触发,然后创建这个函数的实例,最后销毁,我们只需要去编写这个函数本身的代码即可。 当我们持续优化我们的测试流程时,我们播放端的ci构建就简化成了这样的一段代码 ``` curl http://serverless.example.com ```...

### docker相关 ```shell systemctl start docker //启动 sudo systemctl daemon-reload // 守护进程重启 systemctl restart  docker // 重启docker服务 sudo service docker restart // 重启docker服务   service docker stop // 关闭docker systemctl stop...

在一个多人协作的大型项目中,我们在开发的过程中可能经常会面临到这样的问题: - 哎,这次我没有改动到这里啊,这怎么会有bug呢 - 哎,怎么新加了个功能原来的功能受影响了呢 - 哎,这里的样式为什么乱掉了 当我们被提出这些bug的时候,我们是二脸懵逼的,因为这不符合一个程序员的预期!!! 那么我们如何能够避免以上的问题,从而将经历投入到更多的开发(写bug)中去呢? 笔者在这里试着归纳了一下解决问题的办法 ### 样式问题需要制定相应的规范 - 不能使用css,只能用less来书写(大哥,都2888年了还不用less吗) - 使用less的类模块化写法 - 命名风格采用BEM (推荐) ```less .app{ width: 100%; .center{ height: 100% } } ``` (不推荐)...

node
javascript

之前在写react的时候,当我们做map循环的时候,当我们没有一个唯一id来标识每一项item的时候,我们可能会选择使用index ``` data.map((item, index) => { return {item} }) ``` 但是其实当你使用index来作为唯一key的时候,其实是由一个大坑的,什么坑呢?必须坑了你才知道,来看下面的这种情况: ``` class App extends React.Component{ constructor(props) { super(props) this.state = { list: [{id: 1,val: 'aa'}, {id: 2, val: 'bb'},...

javascript

继上一篇[年轻时,我不写单元测试](https://github.com/z2014/Blog/issues/16)文章过后,我们开始在项目中引入了单元测试,希望能够通过单元测试提前发现问题,但是在实施中我们遇到了一个比较严重的问题: > **复杂React组件的单元测试编写难度太大,导致大家不愿意编写单元测试** 为了解决这个问题,我们做了积极的探索,首先,我们回归到我们引入单元测试的本质 #### 希望单元测试解决什么问题? - 面对复杂的业务场景,共用模块间难免会相互影响,希望用单元测试来覆盖原有逻辑,从而保证引入新逻辑,原有模块依然能够表现正常。 这时我们从目标结果反推方式,会发现我们偏移了我们的目标,我们并不希望界面上的ui也包含在我们的单元测试中,页面上ui交互的操作,应该是我们自测过程中,就能够自己发现的问题,而单元测试应该专注于逻辑的测试。基于这样的定位,我们回过头来,再来重新看我们的业务代码,就需要探索出一种新的React组件模式。 最终,我们借鉴了**分层思想**来去设计我们的React组件 我们将一个React组件,分成了UI交互层和逻辑处理层两部分 - UI交互层专注于交互以及UI的正常展示 - 逻辑处理层包括了一个一个的逻辑单元模块,去处理不同的业务逻辑, 利用纯函数的思想,去保证输入和输出的可控 通过这样的分层设计,我们将react中业务逻辑相关拆分出来,针对这样的一个一个单元模块,我们在编写相对应的测试用例,极大的降低了编写一个复杂组件的单元测试的成本。

最近在做项目时,被内部的安全平台扫出了漏洞,也是之前自己早就知道的一些攻击方式,但是在写代码时并没有注意到,这里先记录下: ## 1.ssrf 什么是ssrf呢? > 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。 场景是我在用canvasToHtml的截图库时,由于上传的图片返回的是公司的cdn,因此,如果截图中含有图片时,datatourl就会报错,因为此时调用canvas的画布被认定是一张脏画布,因此这个库的解决方案是请求自己的服务器,再由服务器做一层转发,去请求cdn的地址,代码类似于 `/picture?url=http://i..../c.png` 到了服务端,我们拿到query,再做一次转发 `ctx.body = req.pipe(request(imageUrl).on('error', next));` 但是,其实这个时候是需要校验一下请求的url是不是我们的cdn路径的,很有可能她就会向我们的内网服务发起请求了 ## 2.xss xss想必每个人都不陌生,但是真的自己还是too young! 我用的是art-template来渲染模板 ``` var result = { content: '' }; ``` 当我的content是后端从location里面取出来并且做了加工之后,返回给模板渲染的时候, 这个时候就有可能会引起xss的问题:...

现在网上有很多react原理解析这样的文章,但是往往这样的文章我看完过后却没有什么收获,因为行文思路太快,大部分就是写了几句话简单介绍下这段代码是用来干嘛的,然后就贴上源码让你自己看,有可能作者本人是真的看懂了,但是对于大部分阅读这篇文章的人来说,确是云里雾里。 讲解一个框架的源码,最好的方式就是实现一个简易版的,这样在你实现的过程中,读者就能了解到你整体的思路,也就能站在更高的层面上对框架有一个整体的认知,而不是陷在一些具体的技术细节上。 这篇文章就非常棒的实现了一个简单的react框架,接下来属于对[原文](https://medium.com/@sweetpalma/gooact-react-in-160-lines-of-javascript-44e0742ad60f)的翻译加上一些自己在使用过程中的理解。 首先先整体介绍通过这篇文章你能学到什么--我们将实现一个简单的React,包括简单的组件级api和虚拟dom,文章也将分为以下四个部分 - Elements:在这一章我们将学习JSX是如何被处理成虚拟DOM的 - Rendering: 在这一小节我们将想你展示如何将虚拟dom变成真实的DOM的 - Patching: 在这一章我们将向你展示为什么key如此重要,并且如何利用虚拟DOM对已存在的DOM进行批量更新 - Components :最后一小节将告诉你React组件和他的生命周期 ## Element 元素携带者很多重要的信息,比如节点的type,props,children list,根据这些属性,能渲染出我们需要的元素,它的树形结构如下 ```javascript { "type": "ul", "props": { "className": "some-list" }, "children": [...

这里是原文链接[Tree-shaking versus dead code elimination](https://medium.com/@Rich_Harris/tree-shaking-versus-dead-code-elimination-d3765df85c80) 我一直致力于一个叫rollup的工具,它可以将js各个模块打包在一起。其中他有一个特性叫tree-shaking,他会只将你程序需要的js代码打包进去。 有人问我这个概念从哪里得来的? 然后另一个人就说他只是“消除死代码”换了一个名字 又有一个人说这个tree shaking很愚蠢 但是实际上他们是不同的东西,即使他们在做一件相同的事--减少代码 **## Dead code elimination is silly** 我们来做一个不是很恰当的类比:想象一下你在制作蛋糕的过程中将一整个鸡蛋放进碗里,并且正在捣碎它,而不是我们正常的那种将鸡蛋打开,然后将鸡蛋清之类的倒进去搅拌(类似于鸡蛋汤的操作)。当我们把蛋糕拿出锅的时候,再清理一下鸡蛋壳,这个工作除了十分复杂以外,大部分鸡蛋壳还会遗留在那。 这样,你可能只能吃很少的蛋糕了。 先完成整个项目,然后剔除掉你不要的代码,这就是Dead code elimination。tree-shaking,则是完全相反的一方面,告诉我我要做什么蛋糕,混合的时候需要什么原料。 相比较dead code, 我们推荐live code。从结果来说可能是相同的,但是因为在js中静态分析的限制,就不一样了。live code能获取到更好的结果,而且从表面上看,live code用来解决清楚无用代码的方式更符合逻辑。 一旦发生,rollup并不是最好的。更多的介绍在下面。所以最好的方式是两个都用,rollup打包之后用UglifyJS or...

translation

[**这里是原文链接**](https://reactjs.org/blog/2018/03/29/react-v-16-3.html) 一段时间以前,我们写了一篇文章有关我们即将升级我们遗留的生命周期方法,包含着我们慢慢的迁移的策略。在React 16.3.0这个版本中,为了慢慢迁移,我们增加了一些新的生命周期。我们也推荐了一些被长期期待的一些特性:一个官方的context api,一个 forwarding ref,一个ergonomic ref。 ## Official Context API 这么长时间以来,React一直提供了一个实验性的api context.尽管它是一个很有用的工具,我们还是不推荐使用它因为一些隐藏的问题。而且我们一直计划去用一个更好的api去替代它。 16.3这个版本引入了一个新的context api,它更加的高效,而且他支持各种静态类型检查和很深层次的更新。 这有一个例子来说明,你可以想象你注入了了一个“theme”变量去使用新的api ```javascript const ThemeContext = React.createContext("light") class ThemeProvider extends React.Component{ state = {theme: 'light'} render(){...

translation