`换成`
![]()
`即可。
269 |
270 | line-height 的继承无处不在,而**line-height 不同值类型对于继承也会有不同的影响**,这一点经常被考察到。例如
271 |
272 | - `line-height: 50px`这种固定尺寸,往下继承的就是`50px`
273 | - `line-height: 1.5`这种数值,往下继承的就是`1.5`这个倍数
274 | - `line-height: 150%`或者`line-height: 1.5em`这种方式,往下继承的是当前计算出来的数值,而不是倍数,这里一定要注意!!!
275 |
276 | ### vertical-align
277 |
278 | vertial-align 只有在内联元素以及 table-cell(即表格单元格)元素中才能生效,vertical-align 值比较多,可参考 http://www.w3school.com.cn/cssref/pr_pos_vertical-align.asp 。其中,书中重点强调了可使用数字或者百分比,用处比较大。例如,当文字和小图标一行时,小图标位置偏上,可以给小图标设置`line-height: -5px`让其下移,书中 128 页。
279 |
280 | 书中这里还讲解了好多 vertical-align 的内容,不过我没有继续往下看,因为感觉这些内容已经太深太专业了,和日常的开发联系并不大,因此就先跳过。
281 |
282 | ## 流的破坏和保护
283 |
284 | 本章讲解的元素没有流动特性,而是对流动特性的破坏,但是这也和“流”有关。主要与`floot` BFC `absolute`相关。
285 |
286 | ### float
287 |
288 | 首先,float 是一个很古老的样式属性,**它设计的初衷就是实现简单的图文混排(像报纸一样)**,并没有考虑其他的使用场景。而现在 float 被大家大量的用来做布局使用,做不是它设计初衷的事情,肯定会出现很多问题,也**失去了流动性**。因此,**float 是魔鬼,尽量不要触发它,能躲则躲**。CSS3 慢慢普及之后,我们可以使用 flex grid 来做布局,不要再用 float 了。
289 |
290 | 元素设置了 float 会有以下几个特性:
291 |
292 | - 包裹性。本来元素是自动撑满整个父容器的,设置了 float 之后就会收缩,紧紧包裹住内容。
293 | - 触发 BFC(是其中一个条件)
294 | - 破坏文档流,使父元素塌陷
295 | - 没有任何 margin 合并。都跳出文档流了,肯定也不符合流式布局的特点了。
296 |
297 | float 和流式布局也可以结合使用,例如左右布局,左侧元素宽度`60px`并且设置`float`,右侧设置`margin-left: 70px`即可,书中 156 页。
298 |
299 | 最后,和 float 分不开的还有 clear ,基本一个`clear-fix`就能搞定了。
300 |
301 | ### BFC
302 |
303 | BFC,block formatting context,跨级格式化上下文。如果一个元素触发了 BFC ,那其内部元素无论设置什么样式变化,都不会对元素外部产生影响。BFC 元素不能出现 margin 重叠,也不可能收到 float 的影响。能触发 BFC 的条件是:
304 |
305 | - ``跟元素
306 | - float 不是 none
307 | - overflow: auto/scroll/hidden
308 | - display: table-cell/table-caption/inline-block
309 | - position: fixed/absolute
310 |
311 | 即,只要符合以上条件之一,都不需要使用`clear:both`来清除浮动,因为 BFC 元素不会收到浮动影响布局。
312 |
313 | 一般用于触发 BFC 的条件是`overflow: hidden`,它简单好用又不会对布局产生影响。float 结合 BFC 可以写成:
314 |
315 | ```html
316 |
321 |
322 |

323 |
文字内容……
324 |
325 | ```
326 |
327 | ### absolute
328 |
329 | absolute 也具有破坏性和包裹性,这一点和 float 一样。absoute 还有一个重要的特性是**无依赖**,书中 184 页讲到,因为我之前了解过这块,因此就不再写了,但是确实很重要很常用。
330 |
331 | 另外,absolute 和 fixed 在和`overflow:hidden`一起使用时,可能会遇到各种无法隐藏的问题,因此不要一起混用。**如果遇到 absolute 和 fixed 元素需要裁剪时,可使用`clip`语法,不会出问题**。
332 |
333 | 最后,absolute 可体现流体特性,从一个垂直居中对齐即可体现,即结合`margin:auto`,上文已经写了这个 demo 了,书中 202 页有。
334 |
335 | ## 其他非“流”内容
336 |
337 | 其他和流体布局关系不大的内容,读来对我的印象没有那么深,用起来也不容易出现误解和问题,不重点关注了。
338 |
339 | ## 总结
340 |
341 | CSS 是“流”的世界,这包括:
342 |
343 | - 元素尺寸
344 | - 盒子模型
345 | - 内联元素
346 | - 流的破坏和保护(float、BFC、absolute)
347 |
348 | 而这,就是 CSS2.1 的最核心内容。
349 |
350 |
--------------------------------------------------------------------------------
/book/img/01/1.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangfupeng1988/read-notes/e578f900129d2f1eaae1806ecc2f7e3704c6d25a/book/img/01/1.webp
--------------------------------------------------------------------------------
/book/img/01/2.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangfupeng1988/read-notes/e578f900129d2f1eaae1806ecc2f7e3704c6d25a/book/img/01/2.webp
--------------------------------------------------------------------------------
/book/img/01/3.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangfupeng1988/read-notes/e578f900129d2f1eaae1806ecc2f7e3704c6d25a/book/img/01/3.webp
--------------------------------------------------------------------------------
/book/img/01/4.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangfupeng1988/read-notes/e578f900129d2f1eaae1806ecc2f7e3704c6d25a/book/img/01/4.webp
--------------------------------------------------------------------------------
/book/img/01/5.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangfupeng1988/read-notes/e578f900129d2f1eaae1806ecc2f7e3704c6d25a/book/img/01/5.webp
--------------------------------------------------------------------------------
/book/img/01/6.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangfupeng1988/read-notes/e578f900129d2f1eaae1806ecc2f7e3704c6d25a/book/img/01/6.webp
--------------------------------------------------------------------------------
/book/img/01/7.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangfupeng1988/read-notes/e578f900129d2f1eaae1806ecc2f7e3704c6d25a/book/img/01/7.webp
--------------------------------------------------------------------------------
/book/img/01/8.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangfupeng1988/read-notes/e578f900129d2f1eaae1806ecc2f7e3704c6d25a/book/img/01/8.webp
--------------------------------------------------------------------------------
/book/img/01/9.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangfupeng1988/read-notes/e578f900129d2f1eaae1806ecc2f7e3704c6d25a/book/img/01/9.webp
--------------------------------------------------------------------------------
/book/img/02/01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangfupeng1988/read-notes/e578f900129d2f1eaae1806ecc2f7e3704c6d25a/book/img/02/01.png
--------------------------------------------------------------------------------
/book/img/02/02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangfupeng1988/read-notes/e578f900129d2f1eaae1806ecc2f7e3704c6d25a/book/img/02/02.png
--------------------------------------------------------------------------------
/book/img/02/03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangfupeng1988/read-notes/e578f900129d2f1eaae1806ecc2f7e3704c6d25a/book/img/02/03.png
--------------------------------------------------------------------------------
/book/img/02/04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangfupeng1988/read-notes/e578f900129d2f1eaae1806ecc2f7e3704c6d25a/book/img/02/04.png
--------------------------------------------------------------------------------
/book/img/02/05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangfupeng1988/read-notes/e578f900129d2f1eaae1806ecc2f7e3704c6d25a/book/img/02/05.png
--------------------------------------------------------------------------------
/book/img/02/06.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangfupeng1988/read-notes/e578f900129d2f1eaae1806ecc2f7e3704c6d25a/book/img/02/06.png
--------------------------------------------------------------------------------
/book/img/02/07.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangfupeng1988/read-notes/e578f900129d2f1eaae1806ecc2f7e3704c6d25a/book/img/02/07.png
--------------------------------------------------------------------------------
/book/img/02/08.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangfupeng1988/read-notes/e578f900129d2f1eaae1806ecc2f7e3704c6d25a/book/img/02/08.png
--------------------------------------------------------------------------------
/book/img/02/09.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangfupeng1988/read-notes/e578f900129d2f1eaae1806ecc2f7e3704c6d25a/book/img/02/09.png
--------------------------------------------------------------------------------
/book/img/02/10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangfupeng1988/read-notes/e578f900129d2f1eaae1806ecc2f7e3704c6d25a/book/img/02/10.png
--------------------------------------------------------------------------------
/book/img/02/11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangfupeng1988/read-notes/e578f900129d2f1eaae1806ecc2f7e3704c6d25a/book/img/02/11.png
--------------------------------------------------------------------------------
/book/linux-screen常用命令.md:
--------------------------------------------------------------------------------
1 | # linux screen 常用命令
2 |
3 | 这并不是一本书的读书笔记。
4 |
5 | ## screen 外部
6 |
7 | - `screen ls`查看列表
8 | - `screen -r xxx`恢复 Detached 状态的 screen
9 | - `screen -d xxx`将 Attached 状态改为 Detached 状态,即踢掉之前的连接
10 | - `screen -S name`创建一个新的 screen
11 |
12 | ## screen 内部
13 |
14 | - `ctrl+a d`断开连接
15 | - `ctrl+a w`查看窗口列表
16 | - `ctrl+a
`切换不同的窗口,``为数字
17 | - `ctrl+a c`创建新窗口
18 | - `ctrl+a n`切换到下一个窗口,`ctrl+a p`切换到上一个窗口
19 | - `ctrl+a K`关闭窗口
20 | - `exit`退出窗口(当所有窗口都 exit 之后,该 screen 自动销毁掉)
21 |
22 | ## 分屏
23 |
24 | - `ctrl+a`然后输入`split`即可分屏,或者`ctrl+a S`
25 | - `ctrl+a tab`多屏切换
26 | - `ctrl+a X`关闭当前屏
27 | - `ctrl+a Q`关闭其他屏
28 |
29 |
30 |
--------------------------------------------------------------------------------
/book/vimtutor教程.md:
--------------------------------------------------------------------------------
1 | # vimtutor 教程
2 |
3 | 开始学习和使用 vim 编辑器,最简单的方式不是翻看各种教程、博客,而是在你的命令行中输入`vimtutor`命令,这样系统就会引导你去学习 vim 最常用的功能,其实这就是一本书。我现在根据这份 vimtutor 的教程,将 vim 操作重新整理,并且记录下。
4 |
5 | ## 第一讲
6 |
7 | - `k j h l` 上下左右移动光标
8 | - `w`移动到下一个单词开头,`e`移动到下一个单词结尾,`b`后退到上一个单词开头
9 | - `:q`退出,其中`:q!`不保存强制退出,`:wq`保存之后再退出
10 | - `x`删除光标处的字符。
11 | - `i`插入字符
12 | - `A`在该行的最后追加文本
13 | - 补充:ESC 进入 Normal 模式
14 |
15 | ## 第二讲
16 |
17 | - `dw`从光标处向右删除至下一个单词的开始,即删除掉当前单词的剩余部分以及空格
18 | - `de`从光标处向右删除至本单词的结束,不包括单词后面的空格
19 | - `d$`从光标处向右删除到该行的末尾
20 | - `d^`从光标处向左删除到改行的开始
21 | - 【总结以上】—— `d`是操作符(表示删除操作),后面的字母表示动作(删除哪些部分)
22 | - `0`(或者`^`)将光标移动到行首,`$`将光标移动到行尾
23 | - `2w`将光标向前移动两个单词,`3e`将光标向前移动到第三个单词的末尾。其中数字可以自己随意修改
24 | - `d2w`可向右删除两个单词,`d3e`可享有删除三个单词,数字可以自己随意修改。删除的区别参考`dw`和`de`
25 | - `dd`可以删除正好,`2dd`可以删除两个账号,数字可以自己随意修改
26 | - `u`撤销,`ctrl+r`重做。`U`恢复到**该行**的原始状态
27 |
28 | ## 第三讲
29 |
30 | - `p`粘贴
31 | - `r`替换光标所在位置的字符
32 | - `cw`和`ce`替换光标所在位置到单词末尾的字符
33 | - `c0`替换光标所在位置到行首的字符,`c$`即是到行尾
34 |
35 | ## 第四讲
36 |
37 | - `ctrl+g`显示当前光标所处的位置信息
38 | - `G`定位到文件最后一行,`gg`定位到文件第一行。输入行号,再输入`G`,可跳转到输入的行
39 | - `H`移动到文件开头,`M`移动到文件中间,`L`移动到文件末尾
40 | - `ctrl+d`下移半屏,`ctrl+u`上移半屏
41 | - `ctrl+e`向下滚动,`ctrl+y`线上滚动
42 | - `/`搜索字符串,`n`查看下一个,`N`查看上一个。反向查找用`?`
43 | - `ctrl+o`撤销光标定位,`ctrl+i`恢复光标定位
44 | - `%`匹配程序中的括号,如`{ } ( ) [ ]`
45 | - `:s/old/new`替换**该行**的第一个匹配文本。`:s/old/new/g`替换**该行**的所有匹配文本。`:%s/old/new/g`替换**整个文件**的所有匹配文本。`:%s/old/new/gc`替换**整个文件**的所有匹配文本,并且**挨个确认**
46 |
47 | ## 第五讲
48 |
49 | - `:!command`后面接入 shell 命令,可运行
50 | - `:w filename`可将内容保存到另一个文件中
51 | - `v`可进入选择模式,可选择部分文本。`V`选中一行
52 | - `:r filename` 插入外部文件
53 |
54 | ## 第六讲
55 |
56 | - `o`插入新的一行
57 | - `a`在光标之后插入文本(`i`是在光标之前)
58 | - `R`可联系替换多个字符
59 | - `y`复制内容,`yw`复制一个单词,`yy`复制一行(`v`可进入选择模式,`p`粘贴)
60 | - `:set xxx`设置选项
61 |
62 | ## 第七讲
63 |
64 | - `:help`获取帮助信息
65 |
66 | ## 补充
67 |
68 | - `:edit ./`选择编辑的文件,`i`切换显示模式,`-`返回上一层,R 重命名,D 删除
69 |
--------------------------------------------------------------------------------
/book/前端工程化体系设计和实践.md:
--------------------------------------------------------------------------------
1 | # 《前端工程化体系设计和实践》读书笔记
2 |
3 | 本书作者 [周俊鹏](https://github.com/zhoujunpeng) ,是 [boi](https://github.com/boijs/boi) 的作者。虽然 boi 这款前端构建工具 star 不是很多,但是不妨碍作者对前端工程化的深入和理解,毕竟术业有专攻。
4 |
5 | 不到一周时间(业余时间)草草看完本书,没太详细看细节,因为我平时工作基本用不到。阅读本书权当作为对前端工程化的一个统一的了解和认识,毕竟此前都是在零零散散的项目中接触,没体系的看过。
6 |
7 | 本书具有阅读价值的章节如下:
8 |
9 | - 第二章 脚手架
10 | - 第三章 构建
11 | - 第四章 本地开发服务器
12 | - 第五章 部署
13 |
14 | 光看以上的标题,基本也都涵盖了前端工程化的所有要点。因此,想要构建完整的知识体系,还是看书最快最有效。我也正好借助本书,来梳理一下**如果从零开始构建一个前端开发环境,都需要做哪些工作?**这是本文的最终目的。
15 |
16 | ----
17 |
18 | ## 第二章 脚手架
19 |
20 | 脚手架,即初始化项目环境的所有文件,例如 [create-react-app](https://github.com/facebook/create-react-app) 和 [vue-cli](https://github.com/vuejs/vue-cli) ,可以一键构建 React 和 vue 的开发环境。后续的构建、本地 server 、部署等步骤需要的文件、插件,都需要在脚手架初始化的时候都全部搞定。一次性使用,用完即弃。
21 |
22 | 至于什么好处、收益,书中写了不少,大体就是较少成本、减少配置云云,不再赘述。
23 |
24 | [Yeoman](https://github.com/yeoman/yeoman) 是 2012 年 Google I/O 大会发布的脚手架工具解决方案,它不能直接使用,而是提供了一套完整的脚手架开发的 API ,完全开放,高度可扩展。即可以借助 Yeoman 轻松开发自己的脚手架构建工具。
25 |
26 | 书中介绍了如何使用 Yeoman 开发一个脚手架,我没有详细看。后面如果自己遇到该类需求,再去查阅 Yeoman 文档。
27 |
28 | ----
29 |
30 | ## 第三章 构建
31 |
32 | 构建工具是前端工程化的核心部分,也是文章最大篇幅介绍的部分。
33 |
34 | ### 解决问题
35 |
36 | 构建,也叫做编译。就是将开发环境手写的代码,转换成能被浏览器(或者 nodejs)识别的代码的过程。除了语言转换之外,还要考虑一些性能、开发效率等相关的问题,例如文件合并、图片 base64 嵌入、文件名加 md5、路径识别等。记得之前看过 fis 文档中总结的前端构建工具的 [三种语言能力](https://github.com/fis-dev/fis/wiki/%E4%B8%89%E7%A7%8D%E8%AF%AD%E8%A8%80%E8%83%BD%E5%8A%9B),很有道理,如下:
37 |
38 | - 资源定位:获取任何开发中所使用资源的线上路径;
39 | - 内容嵌入:把一个文件的内容(文本)或者base64编码(图片)嵌入到另一个文件中;
40 | - 依赖声明:在一个文本文件内标记对其他资源的依赖关系;
41 |
42 | ### babel 和 PostCSS —— 使代码面向统一标准而非浏览器差异
43 |
44 | 接下来书中的内容都是介绍以下两点:
45 |
46 | - ES6 + Babel
47 | - CSS + PostCSS
48 |
49 | 大体读来,感觉作者在这两点很强调和赞同一个趋势 —— **第一,写代码应该向标准(ES6、CSS等)靠近,而不是在代码中屈就于浏览器兼容性;第二,构建工具用于抹平标准和浏览器兼容性的差异,但前提是不能妨碍标准。** 简单解释一下。
50 |
51 | 例如。我们可以在开发环境中写标准的 ES6 代码,babel 会编译成浏览器识别的 js 。我们可以在开发环境写标准的 css 代码,PostCSS 会编译成各个浏览器兼容的 css 。说到这里,**作者大赞 PostCSS 相比于 less sass 这些预编译工具的优点 —— 面向语言标准、而非面向浏览器差异**。所以称,PostCSS 是 CSS 的 babel 。
52 |
53 | 但是,构建工具在抹平过程中也不能掺杂自己私定的标准。例如,fis 在生成雪碧图的时候要求这样写 css
54 |
55 | ```css
56 | .icon_home { background-image: url('home.png?__sprite') }
57 | ```
58 |
59 | 很明显,这里的`?__sprite`,除了 fis 其他谁的都不认识它。**构建工具要服务于开发环境,而不能造成二次影响**。
60 |
61 | ### 模块化
62 |
63 | 模块化这部分主要讲了两件事儿:
64 |
65 | - **分模块异步加载** :AMD 本身支持异步加载,而 webpack 对 AMD 的支持并不好。不过在开发环境可以使用 CommonJS 和 ES Module ,虽然这两者标准上不支持异步加载,但是 webpack 可以通过`require.ensure`和`import()`函数来间接支持。(个人思考: webpack 的这种支持方式不是标准化,前端异步加载尽量使用 AMD 方式,至于如何借助工具实现这种方式,尚需调研……)
66 | - **使用缓存策略增量更新** :说白了就是打包出来的静态资源加上 hash 指纹,通过这种方式来清楚缓存。加 hash 指纹或者 md5 后缀是基本功能,所有的构建工具都支持。文章继续扩展,讲到了更加复杂的按需加载和增量更新的结合,提出了各种使用 webpack 具体解决方案,我并没有详细看。
67 |
68 | webpack 对于一部加载、分模块打包、按需加载等这些的配置,我暂时还没有搞明白,这算是自己有理论无实践的技术盲区。我觉得原因有两点:第一,webpack 配置复杂度确实太高;第二,自己没有真正理解这块的整体流程,因此看不透 —— 对于这种问题,只能抽专门时间针对性学习。
69 |
70 | **你可以不学甚至讨厌 webpack 如此复杂的配置文档,但是你必须掌握这部分实现原理和流程。**
71 |
72 | ### 资源定位
73 |
74 | 资源定位,即能识别资源之前的相互引用关系(如 html 引用了某些 js 和 css),以及根据引用关系确定打包之后的最终地址。例如,开发环境代码是`../static/xxx_hash.js`,发布之后就是`https://static.xxx.com/static/xxx_hash.js`,而且要把`xxx_hash.js`上传到 CDN server 端指定的位置。
75 |
76 | **webpack 的逆向注入模式**,即构建工具打包出`xxx_hash.js`之后再逆向插入到 html 模板中。如果按照正常的注入方式,在一开始就要往 html 模板中插入`')
461 | num++
462 | if (num === 2) {
463 | res.end()
464 | }
465 | })
466 | db.getData('sql2', function (err, data) {
467 | res.write('')
468 | num++
469 | if (num === 2) {
470 | res.end()
471 | }
472 | })
473 | })
474 | ```
475 |
476 | 这种多 pagelet 分批下发的方式,ajax 也可以办到。但是 ajax 每次都是一个独立的 http 请求,而 Bigpipe 共用相同的请求,开销十分小。
477 |
478 | ----
479 |
480 | ## 第九章 玩转进程
481 |
482 | 对应 nodejs API 中 [child_process](http://nodejs.cn/api/child_process.html) 和 [cluster](http://nodejs.cn/api/cluster.html) ,开源社区还有 [pm2](https://www.npmjs.com/package/pm2) 工具。
483 |
484 | ### 事件驱动
485 |
486 | **Apache 是采用多线程/多进程模型实现的**,当并发连接数量达到 10k 级别时,内存耗用问题就会暴露出来,这就是著名的 [C10K](http://www.kegel.com/c10k.html) 问题。**而 node 和 Nginx 都是采用事件驱动的方式**,采用单线程避免不必要的内容开销和上下文切换开销。
487 |
488 | 基于事件驱动主要涉及两个问题:
489 |
490 | - **CPU 利用率**。所有处理都是单线程的,影响时间驱动服务模型的根本在于 CPU 的计算能力,因此如何利用多核 CPU ?
491 | - **进程的健壮性**。PHP 中没有线程的概念,它的健壮性是每次请求都建立独立的上下文(线程),而对于 nodejs 所有请求都是统一的上下文,健壮性必须保证(即能自动修复、容错)。
492 |
493 | 另外,**考虑 nodejs 的特殊情况(只能使用部分内存,64 位最多使用 1.4GB ,32 位最多使用 0.7GB),开启多进程还可充分利用内存**。因为每个进程都是一个单独的 v8 实例,会重新分配内存,和其他进程不冲突。
494 |
495 | ### 创建子进程
496 |
497 | [child_process](http://nodejs.cn/api/child_process.html) 提供了创建子进程的方法
498 |
499 | - `spawn`
500 | - `exec`
501 | - `execFile`
502 | - `fork`
503 |
504 | ```js
505 | var cp = require('child_process')
506 | cp.spawn('node', ['worker.js'])
507 | cp.exec('node worker.js', function (err, stdout, stderr) {
508 | // todo
509 | })
510 | cp.execFile('worker.js', function (err, stdout, stderr) {
511 | // todo
512 | })
513 | cp.fork('./worker.js')
514 | ```
515 |
516 | 进程之间的通讯,代码如下。跟前端`WebWorker`类似,使用`on`监听,使用`send`发送。
517 |
518 | ```js
519 | // parent.js
520 | var cp = require('child_process')
521 | var n = cp.for('./sub.js')
522 | n.on('message', function (m) {
523 | console.log('PARENT got message: ' + m)
524 | })
525 | n.send({hello: 'workd'})
526 |
527 | // sub.js
528 | process.on('message', function (m) {
529 | console.log('CHILD got message: ' + m)
530 | })
531 | process.send({foo: 'bar'})
532 | ```
533 |
534 | ### 句柄传递
535 |
536 | 书中通过一个场景很直接的引出了这个问题,干净利落。即:使用上面的`fork`来启动多个进程监听 http 请求,这样会报监听端口冲突的问题。例如,一旦启动了一个进程监听 8080 端口,再想启动另一个进程监听 8080 端口的话,就会报错。那该如何解决这个问题?
537 |
538 | **node 从 v0.5.9 开始引入了进程之间发送句柄的功能**,`child.send(message, [sendHandle])`,后面那个可选的参数就是句柄。句柄可以是一个服务端 socket 对象、一个客户端 socket 对象,一个 UDP 套接字,一个管道等……(其实我没太看懂这里……)。具体的代码示例,可参考书中 243 页。
539 |
540 | 其实,这个问题通过后面的 Cluster 即可轻松解决。但是 **Cluster 也是借用的这里的句柄传递**,因此也要了解一点原理,虽然不会直接用。
541 |
542 | ### 稳定的集群
543 |
544 | 基本就是使用 Cluster ,cluster 模块允许设立一个主进程和若干个 worker 进程,由主进程监控和协调 worker 进程的运行。worker 之间采用进程间通信交换消息,**cluster模块内置一个负载均衡器,采用 Round-robin 算法协调各个 worker 进程之间的负载**。运行时,所有新建立的链接都由主进程完成,然后主进程再把 TCP 连接分配给指定的 worker 进程(即上文的句柄传递)。
545 |
546 | ```js
547 | const cluster = require('cluster')
548 | const os = require('os')
549 | const http = require('http')
550 |
551 | if (cluster.isMaster) {
552 | console.log('是主进程')
553 | const cpus = os.cpus() // cpu 信息
554 | const cpusLength = cpus.length // cpu 核数
555 | for (let i = 0; i < cpusLength; i++) {
556 | // fork() 方法用于新建一个 worker 进程,上下文都复制主进程。只有主进程才能调用这个方法
557 | // 该方法返回一个 worker 对象。
558 | cluster.fork()
559 | }
560 | } else {
561 | console.log('不是主进程')
562 | // 运行该 demo 之后,可以运行 top 命令看下 node 的进程数量
563 | // 如果电脑是 4 核 CPU ,会生成 4 个子进程,另外还有 1 个主进程,一共 5 个 node 进程
564 | // 其中, 4 个子进程受理 http-server
565 | http.createServer((req, res) => {
566 | res.writeHead(200)
567 | res.end('hello world')
568 | }).listen(8000) // 注意,这里就不会有端口冲突的问题了!!!
569 | }
570 | ```
571 |
572 | 维护进程健壮性,**通过 Cluster 能监听到进程退出,然后自动重启,即自动容错**。
573 |
574 | ```js
575 | if (cluster.isMaster) {
576 | const num = os.cpus().length
577 | console.log('Master cluster setting up ' + num + ' workers...')
578 | for (let i = 0; i < num; i++) {
579 | // 按照 CPU 核数,创建 N 个子进程
580 | cluster.fork()
581 | }
582 | cluster.on('online', worker => {
583 | // 监听 workder 进程上线(启动)
584 | console.log('worker ' + worker.process.pid + ' is online')
585 | })
586 | cluster.on('exit', (worker, code, signal) => {
587 | // 兼容 workder 进程退出
588 | console.log('worker ' + worker.process.pid + ' exited with code: ' + code + ' and signal: ' + signal)
589 | // 退出一个,即可立即重启一个
590 | console.log('starting a new workder')
591 | cluster.fork()
592 | })
593 | }
594 | ```
595 |
596 | 示例看似简单,但是实际应用还是尽量使用成熟的工具,例如 [pm2](https://www.npmjs.com/package/pm2)
597 |
598 | ----
599 |
600 | ## 第十章 测试
601 |
602 | 自动化单元测试,将单独整理,此处略过。
603 |
604 | ----
605 |
606 | ## 第十一章 产品化
607 |
608 | 按书中写的内容,我重新总结,应该分位三个层面:
609 |
610 | - 流量处理:负载均衡,CDN 等
611 | - 稳定监控:日志统计、监控内存 CPU、报警邮件等
612 | - 上线部署:构建、部署、上线
613 |
614 | -----
615 |
616 | ## 扩展 & 遗留问题
617 |
618 | - linux 标准输入输出
619 | - 异步流程控制库 [async](https://github.com/caolan/async) 和 [step](https://www.npmjs.com/package/step)
620 | - 异步并发控制的过载保护 [bagpipe](https://www.npmjs.com/package/bagpipe) (本书作者提供)
621 | - stream-handbook [英文原文](https://github.com/substack/stream-handbook) [中文翻译](https://github.com/jabez128/stream-handbook)
622 | - [《汇编语言入门 阮一峰》](https://news.cnblogs.com/n/587863/)
623 | - nodejs 接收文件上传(并写入系统临时文件夹)[formidable](https://www.npmjs.com/package/formidable)
624 | - nodejs 进程守候工具 [pm2](https://www.npmjs.com/package/pm2)
625 |
--------------------------------------------------------------------------------
/book/第三方javascript编程.md:
--------------------------------------------------------------------------------
1 | # 《第三方 javascript 编程》读书笔记
2 |
3 | 这并不是一本新书,阅读这本书的原因是由于我在工作中维护了几个 JSSDK ,感觉自己应该根据自身的精力去拜读一下这本书,毕竟本书的作者是大名鼎鼎的 [disqus](http://www.disqus.com) 工程师。disqus 在 2012 年 pv 就 50亿/月 ,可以说是世界上最具有技术话语权的 JSSDK。
4 |
5 | 本书讲解了开发一个外部使用的 JSSDK 将遇到的问题和解决方案。相比于 disqus 的实际情况,本书肯定只是简单的汇总了个“皮毛”,但是这对于 JSSDK 这一小众的技术方向,完全可以看成一个标杆性的书籍来阅读。
6 |
7 | 根据本书介绍,开发第三方使用的 JSSDK 面临的共性问题有:
8 |
9 | - 应用的分发和加载
10 | - HTML 和 CSS 的渲染
11 | - 与服务器通讯
12 | - 跨域 iframe 通讯
13 | - 验证和会话
14 |
15 | 书中其他的内容并不特殊,即并不是 JSSDK 特有,属于共性问题,也没什么难点,就此略过。另外,除了专门针对 SDK 以外,想要了解跨域、iframe 相关知识的同学,也应该阅读本书。
16 |
17 | ----
18 |
19 | ## 应用的分发和加载
20 |
21 | 读来总结以下要点。
22 |
23 | ### 无阻塞加载脚本
24 |
25 | 使用`defer`(html4 标准)和`async`(html5 标准)都可以无阻塞(不阻塞页面的加载)加载脚本,例如``。**但是首推使用`async`,因为这样会是 js 的执行更快。** 总结一下两者的异同:
26 |
27 | - 相同:不阻塞页面的加载
28 | - 不同:`async`下载完立刻执行,`defer`加载的 js 要等待页面加载、解析完之后再顺序执行
29 |
30 | **注意,使用`async`, js 执行如果有 DOM 操作,需待 DOM Ready 之后。**
31 |
32 | ```html
33 |
34 |
35 | ```
36 |
37 | ### 动态脚本插入
38 |
39 | 即“小拖大”、“静拖动”,直接看代码即可。这份代码在实际工作中用到了可直接拷贝过来使用,因此先整理总结下来。
40 |
41 | ```html
42 |
64 | ```
65 |
66 | ### 参数传递
67 |
68 | 书中总结了好几种,但是我觉得比较可用的就是两种:第一,传递 url 参数;第二,初始化时配置。
69 |
70 | 传递 url 参数例如加载 js 时直接在 url 中带有参数,例如``。这样,server 可以获取到`id`然后动态拼接 js 内容,不过这不是一个靠谱的方案,因为 js 一般都会作为静态文件放在 CDN 上,不会动态生成。还有一种方式就是前端识别
71 |
72 | ```js
73 | function getMyAppId() {
74 | var scripts = document.getElementsByTagName('script')
75 | var el, src, i, length = scripts.length
76 | for (i = 0; i < length; i++) {
77 | el = scripts[i]
78 | src = el.src
79 | /*
80 | 接下来,再分析 src 中是否有 myapp-id=100 格式的参数,即可
81 | */
82 | }
83 | }
84 | ```
85 |
86 | 初始化配置就更加简单了,例如[微信 JSSDK](https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115) 初始化的时候要传入`appid`一样。
87 |
88 | ----
89 |
90 | ## HTML 和 CSS 的渲染
91 |
92 | ### 定位 DOM
93 |
94 | 如何选中操作的 DOM 节点,书中介绍了一些常规方法,无非是通过 id 属性 class 等获取。还有一种是将`