├── img ├── flex02.png ├── git-local.png ├── js2016-1.jpg ├── js2016-2.jpg ├── js2016-3.jpg ├── js2016-4.jpg ├── js2016-5.jpg ├── js2016-6.jpg ├── js2016-7.jpg ├── js2016-8.jpg ├── koa-onion.png ├── web-fetch.png ├── flexremsize.jpeg └── git-remote.png ├── .vscode ├── settings.json └── tasks.json ├── .gitignore ├── gulpfile.js ├── package.json ├── bower.md ├── README.md ├── html ├── css │ ├── prettify.css │ └── markdown.css ├── README.html ├── babel.html ├── vscode2.html ├── vscode.html ├── js2016.html ├── js │ └── prettify.js ├── eslint2.html ├── WebStorm.html └── eslint.html ├── vscode.md ├── LICENSE ├── weui.md ├── js2016.md ├── flex.md ├── webpack.md ├── eslint.md ├── npm.md ├── WebStorm.md └── Jade.md /img/flex02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nydl/devnote/HEAD/img/flex02.png -------------------------------------------------------------------------------- /img/git-local.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nydl/devnote/HEAD/img/git-local.png -------------------------------------------------------------------------------- /img/js2016-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nydl/devnote/HEAD/img/js2016-1.jpg -------------------------------------------------------------------------------- /img/js2016-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nydl/devnote/HEAD/img/js2016-2.jpg -------------------------------------------------------------------------------- /img/js2016-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nydl/devnote/HEAD/img/js2016-3.jpg -------------------------------------------------------------------------------- /img/js2016-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nydl/devnote/HEAD/img/js2016-4.jpg -------------------------------------------------------------------------------- /img/js2016-5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nydl/devnote/HEAD/img/js2016-5.jpg -------------------------------------------------------------------------------- /img/js2016-6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nydl/devnote/HEAD/img/js2016-6.jpg -------------------------------------------------------------------------------- /img/js2016-7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nydl/devnote/HEAD/img/js2016-7.jpg -------------------------------------------------------------------------------- /img/js2016-8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nydl/devnote/HEAD/img/js2016-8.jpg -------------------------------------------------------------------------------- /img/koa-onion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nydl/devnote/HEAD/img/koa-onion.png -------------------------------------------------------------------------------- /img/web-fetch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nydl/devnote/HEAD/img/web-fetch.png -------------------------------------------------------------------------------- /img/flexremsize.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nydl/devnote/HEAD/img/flexremsize.jpeg -------------------------------------------------------------------------------- /img/git-remote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nydl/devnote/HEAD/img/git-remote.png -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // 将设置放入此文件中以覆盖默认值和用户设置。 2 | { 3 | "markdown.styles": [ 4 | "file:///Users/way/prj/devlog/css/markdown.css" 5 | // "file:///Users/way/prj/devlog/css/prettify.css" 6 | ] 7 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "0.1.0", 5 | "command": "gulp", 6 | "isShellCommand": true, 7 | "tasks": [{ 8 | "taskName": "default", 9 | "isBuildCommand": true, 10 | "showOutput": "always", 11 | "isWatching": true 12 | }], 13 | "showOutput": "always" 14 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Node rules: 2 | ## Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 3 | .grunt 4 | 5 | ## Dependency directory 6 | ## Commenting this out is preferred by some people, see 7 | ## https://docs.npmjs.com/misc/faq#should-i-check-my-node_modules-folder-into-git 8 | node_modules 9 | 10 | # Book build output 11 | _book 12 | 13 | # eBook build output 14 | *.epub 15 | *.mobi 16 | *.pdf 17 | .DS_Store 18 | node_modules 19 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | 2 | var gulp = require('gulp'); 3 | var markdown = require('gulp-markdown'); 4 | 5 | // 执行转换任务 6 | gulp.task('markdown', function() { 7 | return gulp.src('**/*.md') 8 | .pipe(markdown()) 9 | // 统一转换到 html 目录 10 | .pipe(gulp.dest('html')); 11 | // 原目录转换 12 | // .pipe(gulp.dest(function(f) { 13 | // return f.base; 14 | // })); 15 | }); 16 | 17 | // 缺省任务 18 | gulp.task('default', function() { 19 | // 对所有 md 文件进行监视,发现修改自动执行 转换任务! 20 | gulp.watch('**/*.md', ['markdown']); 21 | }); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "devnote", 3 | "version": "1.0.0", 4 | "description": "dev note", 5 | "main": "gulpfile.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/nydl/devnote.git" 12 | }, 13 | "keywords": [ 14 | "node.js", 15 | "koa" 16 | ], 17 | "author": "walter", 18 | "license": "ISC", 19 | "bugs": { 20 | "url": "https://github.com/nydl/devnote/issues" 21 | }, 22 | "homepage": "https://github.com/nydl/devnote#readme", 23 | "devDependencies": { 24 | "gulp": "^3.9.1", 25 | "gulp-markdown": "^1.2.0" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /bower.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | bower 12 | ===== 13 | 14 | >Bower是一个客户端技术的软件包管理器,它可用于搜索、安装和卸载如JavaScript、HTML、CSS之类的网络资源。其他一些建立在Bower基础之上的开发工具,如YeoMan和Grunt,这个会在以后的文章中介绍。 15 | 16 | >一个新的web项目开始,我们总是很自然地去下载需要用到的js类库文件,比如jQuery,去官网下载名为jquery-1.10.2.min.js文件,放到我们的项目里。当项目又需要bootstrap的时候,我们会重复刚才的工作,去bootstrap官网下载对应的类库。如果bootstrap所依赖的jQuery并不是1.10.2,而是2.0.3时,我们会再重新下载一个对应版本的jQuery替换原来的。 17 | 18 | >包管理是个复杂的问题,我们要知道谁依赖谁,还要明确哪个版本依赖哪个版本。这些对于开发人员来说,负担过重了。bower作为一个js依赖管理的工具,提供一种理想包管理方式,借助了npm的一些思想,为我们提供一个舒服的开发环境。 19 | 20 | ## 21 | 22 | - https://segmentfault.com/a/1190000002971135 23 | - http://www.zhihu.com/question/24414899 24 | - https://cnodejs.org/topic/5210b7a80a746c580b11e496 25 | 26 | ## 安装bower 27 | 28 | 使用npm,打开终端,输入: 29 | `npm install -g bower` 30 | 其中-g命令表示全局安装 31 | 32 | 作者:尤雨溪 33 | 链接:http://www.zhihu.com/question/24414899/answer/28021471 34 | 来源:知乎 35 | 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 36 | 37 | npm + Browserify 38 | 39 | 我这里想要指出,npm 其实是一个非常好的前端(对,没错,是前端)包管理方案,最主要的就是依靠 Browserify 这个神器。Browserify 最大的意义不是让你能在 npm 上发布前端的静态资源,而是实现前后端的代码共享。npm上有很多包是前后端通用的,比如我要找个现成的算法实现,什么 levenshtein distance 啊,perlin noise 啊,gaussian distribution 啊,A* 寻路啊,npm 上一搜一大把。常用的库如 jquery backbone 之类的,只要你想得到的基本上都有 npm 版本。需要什么直接 npm install 就可以用在浏览器端的项目里了,Component 和 Bower 在这方面跟 npm 完全没有可比性,spm 就更不提了。开发流程上来说也极其省心,项目用 CommonJS 写,不需要任何配置,给一个入口文件就行!还有一个官方工具 watchify,一行命令跑起,保存文件自动构建,连 grunt gulp 都不需要。 40 | 41 | 这个方案唯一的缺点,就是 npm 的树状依赖结构可能导致重复的模块和代码量的臃肿,需要跑一次 `npm dedupe` 来尽量压平依赖树。当然,实际情况中前端模块出现依赖同一模块的不兼容版本还是很少见的。 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 诺亚大陆系统开发技术笔记 2 | 3 | 开发一套大型系统社交+电商系统,涉及前端(ios、安卓、pc、微信)、后台、接口、数据库、缓存、负载均衡、集群等方方面面的知识和技能。 4 | 我们将开发中所涉及的技能、知识、思想记录并整理出来,将其中承载的价值分享、传播给更多人。 5 | 如果你想成为一名全栈或某一方面的编程高手,请跟着我们一起探索、前进。 6 | 7 | > * 如果你是研发高手,请跟我们一起完善笔记,让更多的人掌握这些技能 8 | > * 如果你是研发小白,请跟着我们前进,成为全栈高手 9 | > * 无论你是初中、高中、大专、本科毕业,只要对编程有强烈兴趣,请跟着我们前进,成为全栈高手 10 | > * 我们的CEO14岁时创建诺亚大陆,研发团队有初中、高中、大专毕、本科毕业生,我们对学历没有偏见 11 | > * 相信自己,就能创造奇迹,请跟着我们前进,做更好的自己 12 | > * 本笔记是各种技术简要记录,内容来源于网络及研发人员个人观点,仅供参考 13 | > * 如果你觉得对你有用,请使用微信关注 “诺亚大陆” 公众号,参与诺亚大陆的建设 14 | 15 | ## 笔记清单 16 | 17 | - [js 2016 发展趋势必读](https://github.com/nydl/devnote/blob/master/js2016.md) 18 | - [koa 2.0 node.js的web服务框架](https://github.com/nydl/devnote/blob/master/koa.md) 19 | - 离线 html 浏览,html目录增加了 html、css、js 文件,脱离github环境可直接打开 html文件浏览 20 | - [Visual Studio Code使用](https://github.com/nydl/devnote/blob/master/vscode.md) 21 | - [git 最好的代码版本管理](https://github.com/nydl/devnote/blob/master/git.md) 22 | - [mongoDB 最具代表的NoSql非关系数据库](https://github.com/nydl/devnote/blob/master/mongoDB.md) 23 | - [mongoose mongoDB的最佳ODM封装](https://github.com/nydl/devnote/blob/master/mongoose.md) 24 | 25 | ## markdown 编写工具 26 | 27 | - [Visual Studio Code] 跨平台,微软良心作品,非常棒!无需安装插件支持markdown。 28 | - [Sublime Text] 不错,需注册,需安装markdown插件 29 | - [ATOM] 跨平台,不错,但是太慢、太卡,资源消耗大,用起来不是特别爽 30 | - [MacDown](http://macdown.uranusjr.com) Mac OS,苹果操作系统,对列表里面的代码块没有正确识别! 31 | - [简书](http://www.jianshu.com) 目前使用比较多的在线工具,免费需注册! 32 | - [Cmd Markdown](https://www.zybuluo.com/mdeditor) 有在线及客户端,基本功能免费,界面不错,tab无法设置! 33 | - [dillinger](http://dillinger.io)国外的在线工具 34 | - 源代码显示 35 | - 代码部分,顶格没有问题,如果在列表中,不是顶格,则中间或最后必须有空行,否则不作为代码显示! 36 | - 按语法规范,4个空格或一个tab都作为代码处理,实际上,github 要求中间必须空一行才行,一般在最后空行。 37 | - 如果设置为tab自动转为2个空格,理论上不作为代码,实际上还是能识别为代码。 38 | - vs code默认自动将tab转空格,如果保留tab,缩进的代码在编辑时,不能自动识别为代码 39 | 40 | 41 | --- 42 | 43 | Creative Commons License 44 |
本作品采用知识共享署名-非商业性使用 3.0 中国大陆许可协议进行许可。 45 | -------------------------------------------------------------------------------- /html/css/prettify.css: -------------------------------------------------------------------------------- 1 | .pln{color:#000} 2 | @media screen{.str{color:#080} 3 | .kwd{color:#008} 4 | .com{color:#800} 5 | .typ{color:#606} 6 | .lit{color:#066} 7 | .pun,.opn,.clo{color:#660} 8 | .prettyprint .tag{color:#008} 9 | .atn{color:#606} 10 | .atv{color:#080} 11 | .dec,.var{color:#606} 12 | .fun{color:red} 13 | } 14 | @media print,projection{ 15 | .str{color:#060} 16 | .kwd{color:#006;font-weight:bold} 17 | .com{color:#600;font-style:italic} 18 | .typ{color:#404;font-weight:bold} 19 | .lit{color:#044} 20 | .pun,.opn,.clo{color:#440} 21 | .prettyprint .tag{color:#006;font-weight:bold} 22 | .atn{color:#404} 23 | .atv{color:#060} 24 | } 25 | pre.prettyprint{padding:2px;border:1px solid #888} 26 | ol.linenums{margin-top:0;margin-bottom:0} 27 | li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none} 28 | li.L1,li.L3,li.L5,li.L7,li.L9{background:none;} 29 | .prettyprint, 30 | pre.prettyprint { 31 | background-color: #272822; 32 | border: none; 33 | overflow: hidden; 34 | padding: 10px 15px; 35 | } 36 | .prettyprint.linenums, 37 | pre.prettyprint.linenums { 38 | -webkit-box-shadow: inset 40px 0 0 #39382E, inset 41px 0 0 #464741; 39 | -moz-box-shadow: inset 40px 0 0 #39382E, inset 41px 0 0 #464741; 40 | box-shadow: inset 40px 0 0 #39382E, inset 41px 0 0 #464741; 41 | } 42 | .prettyprint.linenums ol, 43 | pre.prettyprint.linenums ol { 44 | margin: 0 0 0 30px; 45 | padding:0; 46 | } 47 | .prettyprint.linenums ol li, 48 | pre.prettyprint.linenums ol li { 49 | text-indent:0; 50 | padding-left: 12px; 51 | color: #bebec5; 52 | line-height: 20px; 53 | margin-left: 0; 54 | list-style: decimal; 55 | margin-bottom: 0; 56 | word-wrap:break-word; 57 | } 58 | .prettyprint *{font-family:'courier new',monospace;} 59 | .prettyprint .com { color: #93a1a1; } 60 | .prettyprint .lit { color: #AE81FF; } 61 | .prettyprint .pun, 62 | .prettyprint .opn, 63 | .prettyprint .clo { color: #F8F8F2; } 64 | .prettyprint .fun { color: #dc322f; } 65 | .prettyprint .str, 66 | .prettyprint .atv { color: #E6DB74; } 67 | .prettyprint .kwd, 68 | .prettyprint .tag { color: #F92659; } 69 | .prettyprint .typ, 70 | .prettyprint .atn, 71 | .prettyprint .dec, 72 | .prettyprint .var { color: #A6E22E; } 73 | .prettyprint .pln { color: #66D9EF; } 74 | -------------------------------------------------------------------------------- /html/README.html: -------------------------------------------------------------------------------- 1 |

诺亚大陆系统开发技术笔记

2 |

开发一套大型系统社交+电商系统,涉及前端(ios、安卓、pc、微信)、后台、接口、数据库、缓存、负载均衡、集群等方方面面的知识和技能。 3 | 我们将开发中所涉及的技能、知识、思想记录并整理出来,将其中承载的价值分享、传播给更多人。
如果你想成为一名全栈或某一方面的编程高手,请跟着我们一起探索、前进。

4 |
5 | 14 |
15 |

笔记清单

16 | 25 |

markdown 编写工具

26 | 42 |
43 |

44 | Creative Commons License 45 |
本作品采用知识共享署名-非商业性使用 3.0 中国大陆许可协议进行许可。

46 | -------------------------------------------------------------------------------- /vscode.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | VS Code 13 | ======= 14 | 15 | 最好用的跨平台文本编辑器,推荐使用。 16 | 17 | ## 特点 18 | 19 | - 跨平台,开源,免费,启动非常快,目录作为项目管理,集成 git版本管理,使用 node 作为外部任务,能打开大文件,并且编辑不卡顿 20 | - 是目前发现**最好用的编辑器**,之前使用的 Sublime、Pad ++ 等都不用了! 21 | - 同步预览:拆分 md文件,在拆分的文件上点击右上角预览,或者使用 cmd+shift+v 切换到预览视图,即可同步预览。 22 | - tab设置:编辑器似乎能跟踪每个文件的tab设置,如果一个文件开始设置tab自动转空格,用户设置tab改为不转空格, 23 | 新的设置对原来编辑过的文件不起作用,非常神奇,不知道是bug还是一个特色功能。 24 | 需要变更 tab 设置,只能将原文件更名,新建一个,拷贝文本过来! 25 | 26 | ## Markdown 转 html 27 | 28 | 1. npm install -g marked 29 | 2. Create tasks.json 30 | F1 and type in 'Configure Task Runner', press Enter to select it. 31 | Select Others. 32 | tasks.json : 33 | ```js 34 | { 35 | // See http://go.microsoft.com/fwlink/?LinkId=733558 36 | // for the documentation about the tasks.json format 37 | "version": "0.1.0", 38 | "command": "echo", 39 | "isShellCommand": true, 40 | "args": ["Hello World"], 41 | "showOutput": "always" 42 | } 43 | 44 | we change the contents as follows: 45 | { 46 | // See http://go.microsoft.com/fwlink/?LinkId=733558 47 | // for the documentation about the tasks.json format 48 | "version": "0.1.0", 49 | "command": "marked", 50 | "isShellCommand": true, 51 | "args": ["sample.md", "-o", "sample.html"], 52 | "showOutput": "always" 53 | } 54 | ``` 55 | Use ⌃Space to see the available settings. 56 | 3. Run the Build Task 57 | As this is the only task in the file, you can execute it by simply pressing ⇧⌘B (Run Build Task). 58 | 59 | ## Markdown 批量转 html 60 | 61 | 1. 安装任务执行环境 62 | ```js 63 | npm i -g gulp-cli 64 | npm i gulp -D 65 | npm i gulp-markdown -D 66 | 67 | ``` 68 | 2. 创建 Gulp 任务 gulpfile.js,也就是用js编写的类似 bat、cmd一样的批量处理执行脚本 69 | ```js 70 | var gulp = require('gulp'); 71 | var markdown = require('gulp-markdown'); 72 | 73 | // 执行转换任务 74 | gulp.task('markdown', function() { 75 | return gulp.src('**/*.md') 76 | .pipe(markdown()) 77 | // 统一转换到 html 目录 78 | .pipe(gulp.dest('html')); 79 | // 原目录转换 80 | // .pipe(gulp.dest(function(f) { 81 | // return f.base; 82 | // })); 83 | }); 84 | 85 | // 缺省任务 86 | gulp.task('default', function() { 87 | // 对所有 md 文件进行监视,发现修改自动执行 转换任务! 88 | gulp.watch('**/*.md', ['markdown']); 89 | }); 90 | 91 | ``` 92 | 运行 gulp markdown,所有md文件被批量转换到html目录! 93 | 3. 修改 tasks.json 文件,对 md 文件进行监视 94 | set a watch on the default Gulp task we just created. 95 | ```js 96 | { 97 | "version": "0.1.0", 98 | "command": "gulp", 99 | "isShellCommand": true, 100 | "tasks": [{ 101 | "taskName": "default", 102 | "isBuildCommand": true, 103 | "showOutput": "always", 104 | "isWatching": true 105 | }] 106 | } 107 | 108 | ``` 109 | 4. 运行 gulp Build 任务 110 | ⇧⌘B (Run Build Task),md文件修改后,自动转换为 html文件。 111 | 并且在状态栏左下角有个同步的圆形图标,点击可完成同步! 112 | 5. 停止 自动监视任务 113 | 重新 ⇧⌘B,会弹出 “终止运行中的任务”,点击终止即可! 114 | 或者 点击 F1,输入 >terminate Running Task,回车即可! 115 | 116 | ## 插件管理 117 | 118 | - [**插件网址**:]https://marketplace.visualstudio.com/VSCode 119 | - **已安装插件**:cmd+p,输入 ext+空格,即可浏览所安装的插件,点击 x 即可卸载 120 | - **安装插件**:ext install xxx 安装插件 121 | - **更新插件**:ext update 更新插件 122 | 123 | ## 推荐插件 124 | 125 | - ext install beautify 126 | js、css、html、json 格式化插件,推荐使用! 127 | 按F1,在命令行输入 beautify,执行即可将当前文本自动格式化! 128 | - ext install vscode-eslint 129 | 代码规范提示 130 | - ext install JavaScriptSnippets 131 | js 关键字缩写 132 | - ext install jshint 133 | js 输入提示 134 | - [Markdown-TOC](https://github.com/AlanWalk/Markdown-TOC) 135 | 136 | -------------------------------------------------------------------------------- /html/babel.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |

babel

12 |

一款功能强大的js编译(转换)器,能将ES7、ES6编译(转换)为ES5、ES6。

13 |
14 |

babel 6 将功能分拆为很多插件,可以自由组合。如果嫌麻烦,可以直接使用预设(presets)好的插件包。比如:es2015、react。刚开始可能被 babel 晃得不明所以,本质上就是一个转码工具,类似编译器。复杂就是插件化,很多插件让你不知所措。
插件化虽然增加了选择成本,但使得babel发展更快,功能跟强大!
babel 实在太强大了,强大得令 type script 失色!coffee script、dark 彻底退出历史舞台。

15 |
16 |

官网 17 | 插件

18 |

安装

19 | 61 |

使用

62 | 80 |

babel 与 ES6的兼容性问题

81 | 94 |

相关资源

95 | 101 | -------------------------------------------------------------------------------- /html/vscode2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |

VS Code

12 |

最好用的跨平台文本编辑器,推荐使用。

13 |

特点

14 | 21 |

Markdown 转 html

22 |
    23 |
  1. npm install -g marked
  2. 24 |
  3. Create tasks.json
    F1 and type in 'Configure Task Runner', press Enter to select it. 25 | Select Others. 26 | tasks.json :

    27 |
     {
     28 |      // See http://go.microsoft.com/fwlink/?LinkId=733558
     29 |      // for the documentation about the tasks.json format
     30 |      "version": "0.1.0",
     31 |      "command": "echo",
     32 |      "isShellCommand": true,
     33 |      "args": ["Hello World"],
     34 |      "showOutput": "always"
     35 |  }
     36 | 
     37 |  we change the contents as follows:  
     38 |  {
     39 |      // See http://go.microsoft.com/fwlink/?LinkId=733558
     40 |      // for the documentation about the tasks.json format
     41 |      "version": "0.1.0",
     42 |      "command": "marked",
     43 |      "isShellCommand": true,
     44 |      "args": ["sample.md", "-o", "sample.html"],
     45 |      "showOutput": "always"
     46 |  }
     47 | 
    48 |

    Use ⌃Space to see the available settings.

    49 |
  4. 50 |
  5. Run the Build Task
    As this is the only task in the file, you can execute it by simply pressing ⇧⌘B (Run Build Task).
  6. 51 |
52 |

Markdown 批量转 html

53 |
    54 |
  1. 安装任务执行环境

    55 |
     npm i -g gulp-cli
     56 |  npm i gulp -D
     57 |  npm i gulp-markdown -D
     58 | 
    59 |
  2. 60 |
  3. 创建 Gulp 任务 gulpfile.js,也就是用js编写的类似 bat、cmd一样的批量处理执行脚本

    61 |
     var gulp = require('gulp');
     62 |  var markdown = require('gulp-markdown');
     63 | 
     64 |  // 执行转换任务
     65 |  gulp.task('markdown', function() {
     66 |      return gulp.src('**/*.md')
     67 |          .pipe(markdown())
     68 |          // 统一转换到 html 目录
     69 |          .pipe(gulp.dest('html'));
     70 |          // 原目录转换
     71 |          // .pipe(gulp.dest(function(f) {
     72 |          //         return f.base;
     73 |          // }));    
     74 |  });
     75 | 
     76 |  // 缺省任务
     77 |  gulp.task('default', function() {
     78 |      // 对所有 md 文件进行监视,发现修改自动执行 转换任务!
     79 |      gulp.watch('**/*.md', ['markdown']);
     80 |  });
     81 | 
    82 |

    运行 gulp markdown,所有md文件被批量转换到html目录!

    83 |
  4. 84 |
  5. 修改 tasks.json 文件,对 md 文件进行监视 85 | set a watch on the default Gulp task we just created.

    86 |
     {
     87 |  "version": "0.1.0",
     88 |  "command": "gulp",
     89 |  "isShellCommand": true,
     90 |  "tasks": [{
     91 |          "taskName": "default",
     92 |          "isBuildCommand": true,
     93 |          "showOutput": "always",
     94 |          "isWatching": true
     95 |      }]
     96 |  }
     97 | 
    98 |
  6. 99 |
  7. 运行 gulp Build 任务 100 | ⇧⌘B (Run Build Task),md文件修改后,自动转换为 html文件。
    并且在状态栏左下角有个同步的圆形图标,点击可完成同步!
  8. 101 |
  9. 停止 自动监视任务 102 | 重新 ⇧⌘B,会弹出 “终止运行中的任务”,点击终止即可! 103 | 或者 点击 F1,输入 >terminate Running Task,回车即可!
  10. 104 |
105 |

插件管理

106 | 112 |

推荐插件

113 | 123 | -------------------------------------------------------------------------------- /html/vscode.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |

VS Code

12 |

最好用的跨平台文本编辑器,推荐使用。

13 |

特点

14 | 21 |

Markdown 转 html

22 |
    23 |
  1. npm install -g marked
  2. 24 |
  3. Create tasks.json
    F1 and type in 'Configure Task Runner', press Enter to select it. 25 | Select Others. 26 | tasks.json :

    27 |
     {
     28 |      // See http://go.microsoft.com/fwlink/?LinkId=733558
     29 |      // for the documentation about the tasks.json format
     30 |      "version": "0.1.0",
     31 |      "command": "echo",
     32 |      "isShellCommand": true,
     33 |      "args": ["Hello World"],
     34 |      "showOutput": "always"
     35 |  }
     36 | 
     37 |  we change the contents as follows:  
     38 |  {
     39 |      // See http://go.microsoft.com/fwlink/?LinkId=733558
     40 |      // for the documentation about the tasks.json format
     41 |      "version": "0.1.0",
     42 |      "command": "marked",
     43 |      "isShellCommand": true,
     44 |      "args": ["sample.md", "-o", "sample.html"],
     45 |      "showOutput": "always"
     46 |  }
     47 | 
    48 |

    Use ⌃Space to see the available settings.

    49 |
  4. 50 |
  5. Run the Build Task
    As this is the only task in the file, you can execute it by simply pressing ⇧⌘B (Run Build Task).
  6. 51 |
52 |

Markdown 批量转 html

53 |
    54 |
  1. 安装任务执行环境

    55 |
     npm i -g gulp-cli
     56 |  npm i gulp -D
     57 |  npm i gulp-markdown -D
     58 | 
    59 |
  2. 60 |
  3. 创建 Gulp 任务 gulpfile.js,也就是用js编写的类似 bat、cmd一样的批量处理执行脚本

    61 |
     var gulp = require('gulp');
     62 |  var markdown = require('gulp-markdown');
     63 | 
     64 |  // 执行转换任务
     65 |  gulp.task('markdown', function() {
     66 |      return gulp.src('**/*.md')
     67 |          .pipe(markdown())
     68 |          // 统一转换到 html 目录
     69 |          .pipe(gulp.dest('html'));
     70 |          // 原目录转换
     71 |          // .pipe(gulp.dest(function(f) {
     72 |          //         return f.base;
     73 |          // }));    
     74 |  });
     75 | 
     76 |  // 缺省任务
     77 |  gulp.task('default', function() {
     78 |      // 对所有 md 文件进行监视,发现修改自动执行 转换任务!
     79 |      gulp.watch('**/*.md', ['markdown']);
     80 |  });
     81 | 
    82 |

    运行 gulp markdown,所有md文件被批量转换到html目录!

    83 |
  4. 84 |
  5. 修改 tasks.json 文件,对 md 文件进行监视 85 | set a watch on the default Gulp task we just created.

    86 |
     {
     87 |  "version": "0.1.0",
     88 |  "command": "gulp",
     89 |  "isShellCommand": true,
     90 |  "tasks": [{
     91 |          "taskName": "default",
     92 |          "isBuildCommand": true,
     93 |          "showOutput": "always",
     94 |          "isWatching": true
     95 |      }]
     96 |  }
     97 | 
    98 |
  6. 99 |
  7. 运行 gulp Build 任务 100 | ⇧⌘B (Run Build Task),md文件修改后,自动转换为 html文件。
    并且在状态栏左下角有个同步的圆形图标,点击可完成同步!
  8. 101 |
  9. 停止 自动监视任务 102 | 重新 ⇧⌘B,会弹出 “终止运行中的任务”,点击终止即可! 103 | 或者 点击 F1,输入 >terminate Running Task,回车即可!
  10. 104 |
105 |

插件管理

106 | 112 |

推荐插件

113 | 124 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | CC0 1.0 Universal 2 | 3 | Statement of Purpose 4 | 5 | The laws of most jurisdictions throughout the world automatically confer 6 | exclusive Copyright and Related Rights (defined below) upon the creator and 7 | subsequent owner(s) (each and all, an "owner") of an original work of 8 | authorship and/or a database (each, a "Work"). 9 | 10 | Certain owners wish to permanently relinquish those rights to a Work for the 11 | purpose of contributing to a commons of creative, cultural and scientific 12 | works ("Commons") that the public can reliably and without fear of later 13 | claims of infringement build upon, modify, incorporate in other works, reuse 14 | and redistribute as freely as possible in any form whatsoever and for any 15 | purposes, including without limitation commercial purposes. These owners may 16 | contribute to the Commons to promote the ideal of a free culture and the 17 | further production of creative, cultural and scientific works, or to gain 18 | reputation or greater distribution for their Work in part through the use and 19 | efforts of others. 20 | 21 | For these and/or other purposes and motivations, and without any expectation 22 | of additional consideration or compensation, the person associating CC0 with a 23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright 24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work 25 | and publicly distribute the Work under its terms, with knowledge of his or her 26 | Copyright and Related Rights in the Work and the meaning and intended legal 27 | effect of CC0 on those rights. 28 | 29 | 1. Copyright and Related Rights. A Work made available under CC0 may be 30 | protected by copyright and related or neighboring rights ("Copyright and 31 | Related Rights"). Copyright and Related Rights include, but are not limited 32 | to, the following: 33 | 34 | i. the right to reproduce, adapt, distribute, perform, display, communicate, 35 | and translate a Work; 36 | 37 | ii. moral rights retained by the original author(s) and/or performer(s); 38 | 39 | iii. publicity and privacy rights pertaining to a person's image or likeness 40 | depicted in a Work; 41 | 42 | iv. rights protecting against unfair competition in regards to a Work, 43 | subject to the limitations in paragraph 4(a), below; 44 | 45 | v. rights protecting the extraction, dissemination, use and reuse of data in 46 | a Work; 47 | 48 | vi. database rights (such as those arising under Directive 96/9/EC of the 49 | European Parliament and of the Council of 11 March 1996 on the legal 50 | protection of databases, and under any national implementation thereof, 51 | including any amended or successor version of such directive); and 52 | 53 | vii. other similar, equivalent or corresponding rights throughout the world 54 | based on applicable law or treaty, and any national implementations thereof. 55 | 56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, 57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and 58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright 59 | and Related Rights and associated claims and causes of action, whether now 60 | known or unknown (including existing as well as future claims and causes of 61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum 62 | duration provided by applicable law or treaty (including future time 63 | extensions), (iii) in any current or future medium and for any number of 64 | copies, and (iv) for any purpose whatsoever, including without limitation 65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes 66 | the Waiver for the benefit of each member of the public at large and to the 67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver 68 | shall not be subject to revocation, rescission, cancellation, termination, or 69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work 70 | by the public as contemplated by Affirmer's express Statement of Purpose. 71 | 72 | 3. Public License Fallback. Should any part of the Waiver for any reason be 73 | judged legally invalid or ineffective under applicable law, then the Waiver 74 | shall be preserved to the maximum extent permitted taking into account 75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver 76 | is so judged Affirmer hereby grants to each affected person a royalty-free, 77 | non transferable, non sublicensable, non exclusive, irrevocable and 78 | unconditional license to exercise Affirmer's Copyright and Related Rights in 79 | the Work (i) in all territories worldwide, (ii) for the maximum duration 80 | provided by applicable law or treaty (including future time extensions), (iii) 81 | in any current or future medium and for any number of copies, and (iv) for any 82 | purpose whatsoever, including without limitation commercial, advertising or 83 | promotional purposes (the "License"). The License shall be deemed effective as 84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the 85 | License for any reason be judged legally invalid or ineffective under 86 | applicable law, such partial invalidity or ineffectiveness shall not 87 | invalidate the remainder of the License, and in such case Affirmer hereby 88 | affirms that he or she will not (i) exercise any of his or her remaining 89 | Copyright and Related Rights in the Work or (ii) assert any associated claims 90 | and causes of action with respect to the Work, in either case contrary to 91 | Affirmer's express Statement of Purpose. 92 | 93 | 4. Limitations and Disclaimers. 94 | 95 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 96 | surrendered, licensed or otherwise affected by this document. 97 | 98 | b. Affirmer offers the Work as-is and makes no representations or warranties 99 | of any kind concerning the Work, express, implied, statutory or otherwise, 100 | including without limitation warranties of title, merchantability, fitness 101 | for a particular purpose, non infringement, or the absence of latent or 102 | other defects, accuracy, or the present or absence of errors, whether or not 103 | discoverable, all to the greatest extent permissible under applicable law. 104 | 105 | c. Affirmer disclaims responsibility for clearing rights of other persons 106 | that may apply to the Work or any use thereof, including without limitation 107 | any person's Copyright and Related Rights in the Work. Further, Affirmer 108 | disclaims responsibility for obtaining any necessary consents, permissions 109 | or other rights required for any use of the Work. 110 | 111 | d. Affirmer understands and acknowledges that Creative Commons is not a 112 | party to this document and has no duty or obligation with respect to this 113 | CC0 or use of the Work. 114 | 115 | For more information, please see 116 | 117 | -------------------------------------------------------------------------------- /html/css/markdown.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Helvetica, arial, sans-serif; 3 | font-size: 14px; 4 | line-height: 1.6; 5 | padding-top: 10px; 6 | padding-bottom: 10px; 7 | background-color: white; 8 | padding: 30px; } 9 | 10 | body > *:first-child { 11 | margin-top: 0 !important; } 12 | body > *:last-child { 13 | margin-bottom: 0 !important; } 14 | 15 | a { 16 | color: #4183C4; } 17 | a.absent { 18 | color: #cc0000; } 19 | a.anchor { 20 | display: block; 21 | padding-left: 30px; 22 | margin-left: -30px; 23 | cursor: pointer; 24 | position: absolute; 25 | top: 0; 26 | left: 0; 27 | bottom: 0; } 28 | 29 | h1, h2, h3, h4, h5, h6 { 30 | margin: 20px 0 10px; 31 | padding: 0; 32 | font-weight: bold; 33 | -webkit-font-smoothing: antialiased; 34 | cursor: text; 35 | position: relative; } 36 | 37 | h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, h5:hover a.anchor, h6:hover a.anchor { 38 | text-decoration: none; } 39 | 40 | h1 tt, h1 code { 41 | font-size: inherit; } 42 | 43 | h2 tt, h2 code { 44 | font-size: inherit; } 45 | 46 | h3 tt, h3 code { 47 | font-size: inherit; } 48 | 49 | h4 tt, h4 code { 50 | font-size: inherit; } 51 | 52 | h5 tt, h5 code { 53 | font-size: inherit; } 54 | 55 | h6 tt, h6 code { 56 | font-size: inherit; } 57 | 58 | h1 { 59 | font-size: 28px; 60 | color: black; } 61 | 62 | h2 { 63 | font-size: 24px; 64 | border-bottom: 1px solid #cccccc; 65 | color: black; } 66 | 67 | h3 { 68 | font-size: 18px; } 69 | 70 | h4 { 71 | font-size: 16px; } 72 | 73 | h5 { 74 | font-size: 14px; } 75 | 76 | h6 { 77 | color: #777777; 78 | font-size: 14px; } 79 | 80 | p, blockquote, ul, ol, dl, li, table, pre { 81 | margin: 15px 0; } 82 | 83 | hr { 84 | border: 0 none; 85 | color: #cccccc; 86 | height: 4px; 87 | padding: 0; 88 | } 89 | 90 | body > h2:first-child { 91 | margin-top: 0; 92 | padding-top: 0; } 93 | body > h1:first-child { 94 | margin-top: 0; 95 | padding-top: 0; } 96 | body > h1:first-child + h2 { 97 | margin-top: 0; 98 | padding-top: 0; } 99 | body > h3:first-child, body > h4:first-child, body > h5:first-child, body > h6:first-child { 100 | margin-top: 0; 101 | padding-top: 0; } 102 | 103 | a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 { 104 | margin-top: 0; 105 | padding-top: 0; } 106 | 107 | h1 p, h2 p, h3 p, h4 p, h5 p, h6 p { 108 | margin-top: 0; } 109 | 110 | li p.first { 111 | display: inline-block; } 112 | li { 113 | margin: 0; } 114 | ul, ol { 115 | padding-left: 30px; } 116 | 117 | ul :first-child, ol :first-child { 118 | margin-top: 0; } 119 | 120 | dl { 121 | padding: 0; } 122 | dl dt { 123 | font-size: 14px; 124 | font-weight: bold; 125 | font-style: italic; 126 | padding: 0; 127 | margin: 15px 0 5px; } 128 | dl dt:first-child { 129 | padding: 0; } 130 | dl dt > :first-child { 131 | margin-top: 0; } 132 | dl dt > :last-child { 133 | margin-bottom: 0; } 134 | dl dd { 135 | margin: 0 0 15px; 136 | padding: 0 15px; } 137 | dl dd > :first-child { 138 | margin-top: 0; } 139 | dl dd > :last-child { 140 | margin-bottom: 0; } 141 | 142 | blockquote { 143 | border-left: 4px solid #dddddd; 144 | padding: 0 15px; 145 | color: #777777; } 146 | blockquote > :first-child { 147 | margin-top: 0; } 148 | blockquote > :last-child { 149 | margin-bottom: 0; } 150 | 151 | table { 152 | padding: 0;border-collapse: collapse; } 153 | table tr { 154 | border-top: 1px solid #cccccc; 155 | background-color: white; 156 | margin: 0; 157 | padding: 0; } 158 | table tr:nth-child(2n) { 159 | background-color: #f8f8f8; } 160 | table tr th { 161 | font-weight: bold; 162 | border: 1px solid #cccccc; 163 | margin: 0; 164 | padding: 6px 13px; } 165 | table tr td { 166 | border: 1px solid #cccccc; 167 | margin: 0; 168 | padding: 6px 13px; } 169 | table tr th :first-child, table tr td :first-child { 170 | margin-top: 0; } 171 | table tr th :last-child, table tr td :last-child { 172 | margin-bottom: 0; } 173 | 174 | img { 175 | max-width: 100%; } 176 | 177 | span.frame { 178 | display: block; 179 | overflow: hidden; } 180 | span.frame > span { 181 | border: 1px solid #dddddd; 182 | display: block; 183 | float: left; 184 | overflow: hidden; 185 | margin: 13px 0 0; 186 | padding: 7px; 187 | width: auto; } 188 | span.frame span img { 189 | display: block; 190 | float: left; } 191 | span.frame span span { 192 | clear: both; 193 | color: #333333; 194 | display: block; 195 | padding: 5px 0 0; } 196 | span.align-center { 197 | display: block; 198 | overflow: hidden; 199 | clear: both; } 200 | span.align-center > span { 201 | display: block; 202 | overflow: hidden; 203 | margin: 13px auto 0; 204 | text-align: center; } 205 | span.align-center span img { 206 | margin: 0 auto; 207 | text-align: center; } 208 | span.align-right { 209 | display: block; 210 | overflow: hidden; 211 | clear: both; } 212 | span.align-right > span { 213 | display: block; 214 | overflow: hidden; 215 | margin: 13px 0 0; 216 | text-align: right; } 217 | span.align-right span img { 218 | margin: 0; 219 | text-align: right; } 220 | span.float-left { 221 | display: block; 222 | margin-right: 13px; 223 | overflow: hidden; 224 | float: left; } 225 | span.float-left span { 226 | margin: 13px 0 0; } 227 | span.float-right { 228 | display: block; 229 | margin-left: 13px; 230 | overflow: hidden; 231 | float: right; } 232 | span.float-right > span { 233 | display: block; 234 | overflow: hidden; 235 | margin: 13px auto 0; 236 | text-align: right; } 237 | 238 | code, tt { 239 | margin: 0 2px; 240 | padding: 0 5px; 241 | white-space: nowrap; 242 | border: 1px solid #eaeaea; 243 | background-color: #f8f8f8; 244 | border-radius: 3px; } 245 | 246 | pre code { 247 | margin: 0; 248 | padding: 0; 249 | white-space: pre; 250 | border: none; 251 | background: transparent; } 252 | 253 | .highlight pre { 254 | background-color: #f8f8f8; 255 | border: 1px solid #cccccc; 256 | font-size: 13px; 257 | line-height: 19px; 258 | overflow: auto; 259 | padding: 6px 10px; 260 | border-radius: 3px; } 261 | 262 | pre { 263 | background-color: #f8f8f8; 264 | border: 1px solid #cccccc; 265 | font-size: 13px; 266 | line-height: 19px; 267 | overflow: auto; 268 | padding: 6px 10px; 269 | border-radius: 3px; } 270 | pre code, pre tt { 271 | background-color: transparent; 272 | border: none; } 273 | 274 | sup { 275 | font-size: 0.83em; 276 | vertical-align: super; 277 | line-height: 0; 278 | } 279 | * { 280 | -webkit-print-color-adjust: exact; 281 | } 282 | @media screen and (min-width: 914px) { 283 | body { 284 | width: 854px; 285 | margin:0 auto; 286 | } 287 | } 288 | @media print { 289 | table, pre { 290 | page-break-inside: avoid; 291 | } 292 | pre { 293 | word-wrap: break-word; 294 | } 295 | } 296 | -------------------------------------------------------------------------------- /weui.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | weui 12 | ==== 13 | 14 | >目前中国的前端开发主要以 微信为主,因此,微信提供的 WeUI 成为前端 H5自然成为开发首选。 15 | 16 | >WeUI和同 FrozenUI都属于 差不多的 WeUi了,也是一个比较专一的框架,WeUI应该说比FrozenUI前者更专一,话说连个官网都不搞,所有答疑都在 gitHub Issues 解决了,这个框架极其简单,体积当然就不用说了,模块也就 7 个左右,不过体量虽然小做的却不错,口碑看 star 就够了,框架从 16/1/23 发版至今 github star 超过 9K,不过也不排除用户没地方发泄所以都跑到 git 上来,哈哈。 17 | 18 | >我的感觉:还比较年轻、轻量级的,出了不少第三方的扩展,基于VUE的,React的都有,我比较喜欢那个jQuery WeUI:https://github.com/lihongxun945/jquery-weui,如果单纯做基于微信的开发,我会选择这个! 19 | 20 | ## 官网 21 | 22 | - Github:https://github.com/weui/weui 23 | - DEMO:http://weui.github.io/weui/ 24 | - Star:9,237 25 | - 引用 26 | 27 | 28 | 29 | ## 相关资源 30 | 31 | - vue:https://github.com/airyland/vux 32 | - react:https://github.com/weui/react-weui 33 | - sketch:https://github.com/weui/weui-sketch 34 | 矢量图标,可自行修改、增加 35 | - todo示例:https://github.com/progrape/todo 36 | - weui.js:https://github.com/progrape/weui.js 37 | - jquery-weui:https://github.com/lihongxun945/jquery-weui 38 | 在 weui基本库上做了扩展,增加了部分控件,与 weui 100% 兼容。 39 | - router:https://github.com/progrape/router 40 | weui 示例中使用的 router,route自身也带有一个简单的图文列表示例 41 | 42 | 总结:看完微信设计团队设计的这套 DEMO,二话不说如果要做微信公众,这个二话不说必然是首选了。框架不好的地方简而言之就是框架本身应该就没考虑过让用户用到非微信的场景之下。 43 | 44 | 45 | ## 使用 46 | 47 | 说实话,weui的手册真心不直观,由于是纯css样式库,一般人拿到这个不知道如何使用!里面带的一个示例,使用了 router,一般人也看不明白,不知道到底是如何工作的! 48 | 49 | 这样设计的目的,可能跟好的与其它库失配。 50 | 51 | 52 | ## todo示例 53 | 54 | ### 目录说明 55 | 56 | ``` 57 | ├── dist # 编译输出目录 58 | ├── package.json # package.json 59 | ├── src 60 | │ ├── app.js # js 入口文件 61 | │ ├── index.html # html 入口文件 62 | │ ├── lib # 路由、工具等方法 63 | │ ├── todo # 程序主要逻辑文件 64 | └── webpack.config.js 65 | ``` 66 | 67 | ### 运行 68 | 69 | ``` 70 | git clone https://github.com/progrape/todo.git 71 | cd todo 72 | npm install 73 | npm start 74 | ``` 75 | 76 | ### 代码讲解 77 | 78 | - 使用了 webpack 对所有文件打包,浏览时,全部下载到浏览器,在浏览器中运行。 79 | - css 使用了 less库。 80 | - 使用了 babel 库,对新的js语法进行支持 81 | - ui框架当然是 weui 82 | - 运行js库有 jquery、fastclick、weui 83 | - weui.js 使用 js对weui调用做了封装 84 | 85 | ## router 86 | 87 | ### 使用 88 | 89 | HTML 90 | 91 | ```html 92 | 93 | 94 | 95 | 96 | 97 | example 98 | 99 | 100 |
101 | 102 | 103 | 104 | ``` 105 | 106 | JavaScript 107 | 108 | ```javascript 109 | var router = new Router({ 110 | container: '#container' 111 | }); 112 | var home = { 113 | url: '/', 114 | className: 'home', 115 | render: function (){ 116 | return '

home

'; 117 | } 118 | }; 119 | var post = { 120 | url: '/post/:id', 121 | className: 'post', 122 | render: function (){ 123 | var id = this.params.id; 124 | return '

post

'; 125 | } 126 | }; 127 | router.push(home).push(post).setDefault('/').init(); 128 | ``` 129 | 130 | ### 运行示例 131 | 132 | ```shell 133 | git clone https://github.com/progrape/router 134 | cd router 135 | npm install 136 | npm start 137 | ``` 138 | 139 | ### API 140 | 141 | #### Router([option]) 142 | 143 | 参数 `option` 是可选的,下面是该参数可选的属性。 144 | 145 | |属性 |类型 |默认值 |描述| 146 | |-------- |--- |--- |--- 147 | |container |String |'#container' | `container` 容器的选择器 148 | |enter |String |'enter' | 该页面出现时添加的类名,`enterTimeout` 为 0 时会被忽略 149 | |enterTimeout |Number |0 | 在这个时间之后移除添加的 `enter` 类名 150 | |leave |String |'leave' | 该页面离开时添加的类名,`lieaveTimeout` 为 0 时会被忽略 151 | |leaveTimeout |Number |0 | 在这个时间之后移除该页面的 DOM 152 | 153 | 154 | #### 实例方法 155 | 156 | 以下方法执行完毕后均返回实例本身。 157 | 158 | ##### push(route) 159 | 160 | 添加路由页面的配置。下面是 `route` 参数的属性。 161 | 162 | 163 | |属性 |类型 |描述 164 | |-----------|-------|--- 165 | |url |String | 以 `/` 开头的 url,会体现在 hash,支持参数,如:`/user/:userId/post/:posdId` 166 | |className |String | 可选,该页面可以添加的额外类名,以便控制该页面下的样式 167 | |render |function| 页面渲染方法,支持同步和异步, 可以直接返回 html 字符串,可以返回 `promise` 对象,也可以接收 `callback` 参数 168 | |bind |function| 执行绑定事件的方法,`this` 指向当前页面容器 169 | 170 | route 示例如下: 171 | 172 | 同步 173 | 174 | ```javascript 175 | { 176 | url: '/home', 177 | className: 'home', 178 | render: function (){ 179 | return ''; 180 | }, 181 | bind: function (){ 182 | $(this).on('click', 'button', function (){ 183 | // do something 184 | }); 185 | } 186 | } 187 | ``` 188 | 189 | promise 190 | 191 | ```javascript 192 | { 193 | url: '/home', 194 | className: 'home', 195 | render: function (){ 196 | return new Promise(function (resolve, reject){ 197 | resolve(''); 198 | }); 199 | }, 200 | bind: function (){ 201 | $(this).on('click', 'button', function (){ 202 | // do something 203 | }); 204 | } 205 | } 206 | ``` 207 | 208 | callback 209 | 210 | ```javascript 211 | { 212 | url: '/home', 213 | className: 'home', 214 | render: function (callback){ 215 | callback(null, ''); 216 | }, 217 | bind: function (){ 218 | $(this).on('click', 'button', function (){ 219 | // do something 220 | }); 221 | } 222 | } 223 | ``` 224 | 225 | ##### setDefault(url) 226 | 227 | 设置页面启动时默认跳转的 url。 228 | 229 | ##### init() 230 | 231 | 启动页面,在调用完 `push` 和 `setDefault` 方法后调用,主要完成 `hashchange` 的事件监听和跳转默认页面的工作。 232 | 233 | ## 引用文件 234 | 235 | - jquery-weui.min.css 54k 236 | - jquery-weui.min.js 56k 237 | - zepto.min.js 25k 238 | - jquery.min.js 90k 239 | - weui.min.css 36k 240 | - weui.min.js 14k 241 | - bootstrape.js 37k 242 | - bootstrape.css 123k 243 | - sm.min.css 90k 244 | - sm.min.js 119k 245 | 246 | ## 方案 247 | 248 | - 不使用扩展组件的,只需 weui.css + weui.js = 50k 249 | 可使用 weui 中的 13 个基础组件 250 | - 使用扩展组件的,需 weui.css + jquery-weui.css + jquery-weui.js = 146k 251 | 增加了 12 个扩展组件,包括 下拉刷新、滚动加载 252 | - bootstrape方案,需 bootstrape.js + bootstrape.css = 160k 253 | bootstrape方案适合做pc及手机,纯手机,微信H5,推荐 weui方案。 254 | bootstrape 没有包括 weui 扩展组件,需要这些组件,还需要加载其它库! 255 | - 使用 淘宝的 sui,90+119=209 256 | 257 | ## jquery-weui 258 | 259 | ## weui.css 生成 260 | 261 | 克隆代码库,安装依赖,使用 gulp 自动生成 css文件 262 | 263 | ``` 264 | git clone https://github.com/weui/weui.git 265 | cd weui 266 | npm i 267 | gulp 268 | ``` 269 | 270 | 根据项目需要,选择 css,运行 gulp 重新生成 css文件! 271 | 自己构建的css文件一般比较小,但是没法使用公共的 cdn 库,速度上不一定有优势! 272 | 273 | ```js 274 | @import "./base/reset"; 275 | 276 | // icon font 277 | @import "./icon/weui_icon_font"; 278 | 279 | 280 | // button 281 | @import "./widget/weui_button/weui_button"; 282 | 283 | // cell 284 | @import "./widget/weui_cell/weui_cell_global"; 285 | 286 | @import "./widget/weui_cell/weui_access"; 287 | @import "./widget/weui_cell/weui_check"; 288 | @import "./widget/weui_cell/weui_form"; 289 | @import "./widget/weui_cell/weui_switch"; 290 | @import "./widget/weui_cell/weui_uploader"; 291 | 292 | // msg 293 | @import "./widget/weui_page/weui_msg"; 294 | 295 | // article 296 | @import "./widget/weui_page/weui_article"; 297 | 298 | // tab 299 | @import "./widget/weui_tab/weui_tab"; 300 | 301 | // progress 302 | //@import "./widget/weui_progress/weui_progress"; 303 | 304 | // card 305 | @import "./widget/weui_panel/weui_panel"; 306 | 307 | // media box 308 | //@import "./widget/weui_media_box/weui_media_box"; 309 | 310 | // grid 311 | @import "./widget/weui_grid/weui_grid"; 312 | 313 | // tips 314 | //@import "./widget/weui_tips/weui_dialog"; 315 | //@import "./widget/weui_tips/weui_toast"; 316 | //@import "./widget/weui_tips/weui_mask"; 317 | 318 | //action sheet 319 | //@import "./widget/weui_tips/weui_actionsheet"; 320 | 321 | //searchbar 322 | //@import "./widget/weui_searchbar/weui_searchbar"; 323 | ``` 324 | 325 | -------------------------------------------------------------------------------- /js2016.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | # js 2016发展趋势(必读) 14 | 15 | >本文由[gaohailang](https://github.com/gaohailang/blog/issues/12)翻译自[State of the Art JavaScript in 2016](https://medium.com/javascript-and-opinions/state-of-the-art-javascript-in-2016-ab67fc68eb0b),加上了部分译者的观点。就像是隧道终点前的光明,JS生态的最佳实践不再剧烈变更着,现在关于需要学什么越来越明确了。本文就关于核心类库,状态管理,语言特性,构建工具,CSS预处理,API & HTTP 类库,测试工具,依赖管理等等前端开发的方方面面进行了展望和梳理,为你挑出这些最佳实践和面向未来的设计~ 16 | 17 | 那么,你要开始一个崭新的Javascript前端项目了,或者被之前老项目折腾半死,你也许并没有和改变进化步伐极快的社区生态保持技术实践的同步,或者你开始了,但是有大量的可选项不知道怎么选。React,Flux,Angular,Aurelia,Mocha,Jasmine,Jasmine,Babel,TypeScript,Flow。哦我的天呐这么多~ 为了让事件变得更简单,我们很多人正陷入一个陷阱:被我喜欢的XKCD漫画描述的很好: 18 | 19 | ![js2016-1](https://raw.githubusercontent.com/nydl/devnote/master/img/js2016-1.jpg) 20 | 21 | 是的,好消息是现在JS生态开始慢下来了,好项目开始冒出。最佳实践慢慢开始变得清晰了。工程师开始在现有项目上构建自己的工程还是重新创造轮子。 22 | 23 | 作为起点,下面是我对现代化Web应用各个部分的个人选择。一些选择看起来会有些争议,我会在每个选择后附上我的基本推理判断。要注意的是,这些选择通常是我建立在我目前对社区的观察和我个人的经历。你的看法当然会有不同~ 24 | 25 | ## 核心类库:React 26 | 27 | ![js2016-2](https://raw.githubusercontent.com/nydl/devnote/master/img/js2016-2.jpg) 28 | 29 | 目前胜者很显然就是React(译者:你确定?!) 30 | 31 | - 从顶到底都是组件,你的应用程序代码非常容易理解 32 | - 学习曲线非常平缓,要知道罗列它所有关键的API都不会超过一页A4纸张。 33 | - JSX非常棒,你可以用获得JavaScript编程语言的能力和工具链来描述页面 34 | - 使用Flux和Redux这种单向数据流非常直白来表达业务逻辑 35 | - React的社区生态圈非常不错,产出了很多高质量的开发工具如Redux(后续会讲到) 36 | - 在React写的大型项目中,利用Flux管理起数据流/内部状态非常容易(而不像在双向数据绑定中, 例如Angular1.x/Knockout中 37 | - 如果你需要类似于服务端渲染,那么选React没错了 38 | 39 | 现在不少全能的大型框架如Ember,Angular,它们承诺说帮你处理所有的事。但是在React生态中,尽管需要对组件做一些决定(哈这就是你为什么要阅读本文的原因啦),但是这方案更强壮。很多其他框架,譬如Angular2.0正在快速追赶React。 40 | 41 | 『选择React不仅是个技术上的选择,更多是个商业决定!』 42 | 43 | - 额外奖励:一旦你要着手构建自己的移动应用,你会感谢ReactNative项目的 44 | (很牵强哈,Angular社区的Ionic也是PC Web向移动端迁移的好选择。各自的2.0版本也相辅相成推进上) 45 | 46 | ## 应用生命周期:Redux 47 | 48 | ![js2016-3](https://raw.githubusercontent.com/nydl/devnote/master/img/js2016-3.jpg) 49 | 50 | PS: 以上不是它最终的logo 51 | 52 | 现在我们有了我们的视图和组件层,应用程序还需要管理数据状态和应用的生命周期。Redux也是毋容置疑的优胜者。 53 | 54 | 除了React,Facebook展示了名叫Flux的单向数据流的设计模式。Flux最早用来解决和简化应用的状态管理,但是随之而来,很多开发者提出了不少新的问题如如何存储数据状态和从哪发送Ajax请求。 55 | 56 | 为了解决这些问题,不少基于Flux模式之上的框架诞生了:Fluxible, Reflux, Alt, Flummox, Lux, Nuclear, Fluxxor 还有很多。 57 | 58 | 不过,这其中的类Flux的优雅实现最终赢得了社区的关注,它就是Redux。 59 | 60 | 最重要的是,学习Redux小菜一碟。它的作者,Dan Abranmov是一位非常棒的老师(他的教学视频非常易懂好学)。通过那些视频你很容易成为Redux的专家。我见见识到一组几乎没有任何React开发经验的工程师通过学习他的视频,在几周内就开发好能上线的React项目(代码质量也是顶级的) 61 | 62 | Redux的生态系统和Redux本身一样优秀。从神乎其神的开发者工具到令人记忆深刻的reselect,Redux的社区是你最好的后盾。 63 | 64 | 不过有一点需要注意的是不要轻易的去尝试抽象Redux的项目模板。那些模板背后都是有意义有原因的。所以你尝试盲目修改前确保你已经使用过它和理解这样组织代码背后的原因。 65 | 66 | ## 语言:ES6配合Babel,先不加类型 67 | 68 | ![js2016-4](https://raw.githubusercontent.com/nydl/devnote/master/img/js2016-4.jpg) 69 | 70 | 不用再用CoffeeScript了(译者哭了出来,公司13年大规模的使用它,至今后端JS项目80%都是它的身影)。因为它的大部分好的特性在ES6都有了(它是JavaScript的标准语言规范),而且CoffeeScript的工具很弱(如CoffeeLint),它的社区也在快速的衰落。 71 | 72 | ES6是语言的标准。它的大部分特性在最新的主流浏览器中已经被实现,Babel是个可插拔ES6编译器。把它配置到使用合适的预设目标(preset target,如es2015浏览器,es2015-node5),就可以开动了。 73 | 74 | 那么关于类型呢,TypeScript和Flow都给JavaScript提供了加上静态类型的功能,来配合编辑器提供更好的IDE支持和不需要测试就能捕获一些bug。不过我还是建议,先等等看,看看社区的进展和动向。 75 | 76 | TypeScript做了很多工作让JavaScript写起来看起来非常像Java/C#,但它缺乏完善的现代化的类型系统特性如代数数据类型(它对你真正开始实操静态类型时是很重要的)。它也不像Flow那样很好的处理 nulls。 77 | 78 | 更新:TypeScript有union types也能覆盖很多用户开发场景。 79 | 80 | Flow比起来似乎更强大,能捕获到更大范围的bug异常,但是比较难设置。在语言特性上,它比起Babel落后不少,在Windows上的支持也不好。 81 | 82 | 我要说些有争议性的话了:类型在前端开发中并没有我们想的那么重要(可能需要写一篇长文来讲述了)。所以就先等着类型系统变得更强健,目前先只使用Babel,同时关注下Flow~ 83 | 84 | ## 格式和风格:ESlint配合Airbnb指南 85 | 86 | ![js2016-5](https://raw.githubusercontent.com/nydl/devnote/master/img/js2016-5.jpg) 87 | 88 | 关于ESLint异议也不大。使用它的React插件和良好的es6的支持,几乎非常完美完成lint的工作。JSLint是过时了,ESLint这个软件可以单独完成原本需要 JSHint 和 JSCS 联合起来做的事。 89 | 90 | 你需要配置他用你的风格约定。我强烈建议你使用 Airbnb的风格指南,大部分可以被 ESLint airbnb config 来严格约束实现。如果你们团队会在代码风格上产生分歧和争超,那么拿出这份指南来终结所有的不服!它也不是完美的(因为完美的风格不存在),但保持统一一致的代码风格是要高度推荐的。 91 | 92 | 一旦你开始熟悉它,我建议你开启更多的规则。在编辑撰写代码时候越多的捕获不规范(配置你的编辑器IDE使用上这个ESLint插件),就会避免分歧和在决定费神,从而让你和团队更加高效! 93 | 94 | ## 依赖管理:仅考虑NPM,CommonJS 和ES6模块 95 | 96 | ![js2016-6](https://raw.githubusercontent.com/nydl/devnote/master/img/js2016-6.jpg) 97 | 98 | 这一点很明确 - 就用NPM。所有东西,忘记之前的bower。类似与 Browserify 和 Webpack 的构建工具把npm的强大功能引到了web上。版本处理变得很简单,你也获得了node生态的大部分模块提供的功能。不过CSS的相关处理还是不够完美。 99 | 100 | 你可能会考虑的一件事:如何在开发服务器构建应用。不想Ruby社区的Bundler,npm 常使用通配符来指定版本号,导致你开始书写代码到最后部署时候版本号很可能已经变化了。使用 shrinkwrap 文件来锁定你的依赖(我建议使用 [Uber的shrinkwrap](https://github.com/uber/npm-shrinkwrap) 来获得更见一致性的输入)。同时考虑使用利用类似于 Sinopia 来构建自己的私有npm服务器。 101 | 102 | Babel可以把 ES6 模块语法编译到CommonJS。意味着你可面向未来的语法,和在使用构建工具(如Webpack 2.0)时获得它支持的一些静态代码分析工具如 [tree shaking](http://www.2ality.com/2015/12/webpack-tree-shaking.html) 的优势 103 | 104 | 构建工具:Webpack 105 | 106 | ![js2016-7](https://raw.githubusercontent.com/nydl/devnote/master/img/js2016-7.jpg) 107 | 108 | 不想在你的页面文件中加入非常多的外链Script引用,那你就需要一个构建工具来打包你的依赖。如果你也需要允许npm包在浏览器运行工作的工具,那么Webpack就是你需要的。 109 | 110 | 一年前,关于这块还有不少选择。根据你的开发环境,你可以利用Rails的sprockets来解决类似问题。RequireJS,Browserify和Webpack都是以JavaScript基础的工具,现在RollupJS声称自己在ES6模块上处理的更好。 111 | 112 | 在一个个尝试使用后,我最终还是高度推荐Webpack: 113 | 114 | - 它有自己独特的写法,不过即使是最少见的场景也能找到解决的方法 115 | - 主流的模块格式都支持(如AMD,CommonJS,Globals写法) 116 | - 它有处理有问题模块的能力(不是标准的模块写法 117 | - 它能处理CSS文件 118 | - 它有最完善的cache busting/hashing 系统(如果你需要把你的资源发布到CDN) 119 | - 它内置热加载功能 120 | - 它能加载几乎你需要的一切 121 | - 它一套令人惊叹的优化列表 122 | 123 | Webpack目前也是处理大型SPA应用项目的最好方案,利用它的代码切割(code splitting)和懒加载特性。 124 | 125 | 不过它的学习曲线很陡峭,但是一点你掌握了,你还是会认为非常值得因为它的强大功能。 126 | 127 | 那么Gulp或Grunt呢? Webpack比起来最适合处理静态资源。所以他们开始可以用来跑一些其他的任务(但是也不推荐),现在更简单的方法是直接用上 npm scripts 128 | 129 | ## 测试:Mocha + Chai + Sinon(但没那么简单) 130 | 131 | ![js2016-8](https://raw.githubusercontent.com/nydl/devnote/master/img/js2016-8.jpg) 132 | 133 | 目前在 JavaScript 单元测试上,我们有众多选择,你选择任何一个都不会错太多。因为你开始做单元测试,你就走对一大步了。 134 | 135 | 一些选择包括了 Jasmine,Mocha,Tape,AVA 和 Jest。我知道我漏掉来一些,它们都有一些比其他做的好的地方。 136 | 137 | 我对一个测试框架的的选择标准是: 138 | 139 | - 它应该可以在浏览器中运行从而方便调试 140 | - 它应该运行的足够快 141 | - 它可以很好的处理解决异步测试 142 | - 它可以在命令行就能很方便的使用 143 | - 它应该允许我使用任意断言库,而不会约束限制 144 | 145 | 第一个指标让AVA脱颖而出(因为它的确做的非常棒)和Jest(自动Mocking并不像它说的那么好,因为它太慢了) 146 | 147 | 选择Jasmine,Mocha或Tape都不会差太多。我倾向于 Chai 断言因为它拥有很多插件,Sinon's mocks to Jasmine's built in construct。Mocha的异步测试支持很棒(你不用在写类似于 done callback之类的)。[Chai as Promised](https://github.com/domenic/chai-as-promised) 也是很屌。我强烈建议你使用 [Dirty Chai](https://github.com/prodatakey/dirty-chai) 来避免一些让人头疼的问题。Webpack的 [mocha loader](https://github.com/webpack/mocha-loader) 让你编码时自动执行测试。 148 | 149 | 对于React而言,Airbnb的[Enzyme](https://github.com/airbnb/enzyme)和Teaspoon(不是Rails那个!)是不错的相关工具选择。 150 | 151 | 我非常喜欢Mocha的特性和支持情况。如果你喜欢一些最小主义的,读读这篇[关于tape的文章](https://medium.com/javascript-scene/why-i-use-tape-instead-of-mocha-so-should-you-6aa105d8eaf4) 152 | 153 | PS: 154 | Facebook在最近的文章中说,它们是如何扩展Jest的。可能对大部分人来说过于复杂了,如果你有那些资源,不关心是否在浏览器中跑测试,那么它就很适合你。 155 | 156 | 另外,很多人认为我对AVA太武断了。不要误会我,AVA的确很棒。但我有个标准:全浏览器支持。这样我们可以直接从任何浏览器去执行(来测试跨浏览器兼容性)同时要方便调试。如果你不介意那些,你可以使用非常棒的iron-node来debugging。 157 | 158 | ## 工具库:Lodash是绝对王者,但留意 Ramda 159 | 160 | JavaScript不像Java或.NET上有很多强大的内置工具集。所以你可能需要引入一个。 161 | 162 | Lodash,目前来说应该是杂七杂八都有的首选。同时它类似注入[懒求值](http://filimanjaro.com/blog/2014/introducing-lazy-evaluation/)这样的特性让它成为性能最高的选择之一。如果你不想用你就不要把它全部都导入,同时:lodash能让你仅仅引入哪些你需要的函数(这点尤其重要考虑到它现在变得越来越大)。随着4.x版本带来,它原生支持可选的函数式模式给那些函数式编程的极客们使用。来看看[怎么使用它](https://github.com/lodash/lodash/wiki/FP-Guide) 163 | 164 | 如果你真的很喜欢函数式编程,那么不管怎么样,留意下优秀的[Ramda](http://ramdajs.com/0.19.1/index.html)。如果你决定用它,你可能还是需要引入一些lodash函数(Ramda目前专注于数据处理和函数式构建),但这样你能在JavaScript中以非常友好方式获得函数式编程的强大功能 165 | 166 | ## Http请求:就只用fetch 167 | 168 | 许多React应用再也不需要jQuery了。除非你需要使用一些遗留的老旧的第三方组件(它依赖于jQuery),因为根本没必要。同时,意味着你需要一个类似于$.ajax的替代品。 169 | 170 | 为了保持简单,仅仅使用[fetch](https://fetch.spec.whatwg.org/),它在Firefox和Chrome中内建支持。对于其他浏览器,你可能需要引入polyfill。我推荐使用[isomorphic-fetch](https://github.com/matthew-andrews/isomorphic-fetch) 来在服务器端在内覆盖了基础组件选择。 171 | 172 | 还有一些其他好的类库选择如[Axios](https://github.com/mzabriskie/axios),但目前在fetch之上没有多余需求。 173 | 174 | 为了更多关于为什么Promise是重要的讨论,请看我们博客异步代码 175 | 176 | ## 样式:考虑CSS模块 177 | 178 | 这是个我觉得相对发展较慢的领域。Sass就是目前的选择,使用node-sass是你JavaScript项目的不错开始、。我仍然觉得离最终最好的方案还是有很多不足。缺乏引用导入(如仅仅是从文件导入变量和mixin,而不用重新定义选择器和它的样式规则)和原生的URL重写(使它在保持线上代码足够精简就很困难)。node-sass是一个C写的类库,所以要对应好你的Node版本。 179 | 180 | LESS并不受此影响,不过它缺了很多Sass的特性功能。 181 | 182 | PostCSS 看起来更有生命力,它允许你构建自己的CSS预处理器。我推荐你使用它,即使你已经有了你喜欢的预处理器如SASS,它类似于AutoPrefixer使得你不需要要导入类似于Bourbon这样的大型依赖。 183 | 184 | 有一点需要特殊注意的是,CSS Modules。它限制了CSS的层叠部分,使得我们可以定义更加明确的依赖,来避免冲突。你再也不用担心Class名称一致导致的覆盖,也不用特意为了避免它而添加额外的前缀。它和React也配合的很好。有个不足:css-loader和css modules一起使用会导致非常缓慢,如果你的样式数量不少,那么在它优化之前还是避免使用它吧。 185 | 186 | 如果要我现在从头开始一个新项目,那么我大概会使用PostCSS配合一些我喜欢的预编译的CSS类库。 187 | 188 | 不管你选择什么,我还是推荐你看下我这篇文章[CSS performance with Webpack](http://eng.localytics.com/faster-sass-builds-with-webpack/),尤其你也在配套使用SASS。 189 | 190 | ## 前后同构:确保你真的需要它 191 | 192 | Universal或Isometric的JavaScript代表着JavaScript写的代码可以被同时运行在客户端和服务器上。这需要用来在服务器端预先渲染页面来提升性能或SEO友好。感谢React,之前只有类似于Ebay或Facebook这样的巨型科技公司才能实施的方案,现在很多小的开发团队都能做到。不过它并不那么容易,它显著的加大了复杂性,限制了你类库和工具选择。 193 | 194 | 如果你在构建B2C的网站,类似于电商网站,那么你可能必须使用这个方案。但如果你是在做内部网站或者是B2B应用站点,那么这样的性能提升和SEO其实并不需要。所以和你的项目经理讨论下,看看是否有必要~ 195 | 196 | ## API接口:暂时没有好方案 197 | 198 | 看起来每个开发者最后都会疑问那么关于API接口呢?很多人会直接想到[RESTful API](https://en.wikipedia.org/wiki/Representational_state_transfer)(因为太流行了),同时SOAP真的成为过去式了。同时现在也有不少其他标准如:[HATEOAS](https://en.wikipedia.org/wiki/HATEOAS), [JSON API](http://jsonapi.org/),[HAL](http://stateless.co/hal_specification.html),[GraphQL](https://facebook.github.io/react/blog/2015/05/01/graphql-introduction.html) 等 199 | 200 | GraphQL 赋予客户端强大的能力(也是职责),允许它来实施任意的查询接口。结合Relay,它能为你处理客户端状态和缓存。在服务器端实施GraphQL看起来比较困难而且现有的文档大部分是针对Node.js的 201 | 202 | 网飞(NetFlix)的[Falcor](https://github.com/Netflix/falcor) 看起来它也能提供那些Relay和GraphQL提供的功能,但是对于服务器端的实现要求很低。但现在它仅仅是开发者预览版没有正式发布。 203 | 204 | 所有这些有名的标准规范有他们各种的奇怪之处。一些是过于复杂,一些只能处理读取没有覆盖到更新接口。一些又严重和REST走失。许多人选择构建它们自己的,但是最终也要解决它们设计上带来的问题。 205 | 206 | 我不认为现在有什么方案是个大满贯(完美的),但是下面是我对API应该有的功能的一些思考: 207 | 208 | - 它应该是可预测的,你的API节点应该是遵循一致性规范的 209 | - 它可以在一次就能拉取多个资源的数据(如果你的应用启动需要来回请求十几个接口来获得相关的资源数据,应用的性能应该是非常糟糕的 210 | - 它可以覆盖除去读取,也包括更新的能力(很多方案仅仅提供读取的 211 | - 它应该容易debug:譬如看看Chrome的开发者工具的network网络tab下就能审视发生了什么 212 | - 它应该容易被消费,譬如可以简单的通过 fetch API 方式或者有相应的客户端类库支持如Relay 213 | 214 | 我没有找到能覆盖这些需求的方案。如果有,务必让我知道。 215 | 同事考虑,如果你实施一个标准化的RESTful资源路径时,使用Swagger来文档化我们的API。 216 | 217 | ## 客户端软件:Electron 218 | 219 | Electron 是Atom这个优秀编辑器的背后基石。你可以用它来构建自己的应用程序。它的核心,就是一个特殊版本的Node可以来打开Chrome窗口来渲染GUI页面,并且能够获取到操作系统底层的API(不用借助浏览器的安全沙箱等措施)。你可以打包你的应用程序像其他的桌面客户端软件那样分发安装包,并且辅以自动更新机制。 220 | 221 | 这就是用来构建横跨OSX,WIndows和Linux这多个桌面环境的应用软件的最简单的方式,利用起上面提到的所有好用的工具。它也有不错的文档和活跃的社区支持。 222 | 223 | 你也许也听过nw.js(之前叫node-webkit)它年事已高,Electron比它更稳健,更容易上手使用。 224 | 225 | 来使用这个模板项目来开搞自己的Electron,React和热更新项目吧,你可以看看这些东西是怎么相互配合工作的~ 226 | 227 | ## 向谁学习,从哪学起 228 | 229 | 社区有一些大牛,你可以在Twitter,Weibo,掘金上关注他们。 230 | 还有不少好的文章和链接。 231 | 232 | 如 [Removing user interface complexity, or why React is awesome](http://jlongster.com/Removing-User-Interface-Complexity,-or-Why-React-is-Awesome) 就是对了解React背后实现原理和原因的不错讲述。 233 | 234 | ## 如果你不需要,就别用它! 235 | 236 | JavaScript生态区发展很快,欣欣向荣,在快速前进着。但是就像是隧道终点前的光明,最佳实践不在剧烈变更着。现在关于需要学什么越来越明确了。 237 | 238 | 最重要的是记住要保持简单,如无必要,勿增实体。 239 | 240 | 如果你的应用就是两三个页面,那你不需要用到 Router。如果就一个页面,那么你也不用Redux,只需要用React自己管理状态就好。你的应用就是简单的 CRUD 程序,那么不需要用到 Relay。你在学习 ES6 的语法,那么先别急着弄 Async/Await 或者装饰器。你准备开始学习 React 了,你不必要立马就去了解 Hot Reload 热更新和服务器端渲染。如果你刚刚使用上 Webpack,那么也别急着就来用代码切割(code splitting)和多代码块(multiple chunks)。如果你才开始 Redux,那么也不用匆忙用 Redux-Form 或 Redux-Sagas。 241 | 242 | 保持简单,一次学一样,你就不会像其他人一样抱怨JavaScript的破碎(Fatigue 243 | 244 | ## 我少了什么吗? 245 | 246 | 这就是我对目前JavaScript生态现状的看法和观点。如果你觉得我遗漏了那些类别的讨论,或者你认为我在一些选型上的决定不正确,你有更好的可以推荐。那么留言吧~ -------------------------------------------------------------------------------- /flex.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 移动端弹性布局 12 | ============ 13 | 14 | >移动端手机屏幕大小不一,如何自动根据屏幕大小进行适配,是个难题。 15 | 经过对比几个流行的前端适配框架,如 weui(微信)、bootstrape(大名鼎鼎)、sui(淘宝), 16 | 发现淘宝的 sui mobile 样式框架小巧适用。 17 | 本文通过对 sui 进行分拆解析说明,让刚接触前端的同学能理解并快速上手使用移动端布局。 18 | 19 | >同时对流行的 flex 弹性布局进行了兼容性说明。flex弹性布局非常简单、适用,特别适合移动端,但是存在兼容性问题。 20 | 21 | ## flex 兼容性 22 | 23 | - gulp less 编译器对兼容性做了自动化处理,你只需在less中写最新的flex语法,less编译成css时,会自动增加兼容性处理!!! 24 | - sui中的flex.less 使用函数对兼容性做了处理,如果 gulp less没有搞定兼容性,可自行调整 flex.less 进行处理。 25 | 26 | ## 为什么要学弹性布局 27 | 28 | - 微信的weui 在用 29 | - 淘宝的 sui 在用 30 | - bootstrape 4 在用 31 | - react native 只能使用 flex布局!掌握了 flex,也就等于掌握了 安卓、苹果手机APP的前端布局! 32 | - 在手机上、一些局部排版,的确非常简单有效 33 | - 兼容性 34 | 35 | ## 相关资源 36 | 37 | - H5移动端知识点总结 http://www.cnblogs.com/tugenhua0707/p/5180841.html 38 | http://www.open-open.com/lib/view/open1454548816823.html 39 | - Flex 语法 http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html?utm_source=tuicool 40 | - Flex 实例 http://www.ruanyifeng.com/blog/2015/07/flex-examples.html 41 | - 布局:http://isux.tencent.com/web-app-rem.html 42 | - 关于webapp中的文字单位的一些捣腾:http://www.html-js.com/article/2400 43 | - 手机淘宝的flexible设计与实现:ßhttp://www.html-js.com/article/2402 44 | - Web移动端Fixed布局的解决方案:http://www.tuicool.com/articles/Inyueyi 45 | 46 | ## rem 长度单位 47 | 48 | >rem是CSS3新增的一个相对单位(root em,根em),这个单位引起了广泛关注。这个单位与em有什么区别呢?区别在于使用rem为元素设定字体大小时,仍然是相对大小,但相对的只是HTML根元素,而不是em那样相对不确定的上级元素。 49 | 这个单位可谓集相对大小和绝对大小的优点于一身,通过它既可以做到只修改根元素就成比例地调整所有字体大小,又可以避免字体大小逐层复合的连锁反应。目前,除了IE8及更早版本外,所有浏览器均已支持rem。移动端建议使用rem! 50 | 51 | >如果认为rem只是字体大小,就太小看它了,实际上,rem可用于任何元素的空间单位,在转换时,通过 html的font-size转换为px! 52 | 53 | ### px 54 | 55 | 我们一般喜欢用px像素(Pixel),px是像素的意思,相对于屏幕的分辨率而言,是个绝对单位。 56 | px的缺点非常明显,就是无法根据屏幕大小缩放,无法自动适配不同屏幕。 57 | 58 | ### em 59 | 60 | em是相对上层元素的长度单位。em的值并不是固定的,父级元素的字体变化,会引起其变化,容易引起连锁反应,导致显示的不确定,因此不太适合大型项目。 61 | 如上层字体未定义,则相对于浏览器的默认字体尺寸,浏览器的默认字体高都是16px。所有未经调整的浏览器都符合: 1em=16px。 62 | 63 | ### rem 64 | rem 是相对于 html 元素的 font-size 的一个单位。如果 html 上定义了 font-size: 20px;则无论在任何地方都是 1rem = 20px 这个大小不会受到父元素的影响。 65 | 66 | rem综合评价是用来做web app它绝对是最合适的人选之一。 67 | 我们统一使用rem对页面进行整体缩放。强烈建议大家对需要适应页面大小的任何元素都使用 rem 为单位来定义。 68 | 小于 375px 的设备上不做缩小处理,对 大于 375px 宽度的设备进行等比缩放。 69 | 70 | 71 | ## 移动适配布局分析 72 | 73 | >web app的屏幕适配有很多中做法,例如:流式布局、限死宽度,还有就是通过响应式来做,但是这些方案都不是最佳的解决方法。 74 | 75 | ### 流式布局 76 | 77 | 例如流式布局的解决方案有不少弊端,它虽然可以让各种屏幕都适配,但是显示的效果极其的不好,因为只有几个尺寸的手机能够完美的显示出视觉设计师和交互最想要的效果,但是目前行业里用流式布局切web app的公司还是挺多的,看看下面我收集的一些案例: 78 | 79 | 1. 亚马逊 80 | 2. 携程 81 | 3. 兰亭 82 | 83 | 上面的网站都是采用的流式布局的技术实现的,他们在页面布局的时候都是通过百分比来定义宽度,但是高度大都是用px来固定住,所以在大屏幕的手机下显示效果会变成有些页面元素宽度被拉的很长,但是高度还是和原来一样,实际显示非常的不协调,这就是流式布局的最致命的缺点,往往只有几个尺寸的手机下看到的效果是令人满意的,其实很多视觉设计师应该无法接受这种效果,因为他们的设计图在大屏幕手机下看到的效果相当于是被横向拉长来一样。 84 | 85 | 流式布局并不是最理想的实现方式,通过大量的百分比布局,会经常出现许多兼容性的问题,还有就是对设计有很多的限制,因为他们在设计之初就需要考虑流式布局对元素造成的影响,只能设计横向拉伸的元素布局,设计的时候存在很多局限性。 86 | 87 | 88 | ### 固定宽度做法 89 | 90 | 还有一种是固定页面宽度的做法,早期有些网站把页面设置成320的宽度,超出部分留白,这样做视觉,前端都挺开心,视觉在也不用被流式布局限制自己的设计灵感了,前端也不用在搞坑爹的流式布局。但是这种解决方案也是存在一些问题,例如在大屏幕手机下两边是留白的,还有一个就是大屏幕手机下看起来页面会特别小,操作的按钮也很小,手机淘宝首页起初是这么做的,但近期改版了,采用了rem。 91 | 92 | ### 响应式做法 93 | 94 | 响应式这种方式在国内很少有大型企业的复杂性的网站在移动端用这种方法去做,主要原因是工作大,维护性难,所以一般都是中小型的门户或者博客类站点会采用响应式的方法从web page到web app直接一步到位,因为这样反而可以节约成本,不用再专门为自己的网站做一个web app的版本。 95 | 96 | 相应式一般都会使用 BootStrape 库,来实现网站与手机自动适配,jQuery + bootstrape.js + bootstrape.css = 250k,对于一些简单的页面,需要加载 250k第三方库,似乎有些小题大做。 97 | 98 | 针对手机专用的页面,根本不需要考虑pc,因此,个人不太建议手机web采用 bootstrape库! 99 | 100 | ### 设置viewport进行缩放 101 | 102 | 天猫的web app的首页就是采用这种方式去做的,以320宽度为基准,进行缩放,最大缩放为320*1.3 = 416,基本缩放到416都就可以兼容iphone6 plus的屏幕了,这个方法简单粗暴,又高效。说实话我觉得他和用接下去我们要讲的rem都非常高效,不过有部分同学使用过程中反应缩放会导致有些页面元素会糊的情况。 103 | 104 | ### rem 等比例适配所有屏幕 105 | 106 | 由于 rem 是通过根元素进行适配的,网页中的根元素指的是html,我们通过设置html的字体大小就可以控制rem的大小。 107 | 举个按钮的例子: 108 | 109 | ```css 110 | html{ 111 | font-size:10px; 112 | } 113 | .btn { 114 | width: 6rem; 115 | height: 3rem; 116 | line-height: 3rem; 117 | font-size: 1.2rem; 118 | display: inline-block; 119 | background: #06c; 120 | color: #fff; 121 | border-radius: .5rem; 122 | text-decoration: none; 123 | text-align: center; 124 | } 125 | ``` 126 | 127 | 在font-size:10px时,6rem=60px,如此类推,font-size:20px时,6rem=120px。 128 | 129 | 通过html font-size的改变就会导致按钮的大小发生改变,并不需要改变给按钮的宽度和高度,这就是我们想要的适配性。 130 | 131 | ### font-size 设置 132 | 133 | 到这里肯定有很多人会问我是怎么计算出不同分辨率下font-size的值? 134 | 首先假设我上面的页面设计稿给我时候是按照640的标准尺寸给我的前提下,(当然这个尺寸肯定不一定是640,可以是320,或者480,又或是375)来看一组表格。 135 | ![rem尺寸图](img/https://raw.githubusercontent.com/nydl/devnote/master/img/flexremsize.jpeg) 136 | 137 | 上面的表格蓝色一列是640px的尺寸,页面是以640px的宽度去切的,怎么计算不同宽度下font-size的值,大家看表格上面的数值变化应该能明白。举个例子:384/640 = 0.6,384是640的0.6倍,所以384页面宽度下的font-size也等于它的0.6倍,这时384的font-size就等于12px。在不同设备的宽度计算方式以此类推。 138 | 139 | 可以通过JS去动态计算根元素的font-size,这样的好处是所有设备分辨率都能兼容适配,淘宝首页目前就是用的JS计算。但其实不用JS我们也可以做适配,一般我们在做web app都会先统计自己网站有哪些主流的屏幕设备,然后去针对那些设备去做media query设置也可以实现适配,例如下面这样: 140 | 141 | ```css 142 | //375屏幕为 20px,以此为基础计算出每一种宽度的字体大小 143 | //375以下不变,375以上等比放大 144 | 145 | @baseWidth: 375px; // iphone6 的尺寸 146 | @baseFont: 20px; 147 | 148 | html { 149 | font-size: @baseFont; //默认当做320px宽度的屏幕来处理 150 | } 151 | 152 | @bps: 400px, 414px, 480px; 153 | 154 | .loop(@i: 1) when (@i <= length(@bps)) { //注意less数组是从1开始的 155 | @bp: extract(@bps, @i); 156 | 157 | @font: round(@bp/@baseWidth*@baseFont,2); 158 | @media only screen and (min-width: @bp){ 159 | html { 160 | font-size: @font !important; 161 | } 162 | } 163 | .loop((@i + 1)); 164 | }; 165 | .loop; 166 | ``` 167 | less 生成css如下: 168 | 169 | ```css 170 | html { 171 | font-size: 20px; 172 | } 173 | @media only screen and (min-width: 400px) { 174 | html { 175 | font-size: 21.33px !important; 176 | } 177 | } 178 | @media only screen and (min-width: 414px) { 179 | html { 180 | font-size: 22.08px !important; 181 | } 182 | } 183 | @media only screen and (min-width: 480px) { 184 | html { 185 | font-size: 25.6px !important; 186 | } 187 | } 188 | ``` 189 | 190 | 上面的设置当然是不能所有设备全适配,但是用JS是可以实现全适配。 191 | 192 | 下面推荐两个国内用了rem技术的移动站,大家可以上去参考看看他们的做法,手机淘宝目前只有首页用了rem,淘宝native app的首页是内嵌的web app首页。 193 | 194 | - 淘宝首页:m.taobao.com 195 | - D X:m.dx.com 196 | 197 | 最后我们再来看一看他的兼容性: 198 | ![适配兼容性](https://raw.githubusercontent.com/nydl/devnote/master/img/flex02.png) 199 | 200 | ### 通过 js 动态修改 font-size的例子 201 | 202 | >js毕竟要执行,需要时间,建议使用 css 解决。 203 | 204 | ```js 205 | 206 | 207 | 208 | 209 | rem phone test 210 | 211 | 258 | 259 | 260 |
我是头部
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 | 270 | 285 | 286 | 287 | ``` 288 | 289 | ## flex 弹性布局 290 | 291 | ```css 292 | // 开启弹性布局 293 | .flexbox() { 294 | display: -webkit-box; 295 | display: -ms-flexbox; 296 | display: -webkit-flex; 297 | display: flex; 298 | } 299 | 300 | 301 | .flex-wrap(@fw) when (@fw = nowrap) { 302 | -webkit-box-lines: single; 303 | -moz-box-lines: single; 304 | -webkit-flex-wrap: nowrap; 305 | -ms-flex-wrap: none; 306 | -ms-flex-wrap: nowrap; 307 | flex-wrap: nowrap; 308 | } 309 | .flex-wrap(@fw) when (@fw = wrap) { 310 | -webkit-box-lines: multiple; 311 | -moz-box-lines: multiple; 312 | -webkit-flex-wrap: wrap; 313 | -ms-flex-wrap: wrap; 314 | flex-wrap: wrap; 315 | } 316 | .flex-wrap(@fw) when not (@fw = wrap) and not (@fw = nowrap) { 317 | -webkit-flex-wrap: @fw; 318 | -ms-flex-wrap: @fw; 319 | flex-wrap: @fw; 320 | } 321 | .flex-shrink(@fs) { 322 | -webkit-flex-shrink: @fs; 323 | -ms-flex: 0 @fs auto; 324 | flex-shrink: @fs; 325 | } 326 | .justify-content(@jc) when (@jc = flex-start) { 327 | -webkit-box-pack: start; 328 | -ms-flex-pack: start; 329 | -webkit-justify-content: flex-start; 330 | justify-content: flex-start; 331 | } 332 | .justify-content(@jc) when (@jc = flex-end) { 333 | -webkit-box-pack: end; 334 | -ms-flex-pack: end; 335 | -webkit-justify-content: flex-end; 336 | justify-content: flex-end; 337 | } 338 | .justify-content(@jc) when (@jc = space-between) { 339 | -webkit-box-pack: justify; 340 | -ms-flex-pack: justify; 341 | -webkit-justify-content: space-between; 342 | justify-content: space-between; 343 | } 344 | .justify-content(@jc) when not (@jc = flex-start) and not (@jc = flex-end) and not (@jc = space-between) { 345 | -webkit-box-pack: @jc; 346 | -ms-flex-pack: @jc; 347 | -webkit-justify-content: @jc; 348 | justify-content: @jc; 349 | } 350 | .align-items(@ai) when (@ai = flex-start) { 351 | -webkit-box-align: start; 352 | -ms-flex-align: start; 353 | -webkit-align-items: flex-start; 354 | align-items: flex-start; 355 | } 356 | .align-items(@ai) when (@ai = flex-end) { 357 | -webkit-box-align: end; 358 | -ms-flex-align: end; 359 | -webkit-align-items: flex-end; 360 | align-items: flex-end; 361 | } 362 | .align-items(@ai) when not (@ai = flex-start) and not (@ai = flex-end) { 363 | -webkit-box-align: @ai; 364 | -ms-flex-align: @ai; 365 | -webkit-align-items: @ai; 366 | align-items: @ai; 367 | } 368 | .align-content(@ai) { 369 | -ms-flex-line-pack: @ai; 370 | -webkit-align-content: @ai; 371 | align-content: @ai; 372 | } 373 | .align-self(@as) { 374 | -ms-flex-item-align: @as; 375 | -webkit-align-self: @as; 376 | align-self: @as; 377 | } 378 | ``` 379 | -------------------------------------------------------------------------------- /webpack.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 最好的前端打包工具 12 | =============== 13 | 14 | >无比强大的前端打包工具。 15 | 通过智能分析页面引用的 js(循环引用)、css,打包为单一的 bundle.js。 16 | 17 | 使用 webpack的好处 18 | 19 | - 加载快:手机页面对并发http请求有限制,打包成一个文件,可加快加载速度。 20 | - 嵌套:智能分析 js 等文件嵌套,自动安顺序打包。 21 | - 压缩:如果足够智能,应该能只包含 引用的 函数,不用的函数自动排除(待验证)。 22 | - 隔离:防止变量的互相污染。 23 | - react 使用 webpack 24 | - spa、webapp 都要使用 webpack 25 | 26 | ## 资源 27 | 28 | - 官网 http://webpack.github.io/ 29 | - 文档 http://webpack.github.io/docs/ 30 | - 教程 http://webpack.github.io/docs/tutorials/getting-started/ 31 | - webpack实战 http://www.cnblogs.com/tugenhua0707/p/4793265.html 32 | - gulp + webpack 构建多页面前端项目 http://www.open-open.com/news/view/1c51682 33 | - 30分钟手把手教你学webpack实战 34 | http://www.cnblogs.com/tugenhua0707/p/4793265.html#_labe1 35 | - 基于ES6,使用React、Webpack、Babel构建模块化JavaScript应用 36 | http://www.csdn.net/article/2015-05-24/2824757-building-modular-javascript-applications-in-es6-with-react-webpack-and-babel 37 | - webpack学习笔记,webpack http://www.bkjia.com/webzh/1041782.html 38 | - webpack使用优化 http://www.open-open.com/lib/view/open1452487103323.html 39 | - 淘宝npm https://npm.taobao.org/ 40 | - gulp & webpack 构建 - 踩坑集锦 http://www.jianshu.com/p/8412e925b0cf 41 | - Webpack 入门指迷 https://segmentfault.com/a/1190000002551952 42 | 43 | ## 安装 44 | 45 | 项目安装: 46 | `npm i -D webpack` 47 | 48 | 项目安装保存到开发依赖中,便于 使用 `npm i` 一次性建立开发环境,非常方便,如果 npm 改为淘宝镜像,速度还是非常快。 49 | 50 | 全局安装: 51 | `npm i -g webpack` 52 | 53 | 使用 npm i 只能自动安装项目依赖库,全局库需手工安装,对于常用的全局工具,如 gulp、webpack、bable 等常用全局工具,可以全局安装,不用每个项目单独安装。 54 | 55 | 不推荐全局安装,全局库导致项目对环境依赖,不方便更换环境部署。同时,不同项目使用的库版本可能不一致,全局安装会导致兼容性问题。另外,一些 webpack 加载器安装时,会提示没有找到 webpack 而报警! 56 | 57 | ## 使用 58 | 59 | webpack 是 react 的标准配置,将所有css、js、page打包成一个 bundle.js 文件,react本来就是将 html页面组件化,页面代码以js方式编写,特别适合 webpack 整体打包。一个bundle.js就相当于一个独立的 app 程序一样。 60 | 61 | 这种方式的优点是运行时,不用再下载页面,切换非常快,缺点是第一次运行加载的 bundle.js 文件大,需要比较长的时间。 62 | 63 | 对于非spa单页模式的传统多页web应用,如果 只是将 webpack 用来实现 js 模块化,该如何操作呢? 64 | 65 | js 模块化打包: 66 | 67 | - 将前端 js 模块化,抽出一些共性代码作为模块,减少 单个 js 大小。使用 webpack智能分析后打包成一个 bundle.js 文件! 68 | - 使用最新的 es6/7 的规范,提高编程效率。 69 | - 对前端 js 进行 类封装,避免变量、函数污染与冲突。 70 | - 打包后的文件,在 H5 浏览器中能正常执行,也就是说es6/7 要转换为 es5 版本。 71 | - 实现该目的的关键是 webpack.config.js,以及 babel 编译库,webpack 一定会有一种方法与 babel 结合,来调用 babel 库实现 ja版本转换。 72 | - 查找webpack说明,发现这个 转换就是 加载器,后面有专门介绍。 73 | - 编译完成后,发现 js 全部模块化了,在html页面中无法直接使用,如果要在 html或其他地方使用,需在入口文件中使用 window 输出相关变量或函数! 74 | - 不采用 window 输出,则需将 html 页面所有 js 放入入口js文件中,才能调用打包的变量或资源。 75 | 76 | ## webpack 配置文件 77 | 78 | webpack.config.js 79 | 80 | ```js 81 | /** 82 | * Created by way on 16/6/11. 83 | */ 84 | module.exports = { 85 | entry: {prodEdit: './src/js/prodEdit.js'}, 86 | output: { 87 | // path: __dirname, 88 | path: '/Users/way/prj/koa/koastart/public/js/', 89 | // filename: 'bundle.js' 90 | filename: '[name].js' 91 | }, 92 | module: { 93 | loaders: [ 94 | {test: /\.js$/, loader: 'babel', exclude: '/node_modules/'} 95 | ] 96 | }, 97 | resolve: { 98 | extensions: ['', '.js'] 99 | }, 100 | plugins: [] 101 | }; 102 | 103 | ``` 104 | 105 | ## 从html剥离的js文件示例 106 | 107 | ```js 108 | /** 109 | * Created by way on 16/6/11. 110 | * 应用的入口脚本 111 | */ 112 | import Etb from './editTable'; 113 | 114 | const _etSpec = new Etb(); 115 | const _etDesc = new Etb(); 116 | 117 | window.editDesc = tx => { 118 | _etDesc.editCell(tx); 119 | }; 120 | 121 | window.viewDesc = tx => { 122 | _etDesc.viewCell(tx); 123 | }; 124 | 125 | window.editSpec = tx => { 126 | _etSpec.editCell(tx); 127 | }; 128 | 129 | window.viewSpec = tx => { 130 | _etSpec.viewCell(tx); 131 | }; 132 | 133 | // 重新加载规格数据 134 | window.bindSpec = (tb, values) => { 135 | const names = ['SpecN1', 'SpecV1', 'SpecN2', 'SpecV2']; 136 | _etSpec.clearRow(tb); 137 | return _etSpec.addData(tb, names, values); 138 | }; 139 | 140 | // 重新加载详情数据 141 | window.bindDesc = (tb, values) => { 142 | const names = ['Desc']; 143 | _etDesc.clearRow(tb); 144 | return _etDesc.addData(tb, names, values); 145 | }; 146 | 147 | window.clearDesc = tb => { 148 | _etDesc.clearRow(tb); 149 | _etDesc.addRow(tb, '~~请点这里输入文字,点底部图标插入图片~~'); 150 | }; 151 | 152 | // 插入图片 153 | window.insImg = (tb, url) => { 154 | const txt = _etDesc.cutTxt(); 155 | if (txt.trim()) 156 | _etDesc.addTxt(tb, txt); 157 | _etDesc.addImg(tb, url); 158 | }; 159 | 160 | window.kdDesc = evt =>_etDesc.keyDown(evt); 161 | ``` 162 | 163 | ## babel-loader加载器 164 | 165 | >babel加载器就是通过babel库实现js 6、7的代码转换为 js 5,浏览器能正常执行! 166 | >其实通过 babel 自己也能完成转换,但是 babel自身并没有 分析 js中的引用、关联与依赖,后台代码,由于 node.js本身自带的模块化管理可直接使用,因此,后台代码并不需要 模块工具,但是前端部分,只能使用 webpack 这种工具进行依赖分析打包,确保所有的js打包到一个文件,否则,页面代码会以为缺少 模块而无法运行。 167 | 168 | 安装babel-core、babel-preset-es2015、babel-loader加载器: 169 | 170 | `npm i babel-core babel-preset-es2015 babel-loader –D` 171 | 172 | 淘宝npm:https://npm.taobao.org/package/babel-loader 173 | 174 | babel 加载器肯定需要 babel,这块还是 babel 的常规用法。 175 | babel 几个最常用的库: 176 | 177 | ``` 178 | "babel-polyfill": "^6.6.1", 179 | "babel-preset-es2015": "^6.5.0", 180 | "babel-preset-react": "^6.5.0", 181 | ``` 182 | babel-loader加载器使用 .babelrc 文件配置,这个配置文件,使用 bable编译时也有效! 183 | 184 | ``` 185 | { 186 | "presets": ["es2015"], 187 | "plugins": [ 188 | "syntax-object-rest-spread", 189 | "syntax-async-functions", 190 | "syntax-async-generators", 191 | "syntax-class-properties", 192 | "transform-async-to-generator", 193 | "transform-object-rest-spread", 194 | "transform-regenerator", 195 | "transform-strict-mode", 196 | "transform-class-properties" 197 | ] 198 | } 199 | ``` 200 | 201 | ## 使用 gulp 集成 webpack 自动打包 202 | 203 | 安装 gulp 环境,具体请参见 我的 gulp 笔记。 204 | 安装gulp webpack库: 205 | 206 | ``` 207 | npm i webpack-stream -D 208 | npm i vinyl-named -D 209 | ``` 210 | 211 | webpack-stream 详细说明:https://www.npmjs.com/package/webpack-stream 212 | 这个库在 windows 上执行,好像报错!!! 213 | 淘宝镜像:https://npm.taobao.org/package/webpack-stream 214 | 215 | 修改 webpack.config.js,屏蔽 entry 项,使用 gulp的 gulp.src 替代 entry 216 | 217 | ```js 218 | module.exports = { 219 | // entry: {prodEdit: './src/js/prodEdit.js'}, 220 | ``` 221 | 222 | 修改 gulpfile.js 223 | 224 | ```js 225 | var webpack = require('webpack-stream'); 226 | var named = require('vinyl-named'); 227 | var wpcfg = require('./webpack.config.js'); 228 | 229 | gulp.task('build', function () { 230 | 231 | gulp.src(['src/js/prodEdit.js', 'src/js/tool.js']) 232 | .pipe(named()) 233 | .pipe(webpack(wpcfg)) 234 | .pipe(tap(function(file, t){ 235 | var contents = file.contents.toString(); 236 | contents = contents.replace('${version}', pkg.version); 237 | file.contents = new Buffer(contents); 238 | })) 239 | .pipe(header(banner, { pkg : pkg } )) 240 | .pipe(gulp.dest(dst+'js')) 241 | .pipe(uglify()) 242 | .pipe(rename({suffix: '.min'})) 243 | .pipe(gulp.dest(dst + 'js')); 244 | } 245 | ``` 246 | 247 | gulp 自动生成 prodEdit.js、prodEdit.min.js, tool.tool.min.js,一个用于调试,一个是压缩的,用于生产环境! 248 | 249 | ## 有了gulp和webpack,还需要bower吗? 250 | 251 | 不是同一个level的工具。 252 | 253 | - gulp是工具链,可以配合各种插件做js压缩,css压缩,less编译等工作 254 | - webpack是文件打包工具,可以把项目的各种js文、css文件等打包合并成一个或多个文件 255 | - bower是包管理器,用来管理你项目里的那些外部依赖的。 256 | 所以是否还用bower,完全取决于你的需求。不要执着于是否用了gulp或者webpack 257 | 258 | webpack是一个比browserify功能更强大的模块加载器。既然是模块加载器,当然就包括对各种各样模块的加载,包括SASS/LESS/CoffeeScript/png/jpg等,以及webpack对于node_module模块加载已经非常完善了。 259 | 260 | 那么,为什么还需要bower呢?由于前端开发很多第三方模块并非都以标准npm包形式存在,有一些非主流,或者各种原因没放到npm上的包,可以在bower找到。 261 | 262 | 基于这个原因,使用webpack时候,凭着能用npm就用(依赖加载更加方便,功能更加强大),不能用的时候使用bower声明第三方模块依赖,然后使用js/css加载方式进行加载。 263 | 264 | 值得一提的是,webpack官方也提供非常便利的方式加载bower模块(模块的主要文件,被声明在bower.json main属性里面),通过配置后就可以很方便地沿用require来加载bower模块。 265 | 266 | 传送门:http://webpack.github.io/docs/usage-with-bower.html 267 | 268 | 269 | ## 多页面 js 规划 270 | 271 | - 将项目中公共部分js剥离出来,一个页面加载,多个页面共用,避免每个页面单重复加载。 272 | - 公共部分的js不宜过多,如果比较多,使用 gulp 合并打包,提高加载速度。 273 | - 页面个性化部分,每个页面加载独立的个性化js,该js文件需写入 gulpfile,生成最终独立的 js 文件! 274 | - 公共js部分,直接使用cdn加速器独立加载,使用 webpack的外部引用,引入模块使用。 275 | 276 | ## 外链 277 | 278 | Example with library from CDN: 279 | ```js 280 | 281 | 282 | // the artifial module "jquery" exports the global var "jQuery" 283 | externals: { jquery: "jQuery" } 284 | 285 | // inside any module 286 | var $ = require("jquery"); 287 | 288 | ``` 289 | 290 | Example with library included in bundle: 291 | 292 | ```js 293 | copy `jquery-git2.min.js` to your local filesystem 294 | 295 | // make "jquery" resolve to your local copy of the library 296 | // i. e. through the resolve.alias option 297 | resolve: { alias: { jquery: "/path/to/jquery-git2.min.js" } } 298 | 299 | // inside any module 300 | var $ = require("jquery"); 301 | ``` 302 | 303 | 也可以使用插件 304 | 305 | plugin ProvidePlugin 306 | This plugin makes a module available as variable in every module. The module is required only if you use the variable. 307 | 308 | Example: Make $ and jQuery available in every module without writing require("jquery"). 309 | ```js 310 | new webpack.ProvidePlugin({ 311 | $: "jquery", 312 | jQuery: "jquery", 313 | "window.jQuery": "jquery" 314 | }) 315 | ``` 316 | 317 | ## EXPORTING 输出 318 | 319 | The file doesn’t export its value. 320 | 321 | ### exports-loader 322 | 323 | `npm i exports-loader -D` 324 | 325 | This loader exports variables from inside the file. 326 | 327 | Examples: 328 | The file sets a variable in the global context with var XModule = .... 329 | `var XModule = require("exports?XModule!./file.js")` 330 | 331 | The file sets multiple variables in the global context with var XParser, Minimizer. 332 | ``` 333 | var XModule = require("exports?Parser=XParser&Minimizer!./file.js"); 334 | XModule.Parser; XModule.Minimizer` 335 | ``` 336 | The file sets a global variable with XModule = .... 337 | ``` 338 | require("imports?XModule=>undefined!exports?XModule!./file.js") ( 339 | import to not leak to the global context 340 | ) 341 | ``` 342 | The file sets a property on window window.XModule = .... 343 | ``` 344 | require("imports?window=>{}!exports?window.XModule!./file.js") 345 | ``` 346 | 347 | ## EXPOSING 暴露 348 | 349 | There are cases where you want a module to export itself to the global context. 350 | Don’t do this unless you really need this. (Better use the ProvidePlugin) 351 | 352 | ### expose-loader 353 | 354 | This loader exposes the exports to a module to the global context. 355 | 356 | `npm i expose-loader -D` 357 | 358 | Example: 359 | ``` 360 | module: { 361 | loaders: [ 362 | { test: /jquery\.js$/, loader: 'expose?$!expose?jQuery' } 363 | ] 364 | } 365 | ``` 366 | 367 | Expose file.js as XModule to the global context 368 | ``` 369 | require("expose?XModule!./file.js") 370 | Another Example: 371 | require('expose?$!expose?jQuery!jquery'); 372 | ... 373 | $(document).ready(function() { 374 | console.log("hey"); 375 | }) 376 | ``` 377 | 378 | By making Jquery available as a global namespace in our file containing Jquery code or the root file, it’s available to use Jquery everywhere in your project. This works very well if you plan to implement Bootstrap in your Webpack project. 379 | 380 | Note: Using too much global name-spacing will make your app less efficient. If you are planning to use a lot of global namespaces, consider implementing something like Babel runtime to your project. 381 | 382 | ## 参考资源 383 | 384 | - [webpack举例]https://github.com/ruanyf/webpack-demos 385 | - [WebPack实例与前端性能优化](https://segmentfault.com/a/1190000004577578) 386 | - [基于webpack的前端工程化开发之多页站点篇(一)](https://segmentfault.com/a/1190000004511992) 387 | - [基于webpack的前端工程化开发之多页站点篇(二)](https://segmentfault.com/a/1190000004516832) 388 | - [基于 Webpack 和 ES6 打造 JavaScript 类库](http://www.open-open.com/lib/view/open1452821009073.html) 389 | - [webpack + gulp 在前端中的应用](https://segmentfault.com/a/1190000005129121) 390 | - [gulp + webpack 构建多页面前端项目](http://www.open-open.com/news/view/1c51682) 391 | - [gulp + webpack 构建多页面前端项目](http://www.07net01.com/2015/11/967593.html) 392 | -------------------------------------------------------------------------------- /html/js2016.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |

js 2016发展趋势(必读)

12 |
13 |

本文由gaohailang翻译自State of the Art JavaScript in 2016,加上了部分译者的观点。就像是隧道终点前的光明,JS生态的最佳实践不再剧烈变更着,现在关于需要学什么越来越明确了。本文就关于核心类库,状态管理,语言特性,构建工具,CSS预处理,API & HTTP 类库,测试工具,依赖管理等等前端开发的方方面面进行了展望和梳理,为你挑出这些最佳实践和面向未来的设计~

14 |
15 |

那么,你要开始一个崭新的Javascript前端项目了,或者被之前老项目折腾半死,你也许并没有和改变进化步伐极快的社区生态保持技术实践的同步,或者你开始了,但是有大量的可选项不知道怎么选。React,Flux,Angular,Aurelia,Mocha,Jasmine,Jasmine,Babel,TypeScript,Flow。哦我的天呐这么多~ 为了让事件变得更简单,我们很多人正陷入一个陷阱:被我喜欢的XKCD漫画描述的很好:

16 |

js2016-1

17 |

是的,好消息是现在JS生态开始慢下来了,好项目开始冒出。最佳实践慢慢开始变得清晰了。工程师开始在现有项目上构建自己的工程还是重新创造轮子。

18 |

作为起点,下面是我对现代化Web应用各个部分的个人选择。一些选择看起来会有些争议,我会在每个选择后附上我的基本推理判断。要注意的是,这些选择通常是我建立在我目前对社区的观察和我个人的经历。你的看法当然会有不同~

19 |

核心类库:React

20 |

js2016-2

21 |

目前胜者很显然就是React(译者:你确定?!)

22 | 31 |

现在不少全能的大型框架如Ember,Angular,它们承诺说帮你处理所有的事。但是在React生态中,尽管需要对组件做一些决定(哈这就是你为什么要阅读本文的原因啦),但是这方案更强壮。很多其他框架,譬如Angular2.0正在快速追赶React。

32 |

『选择React不仅是个技术上的选择,更多是个商业决定!』

33 | 37 |

应用生命周期:Redux

38 |

js2016-3

39 |

PS: 以上不是它最终的logo

40 |

现在我们有了我们的视图和组件层,应用程序还需要管理数据状态和应用的生命周期。Redux也是毋容置疑的优胜者。

41 |

除了React,Facebook展示了名叫Flux的单向数据流的设计模式。Flux最早用来解决和简化应用的状态管理,但是随之而来,很多开发者提出了不少新的问题如如何存储数据状态和从哪发送Ajax请求。

42 |

为了解决这些问题,不少基于Flux模式之上的框架诞生了:Fluxible, Reflux, Alt, Flummox, Lux, Nuclear, Fluxxor 还有很多。

43 |

不过,这其中的类Flux的优雅实现最终赢得了社区的关注,它就是Redux。

44 |

最重要的是,学习Redux小菜一碟。它的作者,Dan Abranmov是一位非常棒的老师(他的教学视频非常易懂好学)。通过那些视频你很容易成为Redux的专家。我见见识到一组几乎没有任何React开发经验的工程师通过学习他的视频,在几周内就开发好能上线的React项目(代码质量也是顶级的)

45 |

Redux的生态系统和Redux本身一样优秀。从神乎其神的开发者工具到令人记忆深刻的reselect,Redux的社区是你最好的后盾。

46 |

不过有一点需要注意的是不要轻易的去尝试抽象Redux的项目模板。那些模板背后都是有意义有原因的。所以你尝试盲目修改前确保你已经使用过它和理解这样组织代码背后的原因。

47 |

语言:ES6配合Babel,先不加类型

48 |

js2016-4

49 |

不用再用CoffeeScript了(译者哭了出来,公司13年大规模的使用它,至今后端JS项目80%都是它的身影)。因为它的大部分好的特性在ES6都有了(它是JavaScript的标准语言规范),而且CoffeeScript的工具很弱(如CoffeeLint),它的社区也在快速的衰落。

50 |

ES6是语言的标准。它的大部分特性在最新的主流浏览器中已经被实现,Babel是个可插拔ES6编译器。把它配置到使用合适的预设目标(preset target,如es2015浏览器,es2015-node5),就可以开动了。

51 |

那么关于类型呢,TypeScript和Flow都给JavaScript提供了加上静态类型的功能,来配合编辑器提供更好的IDE支持和不需要测试就能捕获一些bug。不过我还是建议,先等等看,看看社区的进展和动向。

52 |

TypeScript做了很多工作让JavaScript写起来看起来非常像Java/C#,但它缺乏完善的现代化的类型系统特性如代数数据类型(它对你真正开始实操静态类型时是很重要的)。它也不像Flow那样很好的处理 nulls。

53 |

更新:TypeScript有union types也能覆盖很多用户开发场景。

54 |

Flow比起来似乎更强大,能捕获到更大范围的bug异常,但是比较难设置。在语言特性上,它比起Babel落后不少,在Windows上的支持也不好。

55 |

我要说些有争议性的话了:类型在前端开发中并没有我们想的那么重要(可能需要写一篇长文来讲述了)。所以就先等着类型系统变得更强健,目前先只使用Babel,同时关注下Flow~

56 |

格式和风格:ESlint配合Airbnb指南

57 |

js2016-5

58 |

关于ESLint异议也不大。使用它的React插件和良好的es6的支持,几乎非常完美完成lint的工作。JSLint是过时了,ESLint这个软件可以单独完成原本需要 JSHint 和 JSCS 联合起来做的事。

59 |

你需要配置他用你的风格约定。我强烈建议你使用 Airbnb的风格指南,大部分可以被 ESLint airbnb config 来严格约束实现。如果你们团队会在代码风格上产生分歧和争超,那么拿出这份指南来终结所有的不服!它也不是完美的(因为完美的风格不存在),但保持统一一致的代码风格是要高度推荐的。

60 |

一旦你开始熟悉它,我建议你开启更多的规则。在编辑撰写代码时候越多的捕获不规范(配置你的编辑器IDE使用上这个ESLint插件),就会避免分歧和在决定费神,从而让你和团队更加高效!

61 |

依赖管理:仅考虑NPM,CommonJS 和ES6模块

62 |

js2016-6

63 |

这一点很明确 - 就用NPM。所有东西,忘记之前的bower。类似与 Browserify 和 Webpack 的构建工具把npm的强大功能引到了web上。版本处理变得很简单,你也获得了node生态的大部分模块提供的功能。不过CSS的相关处理还是不够完美。

64 |

你可能会考虑的一件事:如何在开发服务器构建应用。不想Ruby社区的Bundler,npm 常使用通配符来指定版本号,导致你开始书写代码到最后部署时候版本号很可能已经变化了。使用 shrinkwrap 文件来锁定你的依赖(我建议使用 Uber的shrinkwrap 来获得更见一致性的输入)。同时考虑使用利用类似于 Sinopia 来构建自己的私有npm服务器。

65 |

Babel可以把 ES6 模块语法编译到CommonJS。意味着你可面向未来的语法,和在使用构建工具(如Webpack 2.0)时获得它支持的一些静态代码分析工具如 tree shaking 的优势

66 |

构建工具:Webpack

67 |

js2016-7

68 |

不想在你的页面文件中加入非常多的外链Script引用,那你就需要一个构建工具来打包你的依赖。如果你也需要允许npm包在浏览器运行工作的工具,那么Webpack就是你需要的。

69 |

一年前,关于这块还有不少选择。根据你的开发环境,你可以利用Rails的sprockets来解决类似问题。RequireJS,Browserify和Webpack都是以JavaScript基础的工具,现在RollupJS声称自己在ES6模块上处理的更好。

70 |

在一个个尝试使用后,我最终还是高度推荐Webpack:

71 | 81 |

Webpack目前也是处理大型SPA应用项目的最好方案,利用它的代码切割(code splitting)和懒加载特性。

82 |

不过它的学习曲线很陡峭,但是一点你掌握了,你还是会认为非常值得因为它的强大功能。

83 |

那么Gulp或Grunt呢? Webpack比起来最适合处理静态资源。所以他们开始可以用来跑一些其他的任务(但是也不推荐),现在更简单的方法是直接用上 npm scripts

84 |

测试:Mocha + Chai + Sinon(但没那么简单)

85 |

js2016-8

86 |

目前在 JavaScript 单元测试上,我们有众多选择,你选择任何一个都不会错太多。因为你开始做单元测试,你就走对一大步了。

87 |

一些选择包括了 Jasmine,Mocha,Tape,AVA 和 Jest。我知道我漏掉来一些,它们都有一些比其他做的好的地方。

88 |

我对一个测试框架的的选择标准是:

89 | 96 |

第一个指标让AVA脱颖而出(因为它的确做的非常棒)和Jest(自动Mocking并不像它说的那么好,因为它太慢了)

97 |

选择Jasmine,Mocha或Tape都不会差太多。我倾向于 Chai 断言因为它拥有很多插件,Sinon's mocks to Jasmine's built in construct。Mocha的异步测试支持很棒(你不用在写类似于 done callback之类的)。Chai as Promised 也是很屌。我强烈建议你使用 Dirty Chai 来避免一些让人头疼的问题。Webpack的 mocha loader 让你编码时自动执行测试。

98 |

对于React而言,Airbnb的Enzyme和Teaspoon(不是Rails那个!)是不错的相关工具选择。

99 |

我非常喜欢Mocha的特性和支持情况。如果你喜欢一些最小主义的,读读这篇关于tape的文章

100 |

PS: 101 | Facebook在最近的文章中说,它们是如何扩展Jest的。可能对大部分人来说过于复杂了,如果你有那些资源,不关心是否在浏览器中跑测试,那么它就很适合你。

102 |

另外,很多人认为我对AVA太武断了。不要误会我,AVA的确很棒。但我有个标准:全浏览器支持。这样我们可以直接从任何浏览器去执行(来测试跨浏览器兼容性)同时要方便调试。如果你不介意那些,你可以使用非常棒的iron-node来debugging。

103 |

工具库:Lodash是绝对王者,但留意 Ramda

104 |

JavaScript不像Java或.NET上有很多强大的内置工具集。所以你可能需要引入一个。

105 |

Lodash,目前来说应该是杂七杂八都有的首选。同时它类似注入懒求值这样的特性让它成为性能最高的选择之一。如果你不想用你就不要把它全部都导入,同时:lodash能让你仅仅引入哪些你需要的函数(这点尤其重要考虑到它现在变得越来越大)。随着4.x版本带来,它原生支持可选的函数式模式给那些函数式编程的极客们使用。来看看怎么使用它

106 |

如果你真的很喜欢函数式编程,那么不管怎么样,留意下优秀的Ramda。如果你决定用它,你可能还是需要引入一些lodash函数(Ramda目前专注于数据处理和函数式构建),但这样你能在JavaScript中以非常友好方式获得函数式编程的强大功能

107 |

Http请求:就只用fetch

108 |

许多React应用再也不需要jQuery了。除非你需要使用一些遗留的老旧的第三方组件(它依赖于jQuery),因为根本没必要。同时,意味着你需要一个类似于$.ajax的替代品。

109 |

为了保持简单,仅仅使用fetch,它在Firefox和Chrome中内建支持。对于其他浏览器,你可能需要引入polyfill。我推荐使用isomorphic-fetch 来在服务器端在内覆盖了基础组件选择。

110 |

还有一些其他好的类库选择如Axios,但目前在fetch之上没有多余需求。

111 |

为了更多关于为什么Promise是重要的讨论,请看我们博客异步代码

112 |

样式:考虑CSS模块

113 |

这是个我觉得相对发展较慢的领域。Sass就是目前的选择,使用node-sass是你JavaScript项目的不错开始、。我仍然觉得离最终最好的方案还是有很多不足。缺乏引用导入(如仅仅是从文件导入变量和mixin,而不用重新定义选择器和它的样式规则)和原生的URL重写(使它在保持线上代码足够精简就很困难)。node-sass是一个C写的类库,所以要对应好你的Node版本。

114 |

LESS并不受此影响,不过它缺了很多Sass的特性功能。

115 |

PostCSS 看起来更有生命力,它允许你构建自己的CSS预处理器。我推荐你使用它,即使你已经有了你喜欢的预处理器如SASS,它类似于AutoPrefixer使得你不需要要导入类似于Bourbon这样的大型依赖。

116 |

有一点需要特殊注意的是,CSS Modules。它限制了CSS的层叠部分,使得我们可以定义更加明确的依赖,来避免冲突。你再也不用担心Class名称一致导致的覆盖,也不用特意为了避免它而添加额外的前缀。它和React也配合的很好。有个不足:css-loader和css modules一起使用会导致非常缓慢,如果你的样式数量不少,那么在它优化之前还是避免使用它吧。

117 |

如果要我现在从头开始一个新项目,那么我大概会使用PostCSS配合一些我喜欢的预编译的CSS类库。

118 |

不管你选择什么,我还是推荐你看下我这篇文章CSS performance with Webpack,尤其你也在配套使用SASS。

119 |

前后同构:确保你真的需要它

120 |

Universal或Isometric的JavaScript代表着JavaScript写的代码可以被同时运行在客户端和服务器上。这需要用来在服务器端预先渲染页面来提升性能或SEO友好。感谢React,之前只有类似于Ebay或Facebook这样的巨型科技公司才能实施的方案,现在很多小的开发团队都能做到。不过它并不那么容易,它显著的加大了复杂性,限制了你类库和工具选择。

121 |

如果你在构建B2C的网站,类似于电商网站,那么你可能必须使用这个方案。但如果你是在做内部网站或者是B2B应用站点,那么这样的性能提升和SEO其实并不需要。所以和你的项目经理讨论下,看看是否有必要~

122 |

API接口:暂时没有好方案

123 |

看起来每个开发者最后都会疑问那么关于API接口呢?很多人会直接想到RESTful API(因为太流行了),同时SOAP真的成为过去式了。同时现在也有不少其他标准如:HATEOAS, JSON API,HAL,GraphQL

124 |

GraphQL 赋予客户端强大的能力(也是职责),允许它来实施任意的查询接口。结合Relay,它能为你处理客户端状态和缓存。在服务器端实施GraphQL看起来比较困难而且现有的文档大部分是针对Node.js的

125 |

网飞(NetFlix)的Falcor 看起来它也能提供那些Relay和GraphQL提供的功能,但是对于服务器端的实现要求很低。但现在它仅仅是开发者预览版没有正式发布。

126 |

所有这些有名的标准规范有他们各种的奇怪之处。一些是过于复杂,一些只能处理读取没有覆盖到更新接口。一些又严重和REST走失。许多人选择构建它们自己的,但是最终也要解决它们设计上带来的问题。

127 |

我不认为现在有什么方案是个大满贯(完美的),但是下面是我对API应该有的功能的一些思考:

128 | 135 |

我没有找到能覆盖这些需求的方案。如果有,务必让我知道。 136 | 同事考虑,如果你实施一个标准化的RESTful资源路径时,使用Swagger来文档化我们的API。

137 |

客户端软件:Electron

138 |

Electron 是Atom这个优秀编辑器的背后基石。你可以用它来构建自己的应用程序。它的核心,就是一个特殊版本的Node可以来打开Chrome窗口来渲染GUI页面,并且能够获取到操作系统底层的API(不用借助浏览器的安全沙箱等措施)。你可以打包你的应用程序像其他的桌面客户端软件那样分发安装包,并且辅以自动更新机制。

139 |

这就是用来构建横跨OSX,WIndows和Linux这多个桌面环境的应用软件的最简单的方式,利用起上面提到的所有好用的工具。它也有不错的文档和活跃的社区支持。

140 |

你也许也听过nw.js(之前叫node-webkit)它年事已高,Electron比它更稳健,更容易上手使用。

141 |

来使用这个模板项目来开搞自己的Electron,React和热更新项目吧,你可以看看这些东西是怎么相互配合工作的~

142 |

向谁学习,从哪学起

143 |

社区有一些大牛,你可以在Twitter,Weibo,掘金上关注他们。 144 | 还有不少好的文章和链接。

145 |

Removing user interface complexity, or why React is awesome 就是对了解React背后实现原理和原因的不错讲述。

146 |

如果你不需要,就别用它!

147 |

JavaScript生态区发展很快,欣欣向荣,在快速前进着。但是就像是隧道终点前的光明,最佳实践不在剧烈变更着。现在关于需要学什么越来越明确了。

148 |

最重要的是记住要保持简单,如无必要,勿增实体。

149 |

如果你的应用就是两三个页面,那你不需要用到 Router。如果就一个页面,那么你也不用Redux,只需要用React自己管理状态就好。你的应用就是简单的 CRUD 程序,那么不需要用到 Relay。你在学习 ES6 的语法,那么先别急着弄 Async/Await 或者装饰器。你准备开始学习 React 了,你不必要立马就去了解 Hot Reload 热更新和服务器端渲染。如果你刚刚使用上 Webpack,那么也别急着就来用代码切割(code splitting)和多代码块(multiple chunks)。如果你才开始 Redux,那么也不用匆忙用 Redux-Form 或 Redux-Sagas。

150 |

保持简单,一次学一样,你就不会像其他人一样抱怨JavaScript的破碎(Fatigue

151 |

我少了什么吗?

152 |

这就是我对目前JavaScript生态现状的看法和观点。如果你觉得我遗漏了那些类别的讨论,或者你认为我在一些选型上的决定不正确,你有更好的可以推荐。那么留言吧~

153 | -------------------------------------------------------------------------------- /eslint.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | eslint 13 | ====== 14 | 15 | 最好的js 静态风格、语法、错误检查及在线提示。 16 | 17 | >ESLint 由 JavaScript 红宝书 作者 Nicholas C. Zakas 编写, 2013 年发布第一个版本。 NCZ 的初衷不是重复造一个轮子,而是在际需求得不到 JSHint 团队响应 的情况下做出的选择:以可扩展、每条规则独立、不内置编码风格为理念编写一个 lint 工具。 18 | 19 | ## ESLint 主要有以下特点: 20 | 21 | - 默认规则包含所有 JSLint、JSHint 中存在的规则,易迁移 22 | - 规则可配置性高:可设置「警告」、「错误」两个 error 等级,或者直接禁用 23 | - 包含代码风格检测的规则(可以丢掉 JSCS 了) 24 | - 支持插件扩展、自定义规则 25 | - 支持JSX语法,而JSHint 不支持 JSX 语法 26 | 27 | ## 配置 28 | 29 | - 可以通过以下三种方式配置 ESLint: 30 | - 使用 .eslintrc 文件(支持 JSON 和 YAML 两种语法); 31 | - 在 package.json 中添加 eslintConfig 配置块; 32 | - 直接在代码文件中定义。 33 | 34 | ## 资源 35 | 36 | [官网](http://eslint.org) | 37 | [配置](http://eslint.org/docs/user-guide/configuring) | 38 | [规则](http://eslint.org/docs/rules/) | 39 | [贡献](http://eslint.org/docs/developer-guide/contributing) | 40 | [缺陷](http://eslint.org/docs/developer-guide/contributing/reporting-bugs) | 41 | [Code of Conduct](https://jquery.org/conduct/) | 42 | [Twitter](https://twitter.com/geteslint) | 43 | [邮件列表](https://groups.google.com/group/eslint) | 44 | [聊天室](https://gitter.im/eslint/eslint) 45 | 46 | ## 安装 47 | npm install -g eslint 48 | 49 | ## 使用 50 | 51 | - 创建 .eslintrc文件 52 | eslint --init 53 | - 检查js文件 54 | eslint test.js test2.js 55 | - js 版本:JSX Harmoney,最大限度支持新语法 56 | - ESLint:Java Script 的 代码质量工具中开启 ESLint,提供代码编写规范检查 57 | eslint 库路径设置,如:/Users/way/prj/koa/koastart/node_modules/eslint 58 | 59 | ## 配置 60 | 61 | 修改 `.eslintrc` 文件,定义规则 62 | 63 | ```json 64 | { 65 | "rules": { 66 | "semi": ["error", "always"], 67 | "quotes": ["error", "double"] 68 | } 69 | } 70 | ``` 71 | 72 | `"semi"` 和 `"quotes"` 预定义的规则名称[rules](http://eslint.org/docs/rules) 73 | 第一个值是提示级别 74 | * `"off"` or `0` - 关闭 75 | * `"warn"` or `1` - 警告 76 | * `"error"` or `2` - 错误 77 | 78 | 详细说明请参见[配置说明](http://eslint.org/docs/user-guide/configuring))。 79 | 80 | ## 本项目使用的 .eslintrc 文件 81 | 82 | - 继承 eslint-config-airbnb/base 83 | - 需安装以下插件 84 | ```js 85 | "eslint": "^2.9.0", 86 | "eslint-config-airbnb": "^9.0.1", 87 | "eslint-plugin-import": "^1.8.0", 88 | "eslint-plugin-jsx-a11y": "^1.2.0", 89 | "eslint-plugin-react": "^5.1.1", 90 | 91 | ``` 92 | - 文件内容 93 | ```js 94 | { 95 | "extends": "eslint-config-airbnb/base", 96 | "parser": "babel-eslint", 97 | "env": { 98 | "browser": true, 99 | "node": true, 100 | "mocha": true 101 | }, 102 | "rules": { 103 | // Disable for console/alert 104 | "no-console": 0, 105 | "no-alert": 0, 106 | 107 | "indent": [2, 2, {"SwitchCase": 1}], 108 | "object-curly-spacing": 0 109 | }, 110 | "plugins": [ 111 | "import" 112 | ], 113 | "settings": { 114 | "import/parser": "babel-eslint", 115 | "import/resolve": { 116 | "moduleDirectory": ["node_modules", "src"] 117 | } 118 | }, 119 | "globals": { 120 | "__DEV__": true, 121 | "__OPTION__": true 122 | } 123 | } 124 | ``` 125 | 126 | ## 以下是详细 .eslintrc 文件示例和解释: 127 | 128 | ```js 129 | { 130 | "env": { 131 | "browser": true, 132 | "node": true, 133 | "commonjs": true 134 | }, 135 | "ecmaFeatures": { 136 | // lambda表达式 137 | "arrowFunctions": true, 138 | // 解构赋值 139 | "destructuring": true, 140 | // class 141 | "classes": true, 142 | // http://es6.ruanyifeng.com/#docs/function#函数参数的默认值 143 | "defaultParams": true, 144 | // 块级作用域,允许使用let const 145 | "blockBindings": true, 146 | // 允许使用模块,模块内默认严格模式 147 | "modules": true, 148 | // 允许字面量定义对象时,用表达式做属性名 149 | // http://es6.ruanyifeng.com/#docs/object#属性名表达式 150 | "objectLiteralComputedProperties": true, 151 | // 允许对象字面量方法名简写 152 | /*var o = { 153 | method() { 154 | return "Hello!"; 155 | } 156 | }; 157 | 158 | 等同于 159 | 160 | var o = { 161 | method: function() { 162 | return "Hello!"; 163 | } 164 | }; 165 | */ 166 | "objectLiteralShorthandMethods": true, 167 | /* 168 | 对象字面量属性名简写 169 | var foo = 'bar'; 170 | var baz = {foo}; 171 | baz // {foo: "bar"} 172 | 173 | // 等同于 174 | var baz = {foo: foo}; 175 | */ 176 | "objectLiteralShorthandProperties": true, 177 | // http://es6.ruanyifeng.com/#docs/function#rest参数 178 | "restParams": true, 179 | // http://es6.ruanyifeng.com/#docs/function#扩展运算符 180 | "spread": true, 181 | // http://es6.ruanyifeng.com/#docs/iterator#for---of循环 182 | "forOf": true, 183 | // http://es6.ruanyifeng.com/#docs/generator 184 | "generators": true, 185 | // http://es6.ruanyifeng.com/#docs/string#模板字符串 186 | "templateStrings": true, 187 | "superInFunctions": true, 188 | // http://es6.ruanyifeng.com/#docs/object#对象的扩展运算符 189 | "experimentalObjectRestSpread": true 190 | }, 191 | 192 | "rules": { 193 | // 定义对象的set存取器属性时,强制定义get 194 | "accessor-pairs": 2, 195 | // 指定数组的元素之间要以空格隔开(,后面), never参数:[ 之前和 ] 之后不能带空格,always参数:[ 之前和 ] 之后必须带空格 196 | "array-bracket-spacing": [2, "never"], 197 | // 在块级作用域外访问块内定义的变量是否报错提示 198 | "block-scoped-var": 0, 199 | // if while function 后面的{必须与if在同一行,java风格。 200 | "brace-style": [2, "1tbs", { "allowSingleLine": true }], 201 | // 双峰驼命名格式 202 | "camelcase": 2, 203 | // 数组和对象键值对最后一个逗号, never参数:不能带末尾的逗号, always参数:必须带末尾的逗号, 204 | // always-multiline:多行模式必须带逗号,单行模式不能带逗号 205 | "comma-dangle": [2, "never"], 206 | // 控制逗号前后的空格 207 | "comma-spacing": [2, { "before": false, "after": true }], 208 | // 控制逗号在行尾出现还是在行首出现 209 | // http://eslint.org/docs/rules/comma-style 210 | "comma-style": [2, "last"], 211 | // 圈复杂度 212 | "complexity": [2,9], 213 | // 以方括号取对象属性时,[ 后面和 ] 前面是否需要空格, 可选参数 never, always 214 | "computed-property-spacing": [2,"never"], 215 | // 强制方法必须返回值,TypeScript强类型,不配置 216 | "consistent-return": 0, 217 | // 用于指统一在回调函数中指向this的变量名,箭头函数中的this已经可以指向外层调用者,应该没卵用了 218 | // e.g [0,"that"] 指定只能 var that = this. that不能指向其他任何值,this也不能赋值给that以外的其他值 219 | "consistent-this": 0, 220 | // 强制在子类构造函数中用super()调用父类构造函数,TypeScrip的编译器也会提示 221 | "constructor-super": 0, 222 | // if else while for do后面的代码块是否需要{ }包围,参数: 223 | // multi 只有块中有多行语句时才需要{ }包围 224 | // multi-line 只有块中有多行语句时才需要{ }包围, 但是块中的执行语句只有一行时, 225 | // 块中的语句只能跟和if语句在同一行。if (foo) foo++; else doSomething(); 226 | // multi-or-nest 只有块中有多行语句时才需要{ }包围, 如果块中的执行语句只有一行,执行语句可以零另起一行也可以跟在if语句后面 227 | // [2, "multi", "consistent"] 保持前后语句的{ }一致 228 | // default: [2, "all"] 全都需要{ }包围 229 | "curly": [2, "all"], 230 | // switch语句强制default分支,也可添加 // no default 注释取消此次警告 231 | "default-case": 2, 232 | // 强制object.key 中 . 的位置,参数: 233 | // property,'.'号应与属性在同一行 234 | // object, '.' 号应与对象名在同一行 235 | "dot-location": [2, "property"], 236 | // 强制使用.号取属性 237 | // 参数: allowKeywords:true 使用保留字做属性名时,只能使用.方式取属性 238 | // false 使用保留字做属性名时, 只能使用[]方式取属性 e.g [2, {"allowKeywords": false}] 239 | // allowPattern: 当属性名匹配提供的正则表达式时,允许使用[]方式取值,否则只能用.号取值 e.g [2, {"allowPattern": "^[a-z]+(_[a-z]+)+$"}] 240 | "dot-notation": [2, {"allowKeywords": true}], 241 | // 文件末尾强制换行 242 | "eol-last": 2, 243 | // 使用 === 替代 == 244 | "eqeqeq": [2, "allow-null"], 245 | // 方法表达式是否需要命名 246 | "func-names": 0, 247 | // 方法定义风格,参数: 248 | // declaration: 强制使用方法声明的方式,function f(){} e.g [2, "declaration"] 249 | // expression:强制使用方法表达式的方式,var f = function() {} e.g [2, "expression"] 250 | // allowArrowFunctions: declaration风格中允许箭头函数。 e.g [2, "declaration", { "allowArrowFunctions": true }] 251 | "func-style": 0, 252 | "generator-star-spacing": [2, { "before": true, "after": true }], 253 | "guard-for-in": 0, 254 | "handle-callback-err": [2, "^(err|error)$" ], 255 | "indent": [2, 2, { "SwitchCase": 1 }], 256 | "key-spacing": [2, { "beforeColon": false, "afterColon": true }], 257 | "linebreak-style": 0, 258 | "lines-around-comment": 0, 259 | "max-nested-callbacks": 0, 260 | "new-cap": [2, { "newIsCap": true, "capIsNew": false }], 261 | "new-parens": 2, 262 | "newline-after-var": 0, 263 | "no-alert": 0, 264 | "no-array-constructor": 2, 265 | "no-caller": 2, 266 | "no-catch-shadow": 0, 267 | "no-cond-assign": 2, 268 | "no-console": 0, 269 | "no-constant-condition": 0, 270 | "no-continue": 0, 271 | "no-control-regex": 2, 272 | "no-debugger": 2, 273 | "no-delete-var": 2, 274 | "no-div-regex": 0, 275 | "no-dupe-args": 2, 276 | "no-dupe-keys": 2, 277 | "no-duplicate-case": 2, 278 | "no-else-return": 0, 279 | "no-empty": 0, 280 | "no-empty-character-class": 2, 281 | "no-empty-label": 2, 282 | "no-eq-null": 0, 283 | "no-eval": 2, 284 | "no-ex-assign": 2, 285 | "no-extend-native": 2, 286 | "no-extra-bind": 2, 287 | "no-extra-boolean-cast": 2, 288 | "no-extra-parens": 0, 289 | "no-extra-semi": 0, 290 | "no-fallthrough": 2, 291 | "no-floating-decimal": 2, 292 | "no-func-assign": 2, 293 | "no-implied-eval": 2, 294 | "no-inline-comments": 0, 295 | "no-inner-declarations": [2, "functions"], 296 | "no-invalid-regexp": 2, 297 | "no-irregular-whitespace": 2, 298 | "no-iterator": 2, 299 | "no-label-var": 2, 300 | "no-labels": 2, 301 | "no-lone-blocks": 2, 302 | "no-lonely-if": 0, 303 | "no-loop-func": 0, 304 | "no-mixed-requires": 0, 305 | "no-mixed-spaces-and-tabs": 2, 306 | "no-multi-spaces": 2, 307 | "no-multi-str": 2, 308 | "no-multiple-empty-lines": [2, { "max": 1 }], 309 | "no-native-reassign": 2, 310 | "no-negated-in-lhs": 2, 311 | "no-nested-ternary": 0, 312 | "no-new": 2, 313 | "no-new-func": 0, 314 | "no-new-object": 2, 315 | "no-new-require": 2, 316 | "no-new-wrappers": 2, 317 | "no-obj-calls": 2, 318 | "no-octal": 2, 319 | "no-octal-escape": 2, 320 | "no-param-reassign": 0, 321 | "no-path-concat": 0, 322 | "no-process-env": 0, 323 | "no-process-exit": 0, 324 | "no-proto": 0, 325 | "no-redeclare": 2, 326 | "no-regex-spaces": 2, 327 | "no-restricted-modules": 0, 328 | "no-return-assign": 2, 329 | "no-script-url": 0, 330 | "no-self-compare": 2, 331 | "no-sequences": 2, 332 | "no-shadow": 0, 333 | "no-shadow-restricted-names": 2, 334 | "no-spaced-func": 2, 335 | "no-sparse-arrays": 2, 336 | "no-sync": 0, 337 | "no-ternary": 0, 338 | "no-this-before-super": 2, 339 | "no-throw-literal": 2, 340 | "no-trailing-spaces": 2, 341 | "no-undef": 2, 342 | "no-undef-init": 2, 343 | "no-undefined": 0, 344 | "no-underscore-dangle": 0, 345 | "no-unexpected-multiline": 2, 346 | "no-unneeded-ternary": 2, 347 | "no-unreachable": 2, 348 | "no-unused-expressions": 0, 349 | "no-unused-vars": [2, { "vars": "all", "args": "none" }], 350 | "no-use-before-define": 0, 351 | "no-var": 0, 352 | "no-void": 0, 353 | "no-warning-comments": 0, 354 | "no-with": 2, 355 | "object-curly-spacing": 0, 356 | "object-shorthand": 0, 357 | "one-var": [2, { "initialized": "never" }], 358 | "operator-assignment": 0, 359 | "operator-linebreak": [2, "after", { "overrides": { "?": "before", ":": "before" } }], 360 | "padded-blocks": 0, 361 | "prefer-const": 0, 362 | "quote-props": 0, 363 | "quotes": [2, "single", "avoid-escape"], 364 | "radix": 2, 365 | "semi": [2, "never"], 366 | "semi-spacing": 0, 367 | "sort-vars": 0, 368 | "space-after-keywords": [2, "always"], 369 | "space-before-blocks": [2, "always"], 370 | "space-before-function-paren": [2, "always"], 371 | "space-in-parens": [2, "never"], 372 | "space-infix-ops": 2, 373 | "space-return-throw-case": 2, 374 | "space-unary-ops": [2, { "words": true, "nonwords": false }], 375 | "spaced-comment": [2, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!"] }], 376 | "strict": 0, 377 | "use-isnan": 2, 378 | "valid-jsdoc": 0, 379 | "valid-typeof": 2, 380 | "vars-on-top": 0, 381 | "wrap-iife": [2, "any"], 382 | "wrap-regex": 0, 383 | "yoda": [2, "never"] 384 | } 385 | } 386 | ``` -------------------------------------------------------------------------------- /npm.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | - [NPM是什么](#npm) 14 | - [我们需要了解什么](#) 15 | - [本地安装 vs 全局安装](#-vs-) 16 | - [本地安装](#) 17 | - [全局安装](#) 18 | - [本地路径安装](#) 19 | - [依赖项自动安装](#) 20 | - [指定版本号安装](#) 21 | - [安装其它指令](#) 22 | - [卸载](#) 23 | - [npm包管理](#npm) 24 | - [查看](#) 25 | - [npm发布](#npm) 26 | - [NPM配置](#npm) 27 | - [设置proxy](#proxy) 28 | - [查看proxy](#proxy) 29 | - [删除proxy](#proxy) 30 | - [查看所有配置](#) 31 | - [关于package.json](#packagejson) 32 | - [package版本](#package) 33 | - [常见版本声明形式](#) 34 | - [版本书写要求](#) 35 | - [npm 自动化](#npm-) 36 | - [script](#script) 37 | - [构建javascript](#javascript) 38 | - [监视 javascript](#-javascript) 39 | - [构建CSS](#css) 40 | - [监视CSS](#css) 41 | - [序列化子任务](#) 42 | - [并行子任务](#) 43 | - [完整的package.json例子](#packagejson) 44 | - [当事情变得非常复杂的时候](#) 45 | - [!/bin/bash](#binbash) 46 | - [Windows](#windows) 47 | - [总结](#) 48 | 49 | ![](git/nodenpm.png) 50 | 51 | npm 52 | === 53 | 54 | NPM是什么 55 | --------- 56 | 57 | NPM(node package manager),通常称为node包管理器。顾名思义,它的主要功能就是管理node包,包括:安装、卸载、更新、查看、搜索、发布等。 58 | 59 | npm的背后,是基于couchdb的一个数据库,详细记录了每个包的信息,包括作者、版本、依赖、授权信息等。它的一个很重要的作用就是:将开发者从繁琐的包管理工作(版本、依赖等)中解放出来,更加专注于功能的开发。 60 | 61 | npm官网:https://npmjs.org/ 62 | 63 | npm官方文档:https://npmjs.org/doc/README.html 64 | 65 | 我们需要了解什么 66 | ---------------- 67 | 68 | - npm的安装、卸载、升级、配置 69 | - npm的使用:package的安装、卸载、升级、查看、搜索、发布 70 | - npm包的安装模式:本地 vs 全局 71 | - package.json:包描述信息 72 | - package版本:常见版本声明形式 73 | - npm包安装模式 74 | 75 | 本地安装 vs 全局安装 76 | -------------------- 77 | 78 | 在具体介绍npm包的管理之前,我们首先得来了解一下npm包的两种安装模式。 79 | 80 | node包的安装分两种:本地安装、全局安装。两者的区别如下,后面会通过简单例子说明 81 | 82 | ###本地安装 指令:npm install|i pkg package会被下载到当前所在目录,也只能在当前目录下使用。 运行如下命令,就会在当前目录下安装grunt-cli(grunt命令行工具) 83 | 84 | npm install grunt-cli 安装结束后,当前目录下回多出一个node_modules目录,grunt-cli就安装在里面。同时注意控制台输出的信息:`js 85 | grunt-cli@0.1.9 node_modules/grunt-cli 86 | ├── resolve@0.3.1 87 | ├── nopt@1.0.10 (abbrev@1.0.4) 88 | └── findup-sync@0.1.2 (lodash@1.0.1, glob@3.1.21) 89 | ` 简单说明一下:* grunt-cli@0.1.9:当前安装的package为grunt-cli,版本为0.19* node_modules/grunt-cli:安装目录* resolve@0.3.1:依赖的包有resolve、nopt、findup-sync,它们各自的版本、依赖在后面的括号里列出来 90 | 91 | ###全局安装 指令:npm install|i -g pkg package会被下载到到特定的系统目录下,安装的package能够在所有目录下使用。 上面已经安装了grunt-cli,然后你跑到其他目录下面运行如下命令 92 | 93 | grunt 果断提示你grunt命令不存在,为什么呢?因为上面只是进行了本地安装,grunt命令只能在对应安装目录下使用。 94 | 95 | -bash: grunt: command not found 如果为了使用grunt命令,每到一个目录下都得重新安装一次,那不抓狂才怪。肿么办呢? 96 | 97 | 很简单,采用全局安装就行了,很简单,加上参数-g就可以了 98 | 99 | npm install -g grunt-cli 于是,在所有目录下都可以无压力使用grunt命令了。这个时候,你会注意到控制台输入的信息有点不同。主要的区别在于安装目录,现在变成了`/usr/local/lib/node_modules/grunt-cli` 100 | `/usr/local/lib/node_modules/` 也就是之前所说的全局安装目录啦。` 101 | grunt-cli@0.1.9 /usr/local/lib/node_modules/grunt-cli 102 | ├── resolve@0.3.1 103 | ├── nopt@1.0.10 (abbrev@1.0.4) 104 | └── findup-sync@0.1.2 (lodash@1.0.1, glob@3.1.21) 105 | ` 106 | 107 | ### 本地路径安装 108 | 109 | 指令:npm install|i 路径或zip包 110 | 将包下载到本地后,指定路径即可安装 111 | 112 | ### 依赖项自动安装 113 | 114 | 指令:npm install|i 115 | 在局部 package.json的路径,直接运行上述指令,则按package.json中指定的依赖项自动安装。 116 | 117 | ### 指定版本号安装 118 | 119 | 指令:npm install grunt-cli@"0.1.9" 120 | 安装最新版本的grunt-cli 121 | 不带版本号,安装最新版本 122 | 123 | ### 安装其它指令 124 | 125 | npm install --help 126 | 输出如下,有兴趣的童鞋可以了解下 127 | 128 | - npm install 129 | - npm install 130 | - npm install 131 | - npm install 132 | - npm install @ 133 | - npm install @ 134 | - npm install @ 135 | - 卸载grunt-cli 136 | 137 | ### 卸载 138 | 139 | 比如卸载grunt-cli 140 | npm uninstall grunt-cli 141 | 卸载0.1.9版本的grunt-cli 142 | npm uninstall grunt-cli@"0.1.9" 143 | 144 | ## link 145 | 146 | - 进入该模块,使用 link指令,即可实现全局调用:cmd 使用管理员权限运行,否则link失败。 147 | - 在该目录:C:\Program Files\iojs\node_modules\npm\node_modules\node-gyp,执行 link指令即可将该模块链接到全局路径 148 | - 全局路径 C:\Users\walter\AppData\Roaming\npm\node_modules\node-gyp 有了该包,可全局调用! 149 | - npm link 指定模块,如“coffee-script”,可将该全局模块链接到项目,而不是拷贝安装 150 | - 链接的好处是,原模块更新后,link的模块,自动更新,如果是 拷贝安装,则原模块更新,拷贝安装的模块不会更新! 151 | 152 | 153 | ## npm link引起的Cannot find module 'jade'错误 154 | 155 | 在一个express3项目中,express模块是用npm link链向了全局目录下的express模块,jade还是在项目本地的node_modules中,在运行的时候出现 Cannot find module ‘jade’ 错误。 156 | 157 | 按说不管是用软链接指向全局目录的还是安装在本地模块目录的都应该能找到才对,怎么会出现模块找不到的问题呢,查了一下才发现,原来是express的模版引擎调用机制的问题,它会按自己所在目录的相对位置来查找模版引擎模块(如jade),我们实际使用的express模块在全局目录,所以express会在全局目录里面找jade模块,找不到就会报错。 158 | 159 | 解决办法: 160 | 161 | 将express和模版引擎模块安装在同一个目录,或者都在全局目录,或者都在项目本地模块目录,这样就能正确调用了。 162 | 163 | npm包管理 164 | --------- 165 | 166 | npm的包管理命令是使用频率最高的,所以也是我们需要牢牢记住并熟练使用的。其实无非也就是几个动作:安装、卸载、更新、查看、搜索、发布等。 167 | 168 | ### 查看 169 | 170 | npm ls:查看安装了哪些包 171 | 运行如下命令,就可以查看当前目录安装了哪些package 输出如下` 172 | /private/tmp/npm 173 | └─┬ grunt-cli@0.1.9 174 | ├─┬ findup-sync@0.1.2 175 | │ ├─┬ glob@3.1.21 176 | │ │ ├── graceful-fs@1.2.3 177 | │ │ ├── inherits@1.0.0 178 | │ │ └─┬ minimatch@0.2.12 179 | │ │ ├── lru-cache@2.3.0 180 | │ │ └── sigmund@1.0.0 181 | │ └── lodash@1.0.1 182 | ├─┬ nopt@1.0.10 183 | │ └── abbrev@1.0.4 184 | └── resolve@0.3.1 185 | ` 输出如下,同样,如果是要查看package的全局安装信息,加上-g就可以 186 | 187 | npm ls pkg:查看特定package的信息 运行如下命令,输出grunt-cli的信息 188 | 189 | npm ls grunt-cli 输出的信息比较有限,只有安装目录、版本,如下:` 190 | /private/tmp/npm 191 | └── grunt-cli@0.1.9 192 | ` 如果要查看更详细信息,可以通过npm info pkg,输出的信息非常详尽,包括作者、版本、依赖等。 193 | npm info grunt-cli npm update pkg:package更新 194 | 195 | 更新:npm update grunt-cli 搜索:npm search pgk 输入如下命令 196 | npm search grunt-cli 返回结果如下 197 | ` 198 | npm http GET http://registry.npmjs.org/-/all/since?stale=update_after&startkey=1375519407838 199 | npm http 200 http://registry.npmjs.org/-/all/since?stale=update_after&startkey=1375519407838 200 | NAME DESCRIPTION AUTHOR DATE KEYWORDS 201 | grunt-cli The grunt command line interface. =cowboy =tkellen 2013-07-27 02:24 202 | grunt-cli-dev-exitprocess The grunt command line interface. =dnevnik 2013-03-11 16:19 203 | grunt-client-compiler Grunt wrapper for client-compiler. =rubenv 2013-03-26 09:15 gruntplugin 204 | grunt-clientside Generate clientside js code from CommonJS modules =jga 2012-11-07 01:20 gruntplugin 205 | ` 206 | 207 | npm发布 208 | ------- 209 | 210 | 这个命令我自己也还没实际用过,不误导大家,语法如下,也可参考官方对于package发布的说明https://npmjs.org/doc/developers.html: 211 | 212 | npm publish npm publish 213 | 214 | NPM配置 215 | ------- 216 | 217 | npm的配置工作主要是通过npm config命令,主要包含增、删、改、查几个步骤,下面就以最为常用的proxy配置为例。 218 | 219 | ### 设置proxy 220 | 221 | 内网使用npm很头痛的一个问题就是代理,假设我们的代理是 `http://proxy.example.com:8080`,那么命令如下:`js 222 | npm config set proxy http://proxy.example.com:8080 223 | ` 由于npm config set命令比较常用,于是可以如下简写` 224 | npm set proxy http://proxy.example.com:8080 225 | ` 226 | 227 | ### 查看proxy 228 | 229 | 设置完,我们查看下当前代理设置 230 | 231 | npm config get proxy 输出如下:` 232 | http://proxy.example.com:8080/ 233 | ` 同样可如下简写: 234 | npm get proxy 235 | 236 | ### 删除proxy 237 | 238 | 代理不需要用到了,那删了吧` 239 | npm delete proxy 240 | ` 241 | 242 | ### 查看所有配置 243 | 244 | npm config list 245 | 直接修改配置文件 有时候觉得一条配置一条配置地修改有些麻烦,就直接进配置文件修改了 246 | npm config edit 247 | 248 | 关于package.json 249 | ---------------- 250 | 251 | 包的描述信息啦。假设当我们下载了node应用,这个node应用依赖于A、B、C三个包,如果没有package.json,我们需要人肉安装这个三个包(如果对版本有特定要求就更悲剧了):* npm install A* npm install B* npm install C 有了package.json,一行命令安装所有依赖。 252 | 253 | npm install package.json字段简介 字段相当多,但最重要的的是下面几个* name: package的名字(由于他会成为url的一部分,所以 non-url-safe 的字母不会通过,也不允许出现"."、"_"),最好先在 http://registry.npmjs.org/ 上搜下你取的名字是否已经存在* version: package的版本,当package发生变化时,version也应该跟着一起变化,同时,你声明的版本需要通过semver的校验(semver可自行谷歌)* dependencies: package的应用依赖模块,即别人要使用这个package,至少需要安装哪些东东。应用依赖模块会安装到当前模块的node_modules目录下。* devDependencies:package的开发依赖模块,即别人要在这个package上进行开发* 其他:参见官网 254 | 255 | ### package版本 256 | 257 | 在package.json里,你经常会在包名后看到类似"~0.1.0"这样的字符串,这就是包的版本啦。下面会列举最常见的版本声明形式,以及版本书写的要求。 258 | 259 | 使用install --save时,会将该安装包写入 package.json中,并添加小尖尖(^)而不是小波浪(~)作为依赖版本的前缀。 260 | 261 | #### 常见版本声明形式 262 | 263 | 1. "~1.2.3"匹配中间的数字 264 | ` 265 | "~1.2.3" = ">=1.2.3 <1.3.0" 266 | "~1.2" = ">=1.2.0 <1.3.0" 267 | "~1" = ">=1.0.0 <1.1.0" 268 | ` 269 | 2. "1.x.x"匹配x位置数字 270 | ` 271 | "1.2.x" = ">=1.2.0 <1.3.0" 272 | "1.x.x" = ">=1.0.0 <2.0.0" 273 | "1.2" = "1.2.x" 274 | "1.x" = "1.x.x" 275 | "1" = "1.x.x" 276 | ` 277 | 3. "^1.x.x"匹配第一个数字 278 | ` 279 | "co": "^4.1.0", = >=4 <5 280 | "koa": "^2.0.0", 281 | ` 282 | 283 | 284 | ### 它们有什么区别呢?简单来说: 285 | 286 | - ~会匹配最新的子版本(中间那个数字),比如~1.2.3会匹配所有的1.2.x版本,但不匹配到1.3.0及以上 287 | - ^会匹配最新的主版本(第一个数字),比如^1.2.3将会匹配所有的1.x.x版本,2.0.0就缓缓飘过了。 288 | - 附上版本控制的其他范围: 289 | version 必须严格匹配到 version 版本 290 | >version 必须大于 version 的版本 291 | >=version 大于等于 version 的版本 292 | =version1 <=version2. 301 | range1 || range2 range1 或者 range2 的任一版本. 302 | git... 以GIT地址作为依赖 303 | user/repo 以GitHub地址作为依赖 304 | tag 匹配一个以 tag 标记并发布的版本,参见 npm-tag(1) 305 | path/path/path 以本地地址作为依赖 306 | 307 | 308 | #### 版本书写要求 309 | 310 | 版本可以v开头,比如 v1.0.1(v只是可选), 1.0.1-7,这里的7是所谓的“构建版本号”,不理是神马,反正版本大于1.0.1 1.0.1beta,或者1.0.1-beta,如果1.0.1后面不是 “连字符加数字” 这种形式,那么它是pre release 版本,即版本小于 1.0.1 根据b、c,有:0.1.2-7 > 0.1.2-7-beta > 0.1.2-6 > 0.1.2 > 0.1.2beta 写在后面 311 | 312 | npm 自动化 313 | ---------- 314 | 315 | ### script 316 | 317 | npm 会在项目的`package.json`文件中寻找`scripts`区域,其中包括`npm test`和`npm start`等命令。 318 | 319 | 其实`npm test`和`npm start`是`npm run test`和`npm run start`的简写。事实上,你可以使用npm run来运行scripts里的任何条目。 320 | 321 | 使用`npm run`的方便之处在于,npm会自动把`node_modules/.bin`加入$PATH,这样你可以直接运行依赖程序和开发依赖程序,不用全局安装了。只要npm上的包提供命令行接口,你就可以直接使用它们,方便吧?当然,你总是可以自己写一个简单的小程序。 322 | 323 | ### 构建javascript 324 | 325 | 为了便于组织代码和利用npm上的包,写代码的时候往往使用`module.exports和require()。browserify`可以将这些一起打包成单一的脚本。使用`browserify`很简单,只需在package.json中加入一个['build-js']条目,类似这样:` 326 | "build-js": "browserify browser/main.js > static/bundle.js" 327 | ` 如果是用于生产环境,还需要压缩一下。我们只需要将uglify-js加入devDependency,然后直接通过管道传递一下即可:` 328 | "build-js": "browserify browser/main.js | uglifyjs -mc > static/bundle.js" 329 | ` 330 | 331 | ### 监视 javascript 332 | 333 | 为了能在修改文件之后自动重新生成javascript文件,只需将上面的browserify命令换成watchify并加上一些参数。` 334 | "watch-js": "watchify browser/main.js -o static/bundle.js -dv" 335 | ` 这里加了-d和-v两个参数,这样就可以看到详细的调试信息。 336 | 337 | ### 构建CSS 338 | 339 | 用cat就可以搞定:` 340 | "build-css": "cat static/pages/*.css tabs/*/*.css > static/bundle.css" 341 | ` 342 | 343 | ### 监视CSS 344 | 345 | 和上面用 watchify 监视 javascript 类似,我们用catw监视CSS文件的改动:` 346 | "watch-css": "catw static/pages/*.css tabs/*/*.css -o static/bundle.css -v" 347 | ` 348 | 349 | ### 序列化子任务 350 | 351 | 很简单,npm run每个子任务,然后用&&连接起来就成。` 352 | "build": "npm run build-js && npm run build-css" 353 | ` 354 | 355 | ### 并行子任务 356 | 357 | 类似地,我们用&并行子任务:` 358 | "watch": "npm run watch-js & npm run watch-css" 359 | ` 360 | 361 | ### 完整的package.json例子 362 | 363 | 将上面提到的内容组合起来,package.json大致就是这个样子:`js 364 | { 365 | "name": "my-silly-app", 366 | "version": "1.2.3", 367 | "private": true, 368 | "dependencies": { 369 | "browserify": "~2.35.2", 370 | "uglifyjs": "~2.3.6" 371 | }, 372 | "devDependencies": { 373 | "watchify": "~0.1.0", 374 | "catw": "~0.0.1", 375 | "tap": "~0.4.4" 376 | }, 377 | "scripts": { 378 | "build-js": "browserify browser/main.js | uglifyjs -mc > static/bundle.js", 379 | "build-css": "cat static/pages/*.css tabs/*/*.css", 380 | "build": "npm run build-js && npm run build-css", 381 | "watch-js": "watchify browser/main.js -o static/bundle.js -dv", 382 | "watch-css": "catw static/pages/*.css tabs/*/*.css -o static/bundle.css -v", 383 | "watch": "npm run watch-js & npm run watch-css", 384 | "start": "node server.js", 385 | "test": "tap test/*.js" 386 | } 387 | } 388 | ` 生产环境下,只需运行`npm run build`。如果是本地开发,就用`npm run watch`。 389 | 390 | 你也可以坐下扩展。比方说,如果你希望在运行start前先运行build,那么你只需写上这么一行:` 391 | "start": "npm run build && node server.js" 392 | ` 也许你想同时启动watcher?` 393 | "start-dev": "npm run watch & npm start" 394 | ` 395 | 396 | ### 当事情变得非常复杂的时候 397 | 398 | 如果你发现在单个scripts条目中塞了一大堆命令,那你可以考虑重构一下,把一些命令放到别的地方,比如/bin。 399 | 400 | 你可以用任何语言编写这个脚本,比如bash、node或perl。只需要在脚本上加上合适的#!行。还有,别忘了chmod +x。` 401 | #!/bin/bash 402 | (cd site/main; browserify browser/main.js | uglifyjs -mc > static/bundle.js) 403 | (cd site/xyz; browserify browser.js > static/bundle.js) 404 | `` 405 | "build-js": "bin/build.sh" 406 | ` 407 | 408 | ### Windows 409 | 410 | 你可能会吃惊的是,相当多的类bash语法可以在Windows上工作。不过我们至少还需要让;和&可以正常工作。 411 | 412 | James Halliday分享过一些在Windows兼容的经验,这些经验也适用于本文的主题,可以参考。此外要推荐下win-bash,这是一个很方便的Windows平台上的bash实现。 413 | 414 | ### 总结 415 | 416 | James Halliday希望这个使用npm run的方式能吸引一部人对现有的前端自动化任务工具不满意的人。James Halliday比较偏好unix体系下的那些学习曲线陡峭的工具,比如git,或者类似 npm 这种在 bash 的基础上提供极简界面的工具。也就是说,不需要很多仪式化操作和配合的工具。非常简单的工具,已经足够胜任通常的任务。 417 | 418 | 如果你对npm run风格不感冒。你也许可以考虑下Makefiles,一个稳定而简单,不过多少有点怪异的替代品。 419 | -------------------------------------------------------------------------------- /WebStorm.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | WebStorm 12 | ======== 13 | 14 | node.js 开发最好的IDE系统! 15 | 16 | 网址:http://www.jetbrains.com/webstorm/ 17 | 插件:http://plugins.jetbrains.com/webStorm 18 | 19 | WebStorm是作为JS开发IDE存在的,并且支持流行的Node.js以及JQuery等js框架。 毫无疑问非他莫属,跨平台,强大的代码提示,支持Nodejs调试,此外还支持vi编辑模式,这点我很喜欢。 而Node.js简单说就是一个JS类库并且配备有Google的V8 js引擎来解析和执行js脚本。 那WebStorm+Node.js这样一个组合,用来开发基于Node.js平台的应用是最方便不过的了,并且可以知道WebStorm这个IDE环境对js的支持是灰常强大的,有智能提示、断点调试、查看源码等等功能。 20 | 21 | 安装node 22 | -------- 23 | 24 | - iojs网址(node分离的版本): https://iojs.org/en/index.html 25 | - 最新版本相关文件:https://iojs.org/dist/v2.0.1/ 26 | - 相关中间件:https://github.com/koajs 27 | - 例子: 28 | - https://github.com/koajs/examples 29 | - https://github.com/koajs/workshop 30 | - https://github.com/koajs/kick-off-koa 31 | - windows版本:iojs-v1.7.1-x64.msi 32 | - 苹果版本:iojs-v1.7.1-darwin-x64.tar.gz 33 | - 源代码:iojs-v1.7.1.tar.gz,源代码webstorm需要,用于开发时提示 34 | - 直接运行,按缺省方式安装! 35 | - 如果以前安装有node.js 请卸载,如果安装有旧版本iojs,无需卸载,直接安装即可覆盖。 36 | - 安装完毕,会自动将 node、iojs、npm加入路径! 37 | - 在命令行执行 iojs -v 可看到 安装的版本号。 38 | 39 | 安装webstorm 40 | ------------ 41 | 42 | 1. 下载最新版本,webstorm版本更新非常快! 43 | 2. 运行安装,如以前安装过旧版本,安装新版本会自动卸载旧版本 44 | 3. 安装时,提示是否删除项目加载历史 45 | 4. 提示是否删除设置和插件,一般更新安装选择保留原设置及插件,避免重新配置 46 | 5. 安装路径,如:C:\Program Files (x86)\JetBrains\WebStorm 47 | 6. 创建桌面快捷,作为 js、html、css的缺省编辑器 48 | 7. 提示修改缺省浏览器设置,选择允许修改 49 | 8. 第一次运行,提示是否导入旧版本的设置,如:C:\Users\Walter.WebStorm9 50 | 9. 注册,WebStorm 11 注册码 51 | 52 | 由于最新jetbrains发布了IntelliJ IDEA 15. PyCharm 5.PhpStorm10.WebStorm 11等各个版本,但是改变了注册方法。原先的注册码包括注册机都已经不能使用了。 53 | 54 | 现在有个比较简单的注册方法.注册时选择“License server”输入“http://15.idea.lanyus.com/”点击“OK”即可快速激活JetBrains系列产品 55 | 56 | 设置 57 | ---- 58 | 59 | 1. 在使用 webstorm 的时候,推荐使用黑色的主题,看起来更加的纯净,也会让使用者更加的专注书写代码。 第一次启动,IDE Settings 选择 Darcula主题即可。 也可以在菜单配置选项中设置:在 Appearance 的右边菜单里,选择 Theme > Darcula主题即可。 IDE Settings 指的是 webstorm 的全局配置。 60 | 2. Editor 颜色字体中,配色选择 monokia, Sublime text 3 里面带的配色。 61 | 3. 白色太晃眼,将白色调暗 62 | Default Text: F8F8F2 -》 A7A7A7 63 | Line Number:F8F8F2 -》 A7A7A7 64 | Console Standard output:FFFFFF-》 A7A7A7 65 | Console system output:E4E4FF -》 A7A7A7 66 | 4. 键盘选择缺省键盘 67 | 5. 字体选择 Courier New 或 Consolas,Size:16 68 | 6. 代码风格 69 | - 通用tab size:2, Indent:2, Continuation:2 70 | - js/TypeScript/CoffeeScript tab size:2, Indent:2, Continuation:2 71 | - Comment at first column 不选,注释不置顶 72 | - Blank Lins Keep 中 Maximum Blank Lines InCode:1,最大空行为1行 73 | 7. File Encoding文件编码全部设置为 UTF-8,如果现有项目不是该编码,请先转换为该编码! 74 | File Encodings IDE Encoding: UTF-8 75 | Project Encoding: UTF-8 76 | Default encoding for properties files:UTF-8 77 | 8. Packages 第三方包 一般安装在 C:\Users\Xxx\AppData\Roaming\npm\node_modules 全局路径! 一些包文件安装在 C:\Users\Xxx 路径,如: C:\Users\Xxx.node-gyp 78 | 9. 安装插件 如:markdown 等 79 | 10. js 语言版本,缺省一般为 ECMAScript 5.1,后面支持该js版本的浏览器版本。 纯后台程序可选择 ECMAScript 6,选择6时会提示需要转换,如果后台运行,无需转换,如果前端运行,由于绝大多数浏览器不支持 6版本,因此需要转换。 80 | 11. js后台代码为减少差错,一般需勾选 Strict 严格模式,避免常犯的错误。 81 | 12. Libraries,请勾选 ECMAScript 6,Node.js v1.7.1 Core Modules(不同安装版本不同) 82 | 13. Node.js and NPM中,框架源代码设置。 Source of Node.js Core Modules,请下载源代码,保存到项目路径,在该选项中选择该文件即可! 83 | 14. 项目安装包列表。 Node.js and NPM中全局包及的确项目包的版本及最新版本列表,点击更新可更新。 在该页面也可安装、协助包,一般还是通过 npm install、npm uninstall 来安装、卸载更方便。 84 | 85 | 创建项目 86 | -------- 87 | 88 | 1. 创建项目会自动创建 .idea 目录,保存项目信息。 89 | 2. 创建项目向导提供四种选项: 90 | 1. Web server is installed locally, source files are located under its document root. 91 | 2. Web server is installed locally, source files are located elsewhere locally. 92 | 3. Web server is on a remote host, files are accessible via network share or mounted drive. 93 | 4. Web server is on a remote host, files are accessible via FTP/SFTP/FTPS. 94 | 5. Source files are in a local directory, no Web server is yet configured. 95 | 3. 一般选择5,下一步,提示选择项目路径,选择项目文件目录,点击鼠标右键,设置项目根目录即可。 96 | 97 | 项目运行与调试 98 | -------------- 99 | 100 | 1. 第一次运行项目,需点击右上角,Edit configurations, 101 | 2. 点击添加,选择 Node.js 102 | 3. 输入Name,执行程序,如:C:\Program Files\iojs\node.exe 要执行的代码文件,如:start.js 103 | 4. 可以选择该名称,随时执行或调试该文件。点击执行或调试,会在下面弹出执行或调试窗口。 104 | 5. 调试窗口有执行结果输出,运行错误等,可在该窗口单步跟踪。 105 | 6. 对于js 6,会提示 File Watcher,如Babel、Traceur compiler,自动将 js 6 转换为 js 5,对于后台代码,无需转换,选择忽略。 106 | 可在 Suppressed File Watchers中设置。 107 | 108 | 常用快捷键 109 | ---------- 110 | 111 | 1. 搜索 双击 Shift 112 | 2. 通过文件名称打开文件 ctl+shift+N 113 | 3. 打开最近的文件 ctl+E 114 | 4. 打开导航条 Alt+Home 115 | 116 | File Watcher 117 | ------------ 118 | 119 | - 自动将 CoffeeScript 等转换为 js文件,如将 jade文件转换为 html文件,可配置 File Watcher自动完成转换,避免通过命令行手动转换。 120 | - File Watcher在Settings->Tools->File Watchers 中添加、删除、修改 121 | - 在Code->Inspect Code中可对项目代码规范化进行检查 122 | - 如 jade的自动转换设置如下: 123 | - 安装jade到全局环境`npm install -g jade` 124 | - 手动转换:`jade --watch --out public jade` 125 | - Program: `c:\Users\Walter\AppData\Roaming\npm\jade.cmd` 126 | - Arguments: `$FileName$ --out $ProjectFileDir$\public\$FileDirPathFromParent(jade)$` 127 | - Working directory: `$FileDir$` 128 | 129 | WebStorm功能 130 | ------------ 131 | 132 | 请参见: https://www.jetbrains.com/webstorm/features/ 133 | 134 | ### TypeScript(微软在js之上设计的语言,与Coffee 类似). 135 | 136 | You can now enjoy TypeScript syntax highlighting, on-the-fly error detection, and code completion. WebStorm 6 provides streamlined experience for the full development cycle with new languages such as TypeScript, 137 | 138 | ### CoffeeScript and Dart. Here's what's available already: 139 | 140 | - Automatic compilation/transpilation of these higher-level languages into those recognized by the browsers on all platforms supported by the IDE. This also applies to modern CSS extensions such as LESS and Sass. 141 | - Full-featured debugging of CoffeeScript, TypeScript or Dart with the help of source maps. If you have a minified JS, you can debug it with source maps as well. 142 | 143 | ### Sass 144 | 145 | - custom function definition, completion and renaming support 146 | - highlighting for incorrect @-keyword 147 | - support of nested properties, and more LESS support now includes code insight for mixins and many other improvements. 148 | 149 | ### Google Dart 150 | 151 | The editor also supports inlining Dart script blocks into HTML files. For older versions of the IDE you can use this Dart plugin. 152 | 153 | ### LESS 154 | 155 | ``` 156 | support now includes code insight for mixins and many other improvements. 157 | ``` 158 | 159 | ### CoffeeScript 160 | 161 | now has its own code formatter options and in the editor support for deconstructed parameters and parameters with @ prefix is added. 162 | 163 | ### Core Web Development 164 | 165 | Live Edit, introduced in the previous release, is now easier to get started with and it also supports HTML5 live editing. 166 | 167 | WebStorm 6 also introduces improvements for HTML and CSS coding: a re-designed HTML structure view, with special support for HTML5, and Emmet snippets in the editor. If you're looking to level-up your HTML and CSS coding speed, WebStorm's got your back. 168 | 169 | ![](nodehtml5outline.png) 170 | 171 | ### Zen支持 172 | 173 | ![](nodeemmet.png) 174 | 175 | ### JS Lib 176 | 177 | We’ve also revised our approach to handling JavaScript libraries, allowing JS developers to work transparently with minimized and compiled files stored in the project tree. The IDE smartly uses them for code completion and navigation only when needed and ignores them the rest of the time. 178 | 179 | ![](nodejs_libraries_thumb.png) 180 | 181 | ### validation 182 | 183 | WebStorm equips you with the most powerful code validation tools. You can now validate your JS against Google Closure Linter (new to WebStorm 6), JSHint, JSLint, and our own custom inspections. WebStorm can also automatically pick up the latest version of JSHint for you and, now it understands .jshintrc files if your project has them. 184 | 185 | ### HTTP server 186 | 187 | WebStorm 6 includes a built-in HTTP server for static files. You can view your code in a browser instantly or debug it without setting up your own server. 188 | 189 | ### REST Client 190 | 191 | WebStorm now integrates REST Client to let you test RESTful web services right from the IDE. Simply invoke different requests over HTTP (e.g. GET, POST, PUT and others) to RESTful APIs with various parameters and get response and response headers. 192 | 193 | ### IDE Improvements 194 | 195 | WebStorm 6 has been re-designed with a fresh IDE look and feel. To explore the darker side of coding, turn your lights down and try out our new native dark UI theme, Darcula. 196 | 197 | Last but not least, if you're a happy owner of a new MacBook, feast your eyes on a set of new Retina-adapted icons. 198 | 199 | ![](nodewebstorm_darcula.png) 200 | 201 | Generating a Project from a Framework 202 | ------------------------------------- 203 | 204 | During project creation, WebStorm can generate a project stub for developing Web applications. The project structure is set up and some sources are generated based on external templates and frameworks downloaded upon your request. 205 | 206 | WebStorm generates project stubs based on the following templates: 207 | 208 | - HTML5 Boilerplate, Twitter Bootstrap, and Foundation for client-side application stubs. 209 | - Express and Node Boilerplate for the server-side applications using Node.js. Generating such application stubs requires that Node.js is supported in WebStorm: 210 | - The Node.js plugin is enabled. The plugin is bundled with WebStorm and activated by default. If it is not, enable the plugin in the Plugins page of the Settings dialog box (File | Settings | Plugins). The Node.js framework is downloaded and installed on your computer. 211 | - Dart applications. Generating Dart application stubs requires that Dart is supported in WebStorm: the Dart plugin is enabled. The plugin is bundled with WebStorm and activated by default. If it is not, enable the plugin. The Dart SDK is available on your computer. 212 | 213 | 2013-02-12 Node 后端开发指引 http://vistaswx.com/blog/article/nodejs-dev 214 | 215 | 常用的webstorm快捷键 216 | -------------------- 217 | 218 | ## WebStorm MAC苹果系统快捷键 219 | 220 | ```js 221 | 快捷键 作用 222 | command + / 或 + Shift + / 注释(// 或者/*…*/ ) 223 | /\*\* 回车自动添加函数注释,带函数参数 224 | command + d 副本当前行或选中的区块 225 | command + f 查找当前文档 226 | command + g 跳转到文档的某一行某一列 227 | command + p 显示参数信息 228 | command + r 替换当前文档 229 | command + w 选中当前单词、行、区块等 230 | command + y 删除整行 231 | command + mouseover 显示主要信息 232 | command + [ 移动光标到代码块前 233 | command + ] 移动光标到代码块尾 234 | command + + 折叠区块 235 | command + - 展开区块 236 | command + -> 光标移到行尾 237 | command + <- 光标移到行头 238 | 快捷键 作用 239 | command + option + t 将代码以某种格式包括起来 240 | command + option + l 将代码格式化 241 | 快捷键 作用 242 | command + shift + u 切换大小写 243 | command + shift + [ 选中到代码块前 244 | command + shift + ] 选中到代码块尾 245 | command + shift + + 折叠所有区块 246 | command + shift + - 展开所有区块 247 | 快捷键 作用 248 | shift + return 在任意位置换行 249 | shift + F6 高级修改,可快速修改光标所在的标签、变量、函数等 250 | control + shift + f find in path 251 | control + shift + j 合并行 252 | control + shift + r replace in path 253 | 快捷键 作用 254 | option + delete delete to word start 255 | option + fn + delete delete to word end 256 | option + -> 以单词为单位移动光标 257 | option + <- 以单词为单位移动光标 258 | ``` 259 | 260 | ## WebStorm Windows系统快捷键 261 | 262 | ``` 263 | Ctrl+/ 或 Ctrl+Shift+/ 注释(// 或者/*…*/ ) 264 | Shift+F6 重构-重命名 265 | Ctrl+X 删除行 266 | Ctrl+D 复制行 267 | Ctrl+G 268 | 269 | 查找行 270 | Ctrl+Shift+Up/Down 代码向上/下移动。 271 | F2 或Shift+F2 高亮错误或警告快速定位 272 | 写代码,按Tab 生成代码 273 | 选中文本,按Ctrl+Shift+F7 高亮显示所有该文本,按Esc高亮消失。 274 | Ctrl+B 快速打开光标处的类或方法 275 | Ctrl+E 最近打开的文件 276 | Alt+F1 查找代码所在位置 277 | Ctrl+Alt+L 格式化代码 278 | Ctrl+R 替换文本 279 | Ctrl+F 查找文本 280 | Ctrl+P 方法参数提示 281 | 282 | Webstorm默认配置下的常用快捷键 283 | 查找/代替 284 | 快捷键 285 | 说明 286 | ctrl+shift+N 通过文件名快速查找工程内的文件(必记) 287 | ctrl+shift+alt+N 通过一个字符快速查找位置(必记) 288 | ctrl+F 在文件内快速查找代码 289 | F3 查找下一个 290 | shift+F3 查找上一个 291 | ctrl+R 文件内代码替换 292 | ctrl+shift+R 指定目录内代码批量替换 293 | ctrl+shift+F 指定目录内代码批量查找 294 | ctrl+R 文件内代码替换 295 | 界面操作 296 | 快捷键 297 | 说明 298 | ctrl+shift+A 快速查找并使用编辑器所有功能(必记) 299 | alt+[0-9] 快速拆合功能界面模块 300 | ctrl+shift+F12 最大区域显示代码(会隐藏其他的功能界面模块) 301 | alt+shift+F 将当前文件加入收藏夹 302 | ctrl+alt+s 打开配置窗口 303 | ctrl+tab 切换代码选项卡(还要进行此选择,效率差些) 304 | alt+<-或-> 切换代码选项卡 305 | 快捷键 306 | 说明 307 | ctrl+shift+N 通过文件名快速查找工程内的文件(必记) 308 | ctrl+shift+alt+N 通过一个字符快速查找位置(必记) 309 | ctrl+F 在文件内快速查找代码 310 | F3 查找下一个 311 | shift+F3 查找上一个 312 | ctrl+R 文件内代码替换 313 | ctrl+shift+R 指定目录内代码批量替换 314 | ctrl+shift+F 指定目录内代码批量查找 315 | ctrl+R 文件内代码替换 316 | 界面操作 317 | 快捷键 318 | 说明 319 | ctrl+shift+A 快速查找并使用编辑器所有功能(必记) 320 | alt+[0-9] 快速拆合功能界面模块 321 | ctrl+shift+F12 最大区域显示代码(会隐藏其他的功能界面模块) 322 | alt+shift+F 将当前文件加入收藏夹 323 | ctrl+alt+s 打开配置窗口 324 | ctrl+tab 切换代码选项卡(还要进行此选择,效率差些) 325 | alt+<-或-> 切换代码选项卡 326 | ctrl+F4 关闭当前代码选项卡 327 | 代码编辑 328 | 快捷键 329 | 说明 330 | ctrl+D 复制当前行 331 | ctrl+W 选中单词 332 | ctrl+<-或-> 以单词作为边界跳光标位置 333 | alt+Insert 新建一个文件或其他 334 | ctrl+alt+L 格式化代码 335 | shift+tab/tab 减少/扩大缩进(可以在代码中减少行缩进) 336 | ctrl+Y 删除一行 337 | shift+enter 重新开始一行(无论光标在哪个位置) 338 | 导航 339 | 快捷键 340 | 说明 341 | esc 进入代码编辑区域 342 | alt+F1 查找代码在其他界面模块的位置,颇为有用 343 | ctrl+G 到指定行的代码 344 | ctrl+]/ 光标到代码块的前面或后面 345 | alt+up/down 上一个/下一个方法 346 | 建议配置版本控制快捷键 347 | 快捷键 348 | 说明 349 | ctrl+C 提交代码 350 | ctrl+p 向远程版本库推送更新 351 | ctrl+G 到指定行的代码 352 | ctrl+]/ 光标到代码块的前面或后面 353 | alt+up/down 上一个/下一个方法 354 | ``` 355 | 356 | -------------------------------------------------------------------------------- /html/js/prettify.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by way on 16/5/12. 3 | */ 4 | !function(){var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; 5 | (function(){function S(a){function d(e){var b=e.charCodeAt(0);if(b!==92)return b;var a=e.charAt(1);return(b=r[a])?b:"0"<=a&&a<="7"?parseInt(e.substring(1),8):a==="u"||a==="x"?parseInt(e.substring(2),16):e.charCodeAt(1)}function g(e){if(e<32)return(e<16?"\\x0":"\\x")+e.toString(16);e=String.fromCharCode(e);return e==="\\"||e==="-"||e==="]"||e==="^"?"\\"+e:e}function b(e){var b=e.substring(1,e.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),e=[],a= 6 | b[0]==="^",c=["["];a&&c.push("^");for(var a=a?1:0,f=b.length;a122||(l<65||h>90||e.push([Math.max(65,h)|32,Math.min(l,90)|32]),l<97||h>122||e.push([Math.max(97,h)&-33,Math.min(l,122)&-33]))}}e.sort(function(e,a){return e[0]-a[0]||a[1]-e[1]});b=[];f=[];for(a=0;ah[0]&&(h[1]+1>h[0]&&c.push("-"),c.push(g(h[1])));c.push("]");return c.join("")}function s(e){for(var a=e.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),c=a.length,d=[],f=0,h=0;f=2&&e==="["?a[f]=b(l):e!=="\\"&&(a[f]=l.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var x=0,m=!1,j=!1,k=0,c=a.length;k=5&&"lang-"===w.substring(0,5))&&!(t&&typeof t[1]==="string"))f=!1,w="src";f||(r[z]=w)}h=c;c+=z.length;if(f){f=t[1];var l=z.indexOf(f),B=l+f.length;t[2]&&(B=z.length-t[2].length,l=B-f.length);w=w.substring(5);H(j+h,z.substring(0,l),g,k);H(j+h+l,f,I(w,f),k);H(j+h+B,z.substring(B),g,k)}else k.push(j+h,w)}a.g=k}var b={},s;(function(){for(var g=a.concat(d),j=[],k={},c=0,i=g.length;c=0;)b[n.charAt(e)]=r;r=r[1];n=""+r;k.hasOwnProperty(n)||(j.push(r),k[n]=q)}j.push(/[\S\s]/);s=S(j)})();var x=d.length;return g}function v(a){var d=[],g=[];a.tripleQuotedStrings?d.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?d.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, 13 | q,"'\"`"]):d.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&g.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var b=a.hashComments;b&&(a.cStyleComments?(b>1?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),g.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,q])):d.push(["com", 14 | /^#[^\n\r]*/,q,"#"]));a.cStyleComments&&(g.push(["com",/^\/\/[^\n\r]*/,q]),g.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));if(b=a.regexLiterals){var s=(b=b>1?"":"\n\r")?".":"[\\S\\s]";g.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*("+("/(?=[^/*"+b+"])(?:[^/\\x5B\\x5C"+b+"]|\\x5C"+s+"|\\x5B(?:[^\\x5C\\x5D"+b+"]|\\x5C"+ 15 | s+")*(?:\\x5D|$))+/")+")")])}(b=a.types)&&g.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&g.push(["kwd",RegExp("^(?:"+b.replace(/[\s,]+/g,"|")+")\\b"),q]);d.push(["pln",/^\s+/,q," \r\n\t\u00a0"]);b="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(b+="(?!s*/)");g.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/, 16 | q],["pun",RegExp(b),q]);return C(d,g)}function J(a,d,g){function b(a){var c=a.nodeType;if(c==1&&!x.test(a.className))if("br"===a.nodeName)s(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((c==3||c==4)&&g){var d=a.nodeValue,i=d.match(m);if(i)c=d.substring(0,i.index),a.nodeValue=c,(d=d.substring(i.index+i[0].length))&&a.parentNode.insertBefore(j.createTextNode(d),a.nextSibling),s(a),c||a.parentNode.removeChild(a)}}function s(a){function b(a,c){var d= 17 | c?a.cloneNode(!1):a,e=a.parentNode;if(e){var e=b(e,1),g=a.nextSibling;e.appendChild(d);for(var i=g;i;i=g)g=i.nextSibling,e.appendChild(i)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),d;(d=a.parentNode)&&d.nodeType===1;)a=d;c.push(a)}for(var x=/(?:^|\s)nocode(?:\s|$)/,m=/\r\n?|\n/,j=a.ownerDocument,k=j.createElement("li");a.firstChild;)k.appendChild(a.firstChild);for(var c=[k],i=0;i=0;){var b=d[g];F.hasOwnProperty(b)?D.console&&console.warn("cannot override language handler %s",b):F[b]=a}}function I(a,d){if(!a||!F.hasOwnProperty(a))a=/^\s*=l&&(b+=2);g>=B&&(r+=2)}}finally{if(f)f.style.display=h}}catch(u){D.console&&console.log(u&&u.stack||u)}}var D=window,y=["break,continue,do,else,for,if,return,while"],E=[[y,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], 21 | "catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],M=[E,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],N=[E,"abstract,assert,boolean,byte,extends,final,finally,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"], 22 | O=[N,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,internal,into,is,let,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where"],E=[E,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],P=[y,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], 23 | Q=[y,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],W=[y,"as,assert,const,copy,drop,enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,pub,pure,ref,self,static,struct,true,trait,type,unsafe,use"],y=[y,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],R=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/, 24 | V=/\S/,X=v({keywords:[M,O,E,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",P,Q,y],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),F={};p(X,["default-code"]);p(C([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-", 25 | /^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);p(C([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/], 26 | ["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);p(C([],[["atv",/^[\S\s]+/]]),["uq.val"]);p(v({keywords:M,hashComments:!0,cStyleComments:!0,types:R}),["c","cc","cpp","cxx","cyc","m"]);p(v({keywords:"null,true,false"}),["json"]);p(v({keywords:O,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:R}), 27 | ["cs"]);p(v({keywords:N,cStyleComments:!0}),["java"]);p(v({keywords:y,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);p(v({keywords:P,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);p(v({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:2}),["perl","pl","pm"]);p(v({keywords:Q, 28 | hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);p(v({keywords:E,cStyleComments:!0,regexLiterals:!0}),["javascript","js"]);p(v({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);p(v({keywords:W,cStyleComments:!0,multilineStrings:!0}),["rc","rs","rust"]); 29 | p(C([],[["str",/^[\S\s]+/]]),["regex"]);var Y=D.PR={createSimpleLexer:C,registerLangHandler:p,sourceDecorator:v,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:D.prettyPrintOne=function(a,d,g){var b=document.createElement("div");b.innerHTML="
"+a+"
";b=b.firstChild;g&&J(b,g,!0);K({h:d,j:g,c:b,i:1}); 30 | return b.innerHTML},prettyPrint:D.prettyPrint=function(a,d){function g(){for(var b=D.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;i 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |

eslint

12 |

最好的js书写风格、语法、错误检查及在线提示。

13 |
14 |

ESLint 由 JavaScript 红宝书 作者 Nicholas C. Zakas 编写, 2013 年发布第一个版本。 NCZ 的初衷不是重复造一个轮子,而是在际需求得不到 JSHint 团队响应 的情况下做出的选择:以可扩展、每条规则独立、不内置编码风格为理念编写一个 lint 工具。

15 |
16 |

ESLint 主要有以下特点:

17 |
    18 |
  • 默认规则包含所有 JSLint、JSHint 中存在的规则,易迁移;
  • 19 |
  • 规则可配置性高:可设置「警告」、「错误」两个 error 等级,或者直接禁用;
  • 20 |
  • 包含代码风格检测的规则(可以丢掉 JSCS 了);
  • 21 |
  • 支持插件扩展、自定义规则。
  • 22 |
23 |

配置

24 |
    25 |
  • 可以通过以下三种方式配置 ESLint:
  • 26 |
  • 使用 .eslintrc 文件(支持 JSON 和 YAML 两种语法);
  • 27 |
  • 在 package.json 中添加 eslintConfig 配置块;
  • 28 |
  • 直接在代码文件中定义。
  • 29 |
30 |

本项目使用的 .eslintrc 文件

31 |
    32 |
  • 继承 eslint-config-airbnb/base
  • 33 |
  • 需安装以下插件

    34 |
    "eslint": "^2.9.0",
     35 | "eslint-config-airbnb": "^9.0.1",
     36 | "eslint-plugin-import": "^1.8.0",
     37 | "eslint-plugin-jsx-a11y": "^1.2.0",
     38 | "eslint-plugin-react": "^5.1.1",
     39 | 
    40 |
  • 41 |
  • 文件内容

    42 |
      {
     43 |       "extends": "eslint-config-airbnb/base",
     44 |       "parser": "babel-eslint",
     45 |       "env": {
     46 |           "browser": true,
     47 |           "node": true,
     48 |           "mocha": true
     49 |       },
     50 |       "rules": {
     51 |           // Disable for console/alert
     52 |           "no-console": 0,
     53 |           "no-alert": 0,
     54 | 
     55 |           "indent": [2, 2, {"SwitchCase": 1}],
     56 |           "object-curly-spacing": 0
     57 |       },
     58 |       "plugins": [
     59 |           "import"
     60 |       ],
     61 |       "settings": {
     62 |           "import/parser": "babel-eslint",
     63 |           "import/resolve": {
     64 |               "moduleDirectory": ["node_modules", "src"]
     65 |           }
     66 |       },
     67 |       "globals": {
     68 |           "__DEV__": true,
     69 |           "__OPTION__": true
     70 |       }
     71 |   }
     72 | 
  • 73 |
74 |

以下是详细 .eslintrc 文件示例和解释:

75 |
{  
 76 |   "env": {  
 77 |     "browser": true,  
 78 |     "node": true,  
 79 |     "commonjs": true  
 80 |   },  
 81 |   "ecmaFeatures": {  
 82 |     // lambda表达式  
 83 |     "arrowFunctions": true,  
 84 |     // 解构赋值  
 85 |     "destructuring": true,  
 86 |     // class  
 87 |     "classes": true,  
 88 |     // http://es6.ruanyifeng.com/#docs/function#函数参数的默认值  
 89 |     "defaultParams": true,  
 90 |     // 块级作用域,允许使用let const  
 91 |     "blockBindings": true,  
 92 |     // 允许使用模块,模块内默认严格模式  
 93 |     "modules": true,  
 94 |     // 允许字面量定义对象时,用表达式做属性名  
 95 |     // http://es6.ruanyifeng.com/#docs/object#属性名表达式  
 96 |     "objectLiteralComputedProperties": true,  
 97 |     // 允许对象字面量方法名简写  
 98 |     /*var o = { 
 99 |         method() { 
100 |           return "Hello!"; 
101 |         } 
102 |      }; 
103 | 
104 |      等同于 
105 | 
106 |      var o = { 
107 |        method: function() { 
108 |          return "Hello!"; 
109 |        } 
110 |      }; 
111 |     */  
112 |     "objectLiteralShorthandMethods": true,  
113 |     /* 
114 |       对象字面量属性名简写 
115 |       var foo = 'bar'; 
116 |       var baz = {foo}; 
117 |       baz // {foo: "bar"} 
118 | 
119 |       // 等同于 
120 |       var baz = {foo: foo}; 
121 |     */  
122 |     "objectLiteralShorthandProperties": true,  
123 |     // http://es6.ruanyifeng.com/#docs/function#rest参数  
124 |     "restParams": true,  
125 |     // http://es6.ruanyifeng.com/#docs/function#扩展运算符  
126 |     "spread": true,  
127 |     // http://es6.ruanyifeng.com/#docs/iterator#for---of循环  
128 |     "forOf": true,  
129 |     // http://es6.ruanyifeng.com/#docs/generator  
130 |     "generators": true,  
131 |     // http://es6.ruanyifeng.com/#docs/string#模板字符串  
132 |     "templateStrings": true,  
133 |     "superInFunctions": true,  
134 |     // http://es6.ruanyifeng.com/#docs/object#对象的扩展运算符  
135 |     "experimentalObjectRestSpread": true  
136 |   },  
137 | 
138 |   "rules": {  
139 |     // 定义对象的set存取器属性时,强制定义get  
140 |     "accessor-pairs": 2,  
141 |     // 指定数组的元素之间要以空格隔开(,后面), never参数:[ 之前和 ] 之后不能带空格,always参数:[ 之前和 ] 之后必须带空格  
142 |     "array-bracket-spacing": [2, "never"],  
143 |     // 在块级作用域外访问块内定义的变量是否报错提示  
144 |     "block-scoped-var": 0,  
145 |     // if while function 后面的{必须与if在同一行,java风格。  
146 |     "brace-style": [2, "1tbs", { "allowSingleLine": true }],  
147 |     // 双峰驼命名格式  
148 |     "camelcase": 2,  
149 |     // 数组和对象键值对最后一个逗号, never参数:不能带末尾的逗号, always参数:必须带末尾的逗号,  
150 |     // always-multiline:多行模式必须带逗号,单行模式不能带逗号  
151 |     "comma-dangle": [2, "never"],  
152 |     // 控制逗号前后的空格  
153 |     "comma-spacing": [2, { "before": false, "after": true }],  
154 |     // 控制逗号在行尾出现还是在行首出现  
155 |     // http://eslint.org/docs/rules/comma-style  
156 |     "comma-style": [2, "last"],  
157 |     // 圈复杂度  
158 |     "complexity": [2,9],  
159 |     // 以方括号取对象属性时,[ 后面和 ] 前面是否需要空格, 可选参数 never, always  
160 |     "computed-property-spacing": [2,"never"],  
161 |     // 强制方法必须返回值,TypeScript强类型,不配置  
162 |     "consistent-return": 0,  
163 |     // 用于指统一在回调函数中指向this的变量名,箭头函数中的this已经可以指向外层调用者,应该没卵用了  
164 |     // e.g [0,"that"] 指定只能 var that = this. that不能指向其他任何值,this也不能赋值给that以外的其他值  
165 |     "consistent-this": 0,  
166 |     // 强制在子类构造函数中用super()调用父类构造函数,TypeScrip的编译器也会提示  
167 |     "constructor-super": 0,  
168 |     // if else while for do后面的代码块是否需要{ }包围,参数:  
169 |     //    multi  只有块中有多行语句时才需要{ }包围  
170 |     //    multi-line  只有块中有多行语句时才需要{ }包围, 但是块中的执行语句只有一行时,  
171 |     //                   块中的语句只能跟和if语句在同一行。if (foo) foo++; else doSomething();  
172 |     //    multi-or-nest 只有块中有多行语句时才需要{ }包围, 如果块中的执行语句只有一行,执行语句可以零另起一行也可以跟在if语句后面  
173 |     //    [2, "multi", "consistent"] 保持前后语句的{ }一致  
174 |     //    default: [2, "all"] 全都需要{ }包围  
175 |     "curly": [2, "all"],  
176 |     // switch语句强制default分支,也可添加 // no default 注释取消此次警告  
177 |     "default-case": 2,  
178 |     // 强制object.key 中 . 的位置,参数:  
179 |     //      property,'.'号应与属性在同一行  
180 |     //      object, '.' 号应与对象名在同一行  
181 |     "dot-location": [2, "property"],  
182 |     // 强制使用.号取属性  
183 |     //    参数: allowKeywords:true 使用保留字做属性名时,只能使用.方式取属性  
184 |     //                          false 使用保留字做属性名时, 只能使用[]方式取属性 e.g [2, {"allowKeywords": false}]  
185 |     //           allowPattern:  当属性名匹配提供的正则表达式时,允许使用[]方式取值,否则只能用.号取值 e.g [2, {"allowPattern": "^[a-z]+(_[a-z]+)+$"}]  
186 |     "dot-notation": [2, {"allowKeywords": true}],  
187 |     // 文件末尾强制换行  
188 |     "eol-last": 2,  
189 |     // 使用 === 替代 ==  
190 |     "eqeqeq": [2, "allow-null"],  
191 |     // 方法表达式是否需要命名  
192 |     "func-names": 0,  
193 |     // 方法定义风格,参数:  
194 |     //    declaration: 强制使用方法声明的方式,function f(){} e.g [2, "declaration"]  
195 |     //    expression:强制使用方法表达式的方式,var f = function() {}  e.g [2, "expression"]  
196 |     //    allowArrowFunctions: declaration风格中允许箭头函数。 e.g [2, "declaration", { "allowArrowFunctions": true }]  
197 |     "func-style": 0,  
198 |     "generator-star-spacing": [2, { "before": true, "after": true }],  
199 |     "guard-for-in": 0,  
200 |     "handle-callback-err": [2, "^(err|error)$" ],  
201 |     "indent": [2, 2, { "SwitchCase": 1 }],  
202 |     "key-spacing": [2, { "beforeColon": false, "afterColon": true }],  
203 |     "linebreak-style": 0,  
204 |     "lines-around-comment": 0,  
205 |     "max-nested-callbacks": 0,  
206 |     "new-cap": [2, { "newIsCap": true, "capIsNew": false }],  
207 |     "new-parens": 2,  
208 |     "newline-after-var": 0,  
209 |     "no-alert": 0,  
210 |     "no-array-constructor": 2,  
211 |     "no-caller": 2,  
212 |     "no-catch-shadow": 0,  
213 |     "no-cond-assign": 2,  
214 |     "no-console": 0,  
215 |     "no-constant-condition": 0,  
216 |     "no-continue": 0,  
217 |     "no-control-regex": 2,  
218 |     "no-debugger": 2,  
219 |     "no-delete-var": 2,  
220 |     "no-div-regex": 0,  
221 |     "no-dupe-args": 2,  
222 |     "no-dupe-keys": 2,  
223 |     "no-duplicate-case": 2,  
224 |     "no-else-return": 0,  
225 |     "no-empty": 0,  
226 |     "no-empty-character-class": 2,  
227 |     "no-empty-label": 2,  
228 |     "no-eq-null": 0,  
229 |     "no-eval": 2,  
230 |     "no-ex-assign": 2,  
231 |     "no-extend-native": 2,  
232 |     "no-extra-bind": 2,  
233 |     "no-extra-boolean-cast": 2,  
234 |     "no-extra-parens": 0,  
235 |     "no-extra-semi": 0,  
236 |     "no-fallthrough": 2,  
237 |     "no-floating-decimal": 2,  
238 |     "no-func-assign": 2,  
239 |     "no-implied-eval": 2,  
240 |     "no-inline-comments": 0,  
241 |     "no-inner-declarations": [2, "functions"],  
242 |     "no-invalid-regexp": 2,  
243 |     "no-irregular-whitespace": 2,  
244 |     "no-iterator": 2,  
245 |     "no-label-var": 2,  
246 |     "no-labels": 2,  
247 |     "no-lone-blocks": 2,  
248 |     "no-lonely-if": 0,  
249 |     "no-loop-func": 0,  
250 |     "no-mixed-requires": 0,  
251 |     "no-mixed-spaces-and-tabs": 2,  
252 |     "no-multi-spaces": 2,  
253 |     "no-multi-str": 2,  
254 |     "no-multiple-empty-lines": [2, { "max": 1 }],  
255 |     "no-native-reassign": 2,  
256 |     "no-negated-in-lhs": 2,  
257 |     "no-nested-ternary": 0,  
258 |     "no-new": 2,  
259 |     "no-new-func": 0,  
260 |     "no-new-object": 2,  
261 |     "no-new-require": 2,  
262 |     "no-new-wrappers": 2,  
263 |     "no-obj-calls": 2,  
264 |     "no-octal": 2,  
265 |     "no-octal-escape": 2,  
266 |     "no-param-reassign": 0,  
267 |     "no-path-concat": 0,  
268 |     "no-process-env": 0,  
269 |     "no-process-exit": 0,  
270 |     "no-proto": 0,  
271 |     "no-redeclare": 2,  
272 |     "no-regex-spaces": 2,  
273 |     "no-restricted-modules": 0,  
274 |     "no-return-assign": 2,  
275 |     "no-script-url": 0,  
276 |     "no-self-compare": 2,  
277 |     "no-sequences": 2,  
278 |     "no-shadow": 0,  
279 |     "no-shadow-restricted-names": 2,  
280 |     "no-spaced-func": 2,  
281 |     "no-sparse-arrays": 2,  
282 |     "no-sync": 0,  
283 |     "no-ternary": 0,  
284 |     "no-this-before-super": 2,  
285 |     "no-throw-literal": 2,  
286 |     "no-trailing-spaces": 2,  
287 |     "no-undef": 2,  
288 |     "no-undef-init": 2,  
289 |     "no-undefined": 0,  
290 |     "no-underscore-dangle": 0,  
291 |     "no-unexpected-multiline": 2,  
292 |     "no-unneeded-ternary": 2,  
293 |     "no-unreachable": 2,  
294 |     "no-unused-expressions": 0,  
295 |     "no-unused-vars": [2, { "vars": "all", "args": "none" }],  
296 |     "no-use-before-define": 0,  
297 |     "no-var": 0,  
298 |     "no-void": 0,  
299 |     "no-warning-comments": 0,  
300 |     "no-with": 2,  
301 |     "object-curly-spacing": 0,  
302 |     "object-shorthand": 0,  
303 |     "one-var": [2, { "initialized": "never" }],  
304 |     "operator-assignment": 0,  
305 |     "operator-linebreak": [2, "after", { "overrides": { "?": "before", ":": "before" } }],  
306 |     "padded-blocks": 0,  
307 |     "prefer-const": 0,  
308 |     "quote-props": 0,  
309 |     "quotes": [2, "single", "avoid-escape"],  
310 |     "radix": 2,  
311 |     "semi": [2, "never"],  
312 |     "semi-spacing": 0,  
313 |     "sort-vars": 0,  
314 |     "space-after-keywords": [2, "always"],  
315 |     "space-before-blocks": [2, "always"],  
316 |     "space-before-function-paren": [2, "always"],  
317 |     "space-in-parens": [2, "never"],  
318 |     "space-infix-ops": 2,  
319 |     "space-return-throw-case": 2,  
320 |     "space-unary-ops": [2, { "words": true, "nonwords": false }],  
321 |     "spaced-comment": [2, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!"] }],  
322 |     "strict": 0,  
323 |     "use-isnan": 2,  
324 |     "valid-jsdoc": 0,  
325 |     "valid-typeof": 2,  
326 |     "vars-on-top": 0,  
327 |     "wrap-iife": [2, "any"],  
328 |     "wrap-regex": 0,  
329 |     "yoda": [2, "never"]  
330 |   }  
331 | }
332 | 
333 | -------------------------------------------------------------------------------- /html/WebStorm.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |

WebStorm

12 |

node.js 开发最好的IDE系统!

13 |

网址:http://www.jetbrains.com/webstorm/
插件:http://plugins.jetbrains.com/webStorm

14 |

WebStorm是作为JS开发IDE存在的,并且支持流行的Node.js以及JQuery等js框架。 毫无疑问非他莫属,跨平台,强大的代码提示,支持Nodejs调试,此外还支持vi编辑模式,这点我很喜欢。 而Node.js简单说就是一个JS类库并且配备有Google的V8 js引擎来解析和执行js脚本。 那WebStorm+Node.js这样一个组合,用来开发基于Node.js平台的应用是最方便不过的了,并且可以知道WebStorm这个IDE环境对js的支持是灰常强大的,有智能提示、断点调试、查看源码等等功能。

15 |

安装node

16 | 34 |

安装webstorm

35 |
    36 |
  1. 下载最新版本,webstorm版本更新非常快!
  2. 37 |
  3. 运行安装,如以前安装过旧版本,安装新版本会自动卸载旧版本
  4. 38 |
  5. 安装时,提示是否删除项目加载历史
  6. 39 |
  7. 提示是否删除设置和插件,一般更新安装选择保留原设置及插件,避免重新配置
  8. 40 |
  9. 安装路径,如:C:\Program Files (x86)\JetBrains\WebStorm
  10. 41 |
  11. 创建桌面快捷,作为 js、html、css的缺省编辑器
  12. 42 |
  13. 提示修改缺省浏览器设置,选择允许修改
  14. 43 |
  15. 第一次运行,提示是否导入旧版本的设置,如:C:\Users\Walter.WebStorm9
  16. 44 |
  17. 注册,WebStorm 11 注册码
  18. 45 |
46 |

由于最新jetbrains发布了IntelliJ IDEA 15. PyCharm 5.PhpStorm10.WebStorm 11等各个版本,但是改变了注册方法。原先的注册码包括注册机都已经不能使用了。

47 |

现在有个比较简单的注册方法.注册时选择“License server”输入“http://15.idea.lanyus.com/”点击“OK”即可快速激活JetBrains系列产品

48 |

设置

49 |
    50 |
  1. 在使用 webstorm 的时候,推荐使用黑色的主题,看起来更加的纯净,也会让使用者更加的专注书写代码。 第一次启动,IDE Settings 选择 Darcula主题即可。 也可以在菜单配置选项中设置:在 Appearance 的右边菜单里,选择 Theme > Darcula主题即可。 IDE Settings 指的是 webstorm 的全局配置。
  2. 51 |
  3. Editor 颜色字体中,配色选择 monokia, Sublime text 3 里面带的配色。
  4. 52 |
  5. 白色太晃眼,将白色调暗
    Default Text: F8F8F2 -》 A7A7A7
    Line Number:F8F8F2 -》 A7A7A7
    Console Standard output:FFFFFF-》 A7A7A7
    Console system output:E4E4FF -》 A7A7A7
  6. 53 |
  7. 键盘选择缺省键盘
  8. 54 |
  9. 字体选择 Courier New 或 Consolas,Size:16
  10. 55 |
  11. 代码风格
      56 |
    • 通用tab size:2, Indent:2, Continuation:2
    • 57 |
    • js/TypeScript/CoffeeScript tab size:2, Indent:2, Continuation:2
    • 58 |
    • Comment at first column 不选,注释不置顶
    • 59 |
    • Blank Lins Keep 中 Maximum Blank Lines InCode:1,最大空行为1行
    • 60 |
    61 |
  12. 62 |
  13. File Encoding文件编码全部设置为 UTF-8,如果现有项目不是该编码,请先转换为该编码!
    File Encodings IDE Encoding: UTF-8
    Project Encoding: UTF-8
    Default encoding for properties files:UTF-8
  14. 63 |
  15. Packages 第三方包 一般安装在 C:\Users\Xxx\AppData\Roaming\npm\node_modules 全局路径! 一些包文件安装在 C:\Users\Xxx 路径,如: C:\Users\Xxx.node-gyp
  16. 64 |
  17. 安装插件 如:markdown 等
  18. 65 |
  19. js 语言版本,缺省一般为 ECMAScript 5.1,后面支持该js版本的浏览器版本。 纯后台程序可选择 ECMAScript 6,选择6时会提示需要转换,如果后台运行,无需转换,如果前端运行,由于绝大多数浏览器不支持 6版本,因此需要转换。
  20. 66 |
  21. js后台代码为减少差错,一般需勾选 Strict 严格模式,避免常犯的错误。
  22. 67 |
  23. Libraries,请勾选 ECMAScript 6,Node.js v1.7.1 Core Modules(不同安装版本不同)
  24. 68 |
  25. Node.js and NPM中,框架源代码设置。 Source of Node.js Core Modules,请下载源代码,保存到项目路径,在该选项中选择该文件即可!
  26. 69 |
  27. 项目安装包列表。 Node.js and NPM中全局包及的确项目包的版本及最新版本列表,点击更新可更新。 在该页面也可安装、协助包,一般还是通过 npm install、npm uninstall 来安装、卸载更方便。
  28. 70 |
71 |

创建项目

72 |
    73 |
  1. 创建项目会自动创建 .idea 目录,保存项目信息。
  2. 74 |
  3. 创建项目向导提供四种选项:
      75 |
    1. Web server is installed locally, source files are located under its document root.
    2. 76 |
    3. Web server is installed locally, source files are located elsewhere locally.
    4. 77 |
    5. Web server is on a remote host, files are accessible via network share or mounted drive.
    6. 78 |
    7. Web server is on a remote host, files are accessible via FTP/SFTP/FTPS.
    8. 79 |
    9. Source files are in a local directory, no Web server is yet configured.
    10. 80 |
    81 |
  4. 82 |
  5. 一般选择5,下一步,提示选择项目路径,选择项目文件目录,点击鼠标右键,设置项目根目录即可。
  6. 83 |
84 |

项目运行与调试

85 |
    86 |
  1. 第一次运行项目,需点击右上角,Edit configurations,
  2. 87 |
  3. 点击添加,选择 Node.js
  4. 88 |
  5. 输入Name,执行程序,如:C:\Program Files\iojs\node.exe 要执行的代码文件,如:start.js
  6. 89 |
  7. 可以选择该名称,随时执行或调试该文件。点击执行或调试,会在下面弹出执行或调试窗口。
  8. 90 |
  9. 调试窗口有执行结果输出,运行错误等,可在该窗口单步跟踪。
  10. 91 |
  11. 对于js 6,会提示 File Watcher,如Babel、Traceur compiler,自动将 js 6 转换为 js 5,对于后台代码,无需转换,选择忽略。
    可在 Suppressed File Watchers中设置。
  12. 92 |
93 |

常用快捷键

94 |
    95 |
  1. 搜索 双击 Shift
  2. 96 |
  3. 通过文件名称打开文件 ctl+shift+N
  4. 97 |
  5. 打开最近的文件 ctl+E
  6. 98 |
  7. 打开导航条 Alt+Home
  8. 99 |
100 |

File Watcher

101 |
    102 |
  • 自动将 CoffeeScript 等转换为 js文件,如将 jade文件转换为 html文件,可配置 File Watcher自动完成转换,避免通过命令行手动转换。
  • 103 |
  • File Watcher在Settings->Tools->File Watchers 中添加、删除、修改
  • 104 |
  • 在Code->Inspect Code中可对项目代码规范化进行检查
  • 105 |
  • 如 jade的自动转换设置如下:
  • 106 |
  • 安装jade到全局环境npm install -g jade
      107 |
    • 手动转换:jade --watch --out public jade
    • 108 |
    • Program: c:\Users\Walter\AppData\Roaming\npm\jade.cmd
    • 109 |
    • Arguments: $FileName$ --out $ProjectFileDir$\public\$FileDirPathFromParent(jade)$
    • 110 |
    • Working directory: $FileDir$
    • 111 |
    112 |
  • 113 |
114 |

WebStorm功能

115 |

请参见: https://www.jetbrains.com/webstorm/features/

116 |

TypeScript(微软在js之上设计的语言,与Coffee 类似).

117 |

You can now enjoy TypeScript syntax highlighting, on-the-fly error detection, and code completion. WebStorm 6 provides streamlined experience for the full development cycle with new languages such as TypeScript,

118 |

CoffeeScript and Dart. Here's what's available already:

119 |
    120 |
  • Automatic compilation/transpilation of these higher-level languages into those recognized by the browsers on all platforms supported by the IDE. This also applies to modern CSS extensions such as LESS and Sass.
  • 121 |
  • Full-featured debugging of CoffeeScript, TypeScript or Dart with the help of source maps. If you have a minified JS, you can debug it with source maps as well.
  • 122 |
123 |

Sass

124 |
    125 |
  • custom function definition, completion and renaming support
  • 126 |
  • highlighting for incorrect @-keyword
  • 127 |
  • support of nested properties, and more LESS support now includes code insight for mixins and many other improvements.
  • 128 |
129 |

Google Dart

130 |

The editor also supports inlining Dart script blocks into HTML files. For older versions of the IDE you can use this Dart plugin.

131 |

LESS

132 |
support now includes code insight for mixins and many other improvements.
133 | 

CoffeeScript

134 |

now has its own code formatter options and in the editor support for deconstructed parameters and parameters with @ prefix is added.

135 |

Core Web Development

136 |

Live Edit, introduced in the previous release, is now easier to get started with and it also supports HTML5 live editing.

137 |

WebStorm 6 also introduces improvements for HTML and CSS coding: a re-designed HTML structure view, with special support for HTML5, and Emmet snippets in the editor. If you're looking to level-up your HTML and CSS coding speed, WebStorm's got your back.

138 |

139 |

Zen支持

140 |

141 |

JS Lib

142 |

We’ve also revised our approach to handling JavaScript libraries, allowing JS developers to work transparently with minimized and compiled files stored in the project tree. The IDE smartly uses them for code completion and navigation only when needed and ignores them the rest of the time.

143 |

144 |

validation

145 |

WebStorm equips you with the most powerful code validation tools. You can now validate your JS against Google Closure Linter (new to WebStorm 6), JSHint, JSLint, and our own custom inspections. WebStorm can also automatically pick up the latest version of JSHint for you and, now it understands .jshintrc files if your project has them.

146 |

HTTP server

147 |

WebStorm 6 includes a built-in HTTP server for static files. You can view your code in a browser instantly or debug it without setting up your own server.

148 |

REST Client

149 |

WebStorm now integrates REST Client to let you test RESTful web services right from the IDE. Simply invoke different requests over HTTP (e.g. GET, POST, PUT and others) to RESTful APIs with various parameters and get response and response headers.

150 |

IDE Improvements

151 |

WebStorm 6 has been re-designed with a fresh IDE look and feel. To explore the darker side of coding, turn your lights down and try out our new native dark UI theme, Darcula.

152 |

Last but not least, if you're a happy owner of a new MacBook, feast your eyes on a set of new Retina-adapted icons.

153 |

154 |

Generating a Project from a Framework

155 |

During project creation, WebStorm can generate a project stub for developing Web applications. The project structure is set up and some sources are generated based on external templates and frameworks downloaded upon your request.

156 |

WebStorm generates project stubs based on the following templates:

157 |
    158 |
  • HTML5 Boilerplate, Twitter Bootstrap, and Foundation for client-side application stubs.
  • 159 |
  • Express and Node Boilerplate for the server-side applications using Node.js. Generating such application stubs requires that Node.js is supported in WebStorm:
      160 |
    • The Node.js plugin is enabled. The plugin is bundled with WebStorm and activated by default. If it is not, enable the plugin in the Plugins page of the Settings dialog box (File | Settings | Plugins). The Node.js framework is downloaded and installed on your computer.
    • 161 |
    162 |
  • 163 |
  • Dart applications. Generating Dart application stubs requires that Dart is supported in WebStorm: the Dart plugin is enabled. The plugin is bundled with WebStorm and activated by default. If it is not, enable the plugin. The Dart SDK is available on your computer.
  • 164 |
165 |

2013-02-12 Node 后端开发指引 http://vistaswx.com/blog/article/nodejs-dev

166 |

常用的webstorm快捷键

167 |

WebStorm MAC苹果系统快捷键

168 |
快捷键    作用
169 | command + / 或 + Shift + /    注释(// 或者/*…*/ )
170 | /\*\* 回车自动添加函数注释,带函数参数 
171 | command + d    副本当前行或选中的区块
172 | command + f    查找当前文档
173 | command + g    跳转到文档的某一行某一列
174 | command + p    显示参数信息
175 | command + r    替换当前文档
176 | command + w    选中当前单词、行、区块等
177 | command + y    删除整行
178 | command + mouseover    显示主要信息
179 | command + [    移动光标到代码块前
180 | command + ]    移动光标到代码块尾
181 | command + +    折叠区块
182 | command + -    展开区块
183 | command + ->    光标移到行尾
184 | command + <-    光标移到行头
185 | 快捷键    作用
186 | command + option + t    将代码以某种格式包括起来
187 | command + option + l    将代码格式化
188 | 快捷键    作用
189 | command + shift + u    切换大小写
190 | command + shift + [    选中到代码块前
191 | command + shift + ]    选中到代码块尾
192 | command + shift + +    折叠所有区块
193 | command + shift + -    展开所有区块
194 | 快捷键    作用
195 | shift + return    在任意位置换行
196 | shift + F6    高级修改,可快速修改光标所在的标签、变量、函数等
197 | control + shift + f    find in path
198 | control + shift + j    合并行
199 | control + shift + r    replace in path
200 | 快捷键    作用
201 | option + delete    delete to word start
202 | option + fn + delete    delete to word end
203 | option + ->    以单词为单位移动光标
204 | option + <-    以单词为单位移动光标
205 | 
206 |

WebStorm Windows系统快捷键

207 |
Ctrl+/ 或 Ctrl+Shift+/    注释(// 或者/*…*/ )
208 | Shift+F6    重构-重命名
209 | Ctrl+X    删除行
210 | Ctrl+D    复制行
211 | Ctrl+G
212 | 
213 | 查找行
214 | Ctrl+Shift+Up/Down    代码向上/下移动。
215 | F2 或Shift+F2    高亮错误或警告快速定位
216 | 写代码,按Tab    生成代码
217 | 选中文本,按Ctrl+Shift+F7    高亮显示所有该文本,按Esc高亮消失。
218 | Ctrl+B    快速打开光标处的类或方法
219 | Ctrl+E    最近打开的文件
220 | Alt+F1    查找代码所在位置
221 | Ctrl+Alt+L    格式化代码
222 | Ctrl+R    替换文本
223 | Ctrl+F    查找文本
224 | Ctrl+P    方法参数提示
225 | 
226 | Webstorm默认配置下的常用快捷键
227 | 查找/代替
228 | 快捷键
229 | 说明
230 | ctrl+shift+N     通过文件名快速查找工程内的文件(必记)
231 | ctrl+shift+alt+N     通过一个字符快速查找位置(必记)
232 | ctrl+F     在文件内快速查找代码
233 | F3     查找下一个
234 | shift+F3     查找上一个
235 | ctrl+R     文件内代码替换
236 | ctrl+shift+R     指定目录内代码批量替换
237 | ctrl+shift+F     指定目录内代码批量查找
238 | ctrl+R     文件内代码替换
239 | 界面操作
240 | 快捷键
241 | 说明
242 | ctrl+shift+A     快速查找并使用编辑器所有功能(必记)
243 | alt+[0-9]     快速拆合功能界面模块
244 | ctrl+shift+F12     最大区域显示代码(会隐藏其他的功能界面模块)
245 | alt+shift+F     将当前文件加入收藏夹
246 | ctrl+alt+s     打开配置窗口
247 | ctrl+tab     切换代码选项卡(还要进行此选择,效率差些)
248 | alt+<-或->     切换代码选项卡
249 | 快捷键
250 | 说明
251 | ctrl+shift+N     通过文件名快速查找工程内的文件(必记)
252 | ctrl+shift+alt+N     通过一个字符快速查找位置(必记)
253 | ctrl+F     在文件内快速查找代码
254 | F3     查找下一个
255 | shift+F3     查找上一个
256 | ctrl+R     文件内代码替换
257 | ctrl+shift+R     指定目录内代码批量替换
258 | ctrl+shift+F     指定目录内代码批量查找
259 | ctrl+R     文件内代码替换
260 | 界面操作
261 | 快捷键
262 | 说明
263 | ctrl+shift+A     快速查找并使用编辑器所有功能(必记)
264 | alt+[0-9]     快速拆合功能界面模块
265 | ctrl+shift+F12     最大区域显示代码(会隐藏其他的功能界面模块)
266 | alt+shift+F     将当前文件加入收藏夹
267 | ctrl+alt+s     打开配置窗口
268 | ctrl+tab     切换代码选项卡(还要进行此选择,效率差些)
269 | alt+<-或->     切换代码选项卡
270 | ctrl+F4     关闭当前代码选项卡
271 | 代码编辑
272 | 快捷键
273 | 说明
274 | ctrl+D     复制当前行
275 | ctrl+W     选中单词
276 | ctrl+<-或->     以单词作为边界跳光标位置
277 | alt+Insert     新建一个文件或其他
278 | ctrl+alt+L     格式化代码
279 | shift+tab/tab     减少/扩大缩进(可以在代码中减少行缩进)
280 | ctrl+Y     删除一行
281 | shift+enter     重新开始一行(无论光标在哪个位置)
282 | 导航
283 | 快捷键
284 | 说明
285 | esc     进入代码编辑区域
286 | alt+F1     查找代码在其他界面模块的位置,颇为有用
287 | ctrl+G     到指定行的代码
288 | ctrl+]/     光标到代码块的前面或后面
289 | alt+up/down     上一个/下一个方法
290 | 建议配置版本控制快捷键
291 | 快捷键
292 | 说明
293 | ctrl+C     提交代码
294 | ctrl+p     向远程版本库推送更新
295 | ctrl+G     到指定行的代码
296 | ctrl+]/     光标到代码块的前面或后面
297 | alt+up/down     上一个/下一个方法
298 | 
-------------------------------------------------------------------------------- /Jade.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | JADE 7 | ==== 8 | 9 | 非常简洁、强大的html模版,express 内置标准模版! 10 | 虽然在上万行的测试效率方面比 ejs 低,但是,实际上模版文件一般也就几百行, 11 | 毫秒级别的差异可忽略不计! 12 | 13 | 但是,代码数要少好几倍! 14 | 强烈推荐!!! 15 | 16 | 语法: 17 | 源码: 18 | 19 | html 转换为jade 20 | http://html2jade.org/ 21 | 22 | jade转换为html 23 | Jade watcher 24 | 25 | ## 功能 26 | 27 | - client-side support 28 | - great readability 29 | - flexible indentation 30 | - block-expansion 31 | - mixins 32 | - static includes 33 | - attribute interpolation 34 | - code is escaped by default for security 35 | - contextual error reporting at compile & run time 36 | - executable for compiling jade templates via the command line 37 | - html 5 mode (the default doctype) 38 | - optional memory caching 39 | - combine dynamic and static tag classes 40 | - parse tree manipulation via _filters_ 41 | - template inheritance 42 | - block append / prepend 43 | - supports [Express JS](http://expressjs.com) out of the box 44 | - transparent iteration over objects, arrays, and even non-enumerables via `each` 45 | - block comments 46 | - no tag prefix 47 | - filters 48 | - :stylus must have [stylus](http://github.com/LearnBoost/stylus) installed 49 | - :less must have [less.js](http://github.com/cloudhead/less.js) installed 50 | - :markdown must have [markdown-js](http://github.com/evilstreak/markdown-js), [node-discount](http://github.com/visionmedia/node-discount), or [marked](http://github.com/chjj/marked) installed 51 | - :cdata 52 | - :coffeescript must have [coffee-script](http://jashkenas.github.com/coffee-script/) installed 53 | - [Emacs Mode](https://github.com/brianc/jade-mode) 54 | - [Vim Syntax](https://github.com/digitaltoad/vim-jade) 55 | - [TextMate Bundle](http://github.com/miksago/jade-tmbundle) 56 | - [Coda/SubEtha syntax Mode](https://github.com/aaronmccall/jade.mode) 57 | - [Screencasts](http://tjholowaychuk.com/post/1004255394/jade-screencast-template-engine-for-nodejs) 58 | - [html2jade](https://github.com/donpark/html2jade) converter 59 | 60 | 61 | 62 | ## 示例 63 | ```jade 64 | !!! 5 65 | html 66 | head 67 | meta(charset='utf-8') 68 | title my jade template 69 | body 70 | h1 Hello #{name} 71 | ``` 72 | 输出: 73 | 74 | ```html 75 | 76 | 77 | 78 | 79 | my jade template 80 | 81 | 82 |

Hello Bob

83 | 84 | 85 | ``` 86 | 87 | ## 标记 88 | 直接写标记,不需要 <>,不需要配套的结束标记,代码量少好几倍,更清晰更简短! 89 | 层次关系通过 空格实现,非常直观! 90 | 91 | div 可省略 92 | \#user 93 | .user.user2 94 | 95 | ### 单行嵌套 96 | ul.nav 97 | li.active: a(href="#") Home 98 | li: a(href="#about") About 99 | li: a(href="#contact") Contact 100 | 101 | 注意 : 及 ) 后的空格,如果没有空格,将得不到正确结果 102 | 103 | ### Doctypes 104 | 105 | To add a doctype simply use !!!, or doctype followed by an optional value: 106 | 107 | `!!!` 108 | or 109 | `doctype` 110 | Will output the html 5 doctype, however: 111 | 112 | `!!! transitional` 113 | Will output the `transitional doctype`. 114 | 115 | Doctypes are case-insensitive, so the following are equivalent: 116 | ``` 117 | doctype Basic 118 | doctype basic 119 | ``` 120 | it's also possible to simply pass a doctype literal: 121 | ``` 122 | doctype html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" 123 | ``` 124 | yielding: 125 | ``` 126 | 127 | ``` 128 | 129 | Below are the doctypes defined by default, which can easily be extended: 130 | ``` 131 | var doctypes = exports.doctypes = { 132 | '5': '', 133 | 'default': '', 134 | 'xml': '', 135 | 'transitional': '', 136 | 'strict': '', 137 | 'frameset': '', 138 | '1.1': '', 139 | 'basic': '', 140 | 'mobile': '' 141 | }; 142 | ``` 143 | To alter the default simply change: 144 | ``` 145 | jade.doctypes.default = 'whatever you want'; 146 | ``` 147 | 148 | ### 属性 149 | a(href='/login', title='View login page') Login 150 | 注意 Login 之前的空格! 151 | 152 | ## 文本 153 | 通过 . 或 | 实现,注意 p. 中间不能有 空格 154 | 注意,script、style 两个标记的文本不需要 | 符号,可直接写! 155 | 156 | ``` 157 | html 158 | body 159 | |

Title

160 | |

foo bar baz

161 | ``` 162 | 或者: 163 | ``` 164 | html 165 | body. 166 |

Title

167 |

foo bar baz

168 | ``` 169 | 注意,点前面不能有空格! 170 | 171 | jade 空格 172 | |男     173 | 174 | 175 | ## 变量 176 | 177 | jade变量属于 js 代码的一种,jade 模版 不通过 代码标记-,也能智能识别 js 代码, 178 | 因此,代码中的变量,能自动转换为字符串! 179 | 180 | 任何模版都支持变量,一般都通过 = 来实现,jade则支持好几种: 181 | 182 | - = 或 != 183 | \- var foo = 'bar' 184 | = foo 185 | h1= foo 186 | 注意 =前面不能有空格!!! 187 | 188 | = 对 <> 会自动转码,确保一些html标记按原文输出, 189 | != 则 不会转码,内嵌的 html 标记将 按标记输出,相当于 能获得 标记效果! 190 | {"name": "Hello World"} 191 | li= name
  • Hello <em>World</em>
  • 192 | li!= name
  • Hello World
  • 193 | 194 | - 字符串嵌入变量引用 \#{} 或 !{} 195 | 同时,与 = 一样的效果,undefined时, #{} 自动转换为 undefined字符串 196 | a(href='/user/' + user.id)= user.name 197 | 作为变量处理! 198 | 等同: 199 | a(href='/user/#{user.id}')= user.name 200 | 内嵌写法! 201 | 如对 undefined变量显示空字符串,则需对变量进行判断! 202 | a(href='/user/#{user.id?user.id:''}')= user.name 203 | 204 | 205 | 206 | ## 代码 207 | Jade目前支持三种类型的可执行代码,第一种以-为前缀,不会被缓冲: 208 | 209 | 更加智能,书写非常流程,爽!不像其他 模版,需要前缀、后缀! 210 | 211 | - 前缀\- 实现,如 \- var foo = 'bar' 212 | - 智能推断,如 if, else if, else, until, while, unless 213 | unless user.isAnonymous 214 | p You're logged in as #{user.name} 215 | 216 | - = 对于 p textarea等 非 value 可直接使用 = 217 | 如 218 | p=nick 219 | a=nick 220 | 221 | input#txNick.input-xlarge(type="text", name="txNick", value=nick) 222 | undefined 会输出空 223 | input#txShowName.input-xlarge(type="text", name="txAlias", value="#{alias}") 224 | undefined 会输出 undefined字符串! 225 | 226 | - != 227 | 228 | - var foo = 'bar'; 229 | 这可被用于条件或循环: 230 | 231 | - for (var key in obj) 232 | p= obj[key] 233 | 由于Jade的缓冲技术,下面的代码是有效的: 234 | 235 | - if (foo) 236 | ul 237 | li yay 238 | li foo 239 | li worked 240 | - else 241 | p oh no! you are not in csser.com 242 | 243 | 如果 foo 未定义,会报错! 244 | 245 | if typeof foo !== "undefined" 246 | 247 | 甚至详细的迭代循环: 248 | 249 | - if (items.length) 250 | ul 251 | - items.forEach(function(item){ 252 | li= item 253 | - }) 254 | 任何你希望的都可以实现! 255 | 256 | 接下来我们转义了缓冲代码,用于缓冲返回值,以等号(=)作为前缀: 257 | 258 | - var foo = 'bar' 259 | = foo 260 | h1= foo 261 | 输出: bar

    bar

    . 被'='缓冲的代码会默认经过转义以增强安全性,要输出为转义的值需要使用 !=: 262 | 263 | p!= aVarContainingMoreHTML 264 | 一个允许使用"vanilla"Javascript的例外,是 - each 标记,其表现形式为: 265 | 266 | - each VAL[, KEY] in OBJ 267 | 实现循环数组的例子: 268 | 269 | - var items = ["one", "two", "three"] 270 | - each item in items 271 | li= item 272 | 输出: 273 | 274 |
  • one
  • 275 |
  • two
  • 276 |
  • three
  • 277 | 循环对象的键和值: 278 | 279 | - var obj = { foo: 'bar' } 280 | - each val, key in obj 281 | li #{key}: #{val} 282 | 这会输出
  • foo: bar
  • 283 | 284 | 也可以进行嵌套循环: 285 | 286 | - each user in users 287 | - each role in user.roles 288 | li= role 289 | 当一个属性为undefined,Jade会输出空串,例如: 290 | 291 | textarea= user.signature 292 | 近期的Jade版本会输出空字符串而不是undefined: 293 | 294 | 295 | 296 | 297 | 298 | 299 | ## 迭代 300 | 所有模版都支持迭代,否则无法实现列表! 301 | 302 | ``` 303 | - var items = ["one", "two", "three"] 304 | each item in items 305 | li= item 306 | ``` 307 | outputs: 308 | ``` 309 |
  • one
  • 310 |
  • two
  • 311 |
  • three
  • 312 | ``` 313 | 314 | iterating an array with index: 315 | ``` 316 | items = ["one", "two", "three"] 317 | each item, i in items 318 | li #{item}: #{i} 319 | ``` 320 | 321 | outputs: 322 | ``` 323 |
  • one: 0
  • 324 |
  • two: 1
  • 325 |
  • three: 2
  • 326 | ``` 327 | 328 | iterating an object's keys and values: 329 | ``` 330 | obj = { foo: 'bar' } 331 | each val, key in obj 332 | li #{key}: #{val} 333 | ``` 334 | would output `
  • foo: bar
  • ` 335 | 336 | Internally Jade converts these statements to regular JavaScript loops such as users.forEach(function(user){, 337 | so lexical scope and nesting applies as it would with regular JavaScript: 338 | ``` 339 | each user in users 340 | each role in user.roles 341 | li= role 342 | ``` 343 | You may also use for if you prefer: 344 | ``` 345 | for user in users 346 | for role in user.roles 347 | li= role 348 | ``` 349 | 350 | ## 注释 351 | 注释通过 // 实现,如果不需要输出,则用 //- 352 | 353 | ## 过滤器 354 | 相当于插件,一般模版都不支持过滤器,比如 内置的 markdown过滤器,也就是说可以写入 markdown,输出 html! 355 | 356 | :markdown 357 | # Markdown 358 | 359 | I often like including markdown documents in my jade templates. 360 | :coffee 361 | console.log 'This is coffee script' 362 | 363 | 364 | ``` 365 | body 366 | :markdown 367 | Woah! jade _and_ markdown, very **cool** 368 | we can even link to [stuff](http://google.com) 369 | ``` 370 | 输出: 371 | ``` 372 |

    Woah! jade and markdown, very cool we can even link to stuff

    373 | ``` 374 | 375 | ## 继承 376 | 一般模版没有继承。继承通过 `block` and `extends` 关键字实现。 377 | express 支持 jade 继承功能! 378 | 一般 内容模块会从 母版继承! 379 | 380 | block 缺省时覆盖, 也可 prepend, or append blocks. 381 | 382 | ## 包含 include 383 | 一个jade 文件可包含另外一个文件,包括 js、css、jade,缺省为 jade后缀! 384 | 385 | ``` 386 | html 387 | include includes/head 388 | body 389 | h1 My Site 390 | p Welcome to my super amazing site. 391 | include includes/foot 392 | ``` 393 | 394 | ## 混入 mixin 395 | 插入 片段,类似 ejs 的 partials 功能,如果跨文件,则 需通过 include将独立文件包含进来! 396 | ejs 则 不需要 包含,通过 名称约定完成,jade 更加灵活! 397 | 398 | 399 | ``` 400 | mixin book(name, price) 401 | li #{name} for #{price} € 402 | 403 | ul#books 404 | +book("Book A", 12.99) 405 | +book("Book B", 5.99) 406 | ``` 407 | 408 | 输出: 409 | ``` 410 |
      411 |
    • Book A for 12.99 €
    • 412 |
    • Book B for 5.99 €
    • 413 |
    414 | ``` 415 | 416 | 417 | ## 传值 418 | 419 | Passing Variables to Your Templates via the Response Object 420 | Variables can be passed down to a template as a parameter to the response object, but functions cannot. Here is an example showing how to set and access these variables. 421 | ``` 422 | var locals = { title: 'My page title', includes: {charting: true} }; 423 | app.render( 'mypage', locals ); 424 | ``` 425 | Template File 426 | ``` 427 | <% if( locals.includes.charting ) { %> 428 |

    Charting is included

    429 | <% } %> 430 |

    locals:<%- JSON.stringify(locals) %>

    431 | ``` 432 | 433 | Functions cannot be passed down via the response object. That means there is no replacement for the template-initiated processing that dynamic helpers provided. 434 | Another trick is to use middleware to add properties or methods to the request object then, on render, pass derived properties to the render method. This is how the connect-flash modules operates. 435 | Passing Variables to Your Templates via the App Object 436 | You can pass app-level variables to your templates by attaching properties or functions to app.settings. Although this is referred to as app.locals in the documentation, you can’t actually set app.locals.myvar to a value and see this in your template. I presume this is another case of documentation written for people who already understand the application, meaning it wasn’t written for me. 437 | To set an app-level variable or function you either call app.set() or set a property of app.settings as shown below. 438 | In app.js 439 | ``` 440 | app.set('tLaunch',new Date()); 441 | app.settings.appName = 'MyApp'; // Equivalent to using app.set(appName,'MyApp'); 442 | app.set('appVersion',function() { config.getAppVersion() }); 443 | ``` 444 | To read the app-level variable in your template you reference settings.myvar. To call the function you call settings.myfunc(). Remember, you can’t pass any parameters to the function, so you can’t get request-specific data using this function. 445 | Template File 446 | ``` 447 |

    The time my app was launched:<%- settings.tLaunch.toString() %>

    448 |

    App Name:<%- settings.appName %>

    449 |

    App Version:<%- settings.appVersion() %>

    450 | ``` 451 | 452 | app.locals 453 | Application local variables are provided to all templates rendered within the application. This is useful for providing helper functions to templates, as well as app-level data. 454 | 455 | app.locals.title = 'My App'; 456 | app.locals.strftime = require('strftime'); 457 | The app.locals object is a JavaScript Function, which when invoked with an object will merge properties into itself, providing a simple way to expose existing objects as local variables. 458 | 459 | app.locals({ 460 | title: 'My App', 461 | phone: '1-250-858-9990', 462 | email: 'me@myapp.com' 463 | }); 464 | 465 | app.locals.title 466 | // => 'My App' 467 | 468 | app.locals.email 469 | // => 'me@myapp.com' 470 | By default Express exposes only a single app-level local variable, settings. 471 | 472 | app.set('title', 'My App'); 473 | // use settings.title in a view 474 | 475 | 476 | ## radio select 477 | 478 | .control-group 479 | label.control-label(for="txSex") 性别 480 | .controls 481 | label.radio.inline 482 | input#txSex1.inline(type="radio", name="txSex", value="男", checked=sex=="男") 483 | | 男     484 | label.radio.inline 485 | input#txSex2.inline(type="radio", name="txSex", value="女", checked=sex=="女") 486 | 女 487 | .control-group 488 | label.control-label(for="txType") 类别 489 | .controls 490 | select#txType(name="txType") 491 | option(value=1,selected=type==1) 个人 492 | option(value=2,selected=type==2) 企业 493 | option(value=3,selected=type==3) 群组 494 | option(value=4,selected=type==4) 公众 495 | 496 | Boolean Attributes 497 | 498 | Boolean attributes are mirrored by Jade, and accept bools, aka true or false. When no value is specified true is assumed. 499 | 500 | input(type='checkbox', checked) 501 | input(type='checkbox', checked=true) 502 | input(type='checkbox', checked=false) 503 | input(type='checkbox', checked=true.toString()) 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | ## undefined 处理 512 | 后台 render对象 与 jade模版引用的变量不一致,导致缺失的字段全部显示 undefined 字符串! 513 | input#txNick.input-xlarge(type="text", name="txNick", value=nick) 514 | undefined 会输出空 515 | input#txShowName.input-xlarge(type="text", name="txAlias", value="#{alias}") 516 | undefined 会输出 undefined字符串! 517 | 518 | -------------------------------------------------------------------------------- /html/eslint.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |

    eslint

    12 |

    最好的js 静态风格、语法、错误检查及在线提示。

    13 |
    14 |

    ESLint 由 JavaScript 红宝书 作者 Nicholas C. Zakas 编写, 2013 年发布第一个版本。 NCZ 的初衷不是重复造一个轮子,而是在际需求得不到 JSHint 团队响应 的情况下做出的选择:以可扩展、每条规则独立、不内置编码风格为理念编写一个 lint 工具。

    15 |
    16 |

    ESLint 主要有以下特点:

    17 |
      18 |
    • 默认规则包含所有 JSLint、JSHint 中存在的规则,易迁移
    • 19 |
    • 规则可配置性高:可设置「警告」、「错误」两个 error 等级,或者直接禁用
    • 20 |
    • 包含代码风格检测的规则(可以丢掉 JSCS 了)
    • 21 |
    • 支持插件扩展、自定义规则
    • 22 |
    • 支持JSX语法,而JSHint 不支持 JSX 语法
    • 23 |
    24 |

    配置

    25 |
      26 |
    • 可以通过以下三种方式配置 ESLint:
    • 27 |
    • 使用 .eslintrc 文件(支持 JSON 和 YAML 两种语法);
    • 28 |
    • 在 package.json 中添加 eslintConfig 配置块;
    • 29 |
    • 直接在代码文件中定义。
    • 30 |
    31 |

    资源

    32 |

    官网 | 33 | 配置 | 34 | 规则 | 35 | 贡献 | 36 | 缺陷 | 37 | Code of Conduct | 38 | Twitter | 39 | 邮件列表 | 40 | 聊天室

    41 |

    安装

    42 |

    npm install -g eslint

    43 |

    使用

    44 |
      45 |
    • 创建 .eslintrc文件 46 | eslint --init
    • 47 |
    • 检查js文件 48 | eslint test.js test2.js
    • 49 |
    50 |

    配置

    51 |

    修改 .eslintrc 文件,定义规则

    52 |
    {
     53 |   "rules": {
     54 |     "semi": ["error", "always"],
     55 |     "quotes": ["error", "double"]
     56 |   }
     57 | }
     58 | 
    59 |

    "semi""quotes" 预定义的规则名称rules
    第一个值是提示级别

    60 |
      61 |
    • "off" or 0 - 关闭
    • 62 |
    • "warn" or 1 - 警告
    • 63 |
    • "error" or 2 - 错误
    • 64 |
    65 |

    详细说明请参见配置说明)。

    66 |

    本项目使用的 .eslintrc 文件

    67 |
      68 |
    • 继承 eslint-config-airbnb/base
    • 69 |
    • 需安装以下插件

      70 |
      "eslint": "^2.9.0",
       71 | "eslint-config-airbnb": "^9.0.1",
       72 | "eslint-plugin-import": "^1.8.0",
       73 | "eslint-plugin-jsx-a11y": "^1.2.0",
       74 | "eslint-plugin-react": "^5.1.1",
       75 | 
      76 |
    • 77 |
    • 文件内容

      78 |
      {
       79 |   "extends": "eslint-config-airbnb/base",
       80 |   "parser": "babel-eslint",
       81 |   "env": {
       82 |     "browser": true,
       83 |     "node": true,
       84 |     "mocha": true
       85 |   },
       86 |   "rules": {
       87 |     // Disable for console/alert
       88 |     "no-console": 0,
       89 |     "no-alert": 0,
       90 | 
       91 |     "indent": [2, 2, {"SwitchCase": 1}],
       92 |     "object-curly-spacing": 0
       93 |   },
       94 |   "plugins": [
       95 |     "import"
       96 |   ],
       97 |   "settings": {
       98 |     "import/parser": "babel-eslint",
       99 |     "import/resolve": {
      100 |       "moduleDirectory": ["node_modules", "src"]
      101 |     }
      102 |   },
      103 |   "globals": {
      104 |     "__DEV__": true,
      105 |     "__OPTION__": true
      106 |   }
      107 | }
      108 | 
      109 |
    • 110 |
    111 |

    以下是详细 .eslintrc 文件示例和解释:

    112 |
    {  
    113 |   "env": {  
    114 |     "browser": true,  
    115 |     "node": true,  
    116 |     "commonjs": true  
    117 |   },  
    118 |   "ecmaFeatures": {  
    119 |     // lambda表达式  
    120 |     "arrowFunctions": true,  
    121 |     // 解构赋值  
    122 |     "destructuring": true,  
    123 |     // class  
    124 |     "classes": true,  
    125 |     // http://es6.ruanyifeng.com/#docs/function#函数参数的默认值  
    126 |     "defaultParams": true,  
    127 |     // 块级作用域,允许使用let const  
    128 |     "blockBindings": true,  
    129 |     // 允许使用模块,模块内默认严格模式  
    130 |     "modules": true,  
    131 |     // 允许字面量定义对象时,用表达式做属性名  
    132 |     // http://es6.ruanyifeng.com/#docs/object#属性名表达式  
    133 |     "objectLiteralComputedProperties": true,  
    134 |     // 允许对象字面量方法名简写  
    135 |     /*var o = { 
    136 |         method() { 
    137 |           return "Hello!"; 
    138 |         } 
    139 |      }; 
    140 | 
    141 |      等同于 
    142 | 
    143 |      var o = { 
    144 |        method: function() { 
    145 |          return "Hello!"; 
    146 |        } 
    147 |      }; 
    148 |     */  
    149 |     "objectLiteralShorthandMethods": true,  
    150 |     /* 
    151 |       对象字面量属性名简写 
    152 |       var foo = 'bar'; 
    153 |       var baz = {foo}; 
    154 |       baz // {foo: "bar"} 
    155 | 
    156 |       // 等同于 
    157 |       var baz = {foo: foo}; 
    158 |     */  
    159 |     "objectLiteralShorthandProperties": true,  
    160 |     // http://es6.ruanyifeng.com/#docs/function#rest参数  
    161 |     "restParams": true,  
    162 |     // http://es6.ruanyifeng.com/#docs/function#扩展运算符  
    163 |     "spread": true,  
    164 |     // http://es6.ruanyifeng.com/#docs/iterator#for---of循环  
    165 |     "forOf": true,  
    166 |     // http://es6.ruanyifeng.com/#docs/generator  
    167 |     "generators": true,  
    168 |     // http://es6.ruanyifeng.com/#docs/string#模板字符串  
    169 |     "templateStrings": true,  
    170 |     "superInFunctions": true,  
    171 |     // http://es6.ruanyifeng.com/#docs/object#对象的扩展运算符  
    172 |     "experimentalObjectRestSpread": true  
    173 |   },  
    174 | 
    175 |   "rules": {  
    176 |     // 定义对象的set存取器属性时,强制定义get  
    177 |     "accessor-pairs": 2,  
    178 |     // 指定数组的元素之间要以空格隔开(,后面), never参数:[ 之前和 ] 之后不能带空格,always参数:[ 之前和 ] 之后必须带空格  
    179 |     "array-bracket-spacing": [2, "never"],  
    180 |     // 在块级作用域外访问块内定义的变量是否报错提示  
    181 |     "block-scoped-var": 0,  
    182 |     // if while function 后面的{必须与if在同一行,java风格。  
    183 |     "brace-style": [2, "1tbs", { "allowSingleLine": true }],  
    184 |     // 双峰驼命名格式  
    185 |     "camelcase": 2,  
    186 |     // 数组和对象键值对最后一个逗号, never参数:不能带末尾的逗号, always参数:必须带末尾的逗号,  
    187 |     // always-multiline:多行模式必须带逗号,单行模式不能带逗号  
    188 |     "comma-dangle": [2, "never"],  
    189 |     // 控制逗号前后的空格  
    190 |     "comma-spacing": [2, { "before": false, "after": true }],  
    191 |     // 控制逗号在行尾出现还是在行首出现  
    192 |     // http://eslint.org/docs/rules/comma-style  
    193 |     "comma-style": [2, "last"],  
    194 |     // 圈复杂度  
    195 |     "complexity": [2,9],  
    196 |     // 以方括号取对象属性时,[ 后面和 ] 前面是否需要空格, 可选参数 never, always  
    197 |     "computed-property-spacing": [2,"never"],  
    198 |     // 强制方法必须返回值,TypeScript强类型,不配置  
    199 |     "consistent-return": 0,  
    200 |     // 用于指统一在回调函数中指向this的变量名,箭头函数中的this已经可以指向外层调用者,应该没卵用了  
    201 |     // e.g [0,"that"] 指定只能 var that = this. that不能指向其他任何值,this也不能赋值给that以外的其他值  
    202 |     "consistent-this": 0,  
    203 |     // 强制在子类构造函数中用super()调用父类构造函数,TypeScrip的编译器也会提示  
    204 |     "constructor-super": 0,  
    205 |     // if else while for do后面的代码块是否需要{ }包围,参数:  
    206 |     //    multi  只有块中有多行语句时才需要{ }包围  
    207 |     //    multi-line  只有块中有多行语句时才需要{ }包围, 但是块中的执行语句只有一行时,  
    208 |     //                   块中的语句只能跟和if语句在同一行。if (foo) foo++; else doSomething();  
    209 |     //    multi-or-nest 只有块中有多行语句时才需要{ }包围, 如果块中的执行语句只有一行,执行语句可以零另起一行也可以跟在if语句后面  
    210 |     //    [2, "multi", "consistent"] 保持前后语句的{ }一致  
    211 |     //    default: [2, "all"] 全都需要{ }包围  
    212 |     "curly": [2, "all"],  
    213 |     // switch语句强制default分支,也可添加 // no default 注释取消此次警告  
    214 |     "default-case": 2,  
    215 |     // 强制object.key 中 . 的位置,参数:  
    216 |     //      property,'.'号应与属性在同一行  
    217 |     //      object, '.' 号应与对象名在同一行  
    218 |     "dot-location": [2, "property"],  
    219 |     // 强制使用.号取属性  
    220 |     //    参数: allowKeywords:true 使用保留字做属性名时,只能使用.方式取属性  
    221 |     //                          false 使用保留字做属性名时, 只能使用[]方式取属性 e.g [2, {"allowKeywords": false}]  
    222 |     //           allowPattern:  当属性名匹配提供的正则表达式时,允许使用[]方式取值,否则只能用.号取值 e.g [2, {"allowPattern": "^[a-z]+(_[a-z]+)+$"}]  
    223 |     "dot-notation": [2, {"allowKeywords": true}],  
    224 |     // 文件末尾强制换行  
    225 |     "eol-last": 2,  
    226 |     // 使用 === 替代 ==  
    227 |     "eqeqeq": [2, "allow-null"],  
    228 |     // 方法表达式是否需要命名  
    229 |     "func-names": 0,  
    230 |     // 方法定义风格,参数:  
    231 |     //    declaration: 强制使用方法声明的方式,function f(){} e.g [2, "declaration"]  
    232 |     //    expression:强制使用方法表达式的方式,var f = function() {}  e.g [2, "expression"]  
    233 |     //    allowArrowFunctions: declaration风格中允许箭头函数。 e.g [2, "declaration", { "allowArrowFunctions": true }]  
    234 |     "func-style": 0,  
    235 |     "generator-star-spacing": [2, { "before": true, "after": true }],  
    236 |     "guard-for-in": 0,  
    237 |     "handle-callback-err": [2, "^(err|error)$" ],  
    238 |     "indent": [2, 2, { "SwitchCase": 1 }],  
    239 |     "key-spacing": [2, { "beforeColon": false, "afterColon": true }],  
    240 |     "linebreak-style": 0,  
    241 |     "lines-around-comment": 0,  
    242 |     "max-nested-callbacks": 0,  
    243 |     "new-cap": [2, { "newIsCap": true, "capIsNew": false }],  
    244 |     "new-parens": 2,  
    245 |     "newline-after-var": 0,  
    246 |     "no-alert": 0,  
    247 |     "no-array-constructor": 2,  
    248 |     "no-caller": 2,  
    249 |     "no-catch-shadow": 0,  
    250 |     "no-cond-assign": 2,  
    251 |     "no-console": 0,  
    252 |     "no-constant-condition": 0,  
    253 |     "no-continue": 0,  
    254 |     "no-control-regex": 2,  
    255 |     "no-debugger": 2,  
    256 |     "no-delete-var": 2,  
    257 |     "no-div-regex": 0,  
    258 |     "no-dupe-args": 2,  
    259 |     "no-dupe-keys": 2,  
    260 |     "no-duplicate-case": 2,  
    261 |     "no-else-return": 0,  
    262 |     "no-empty": 0,  
    263 |     "no-empty-character-class": 2,  
    264 |     "no-empty-label": 2,  
    265 |     "no-eq-null": 0,  
    266 |     "no-eval": 2,  
    267 |     "no-ex-assign": 2,  
    268 |     "no-extend-native": 2,  
    269 |     "no-extra-bind": 2,  
    270 |     "no-extra-boolean-cast": 2,  
    271 |     "no-extra-parens": 0,  
    272 |     "no-extra-semi": 0,  
    273 |     "no-fallthrough": 2,  
    274 |     "no-floating-decimal": 2,  
    275 |     "no-func-assign": 2,  
    276 |     "no-implied-eval": 2,  
    277 |     "no-inline-comments": 0,  
    278 |     "no-inner-declarations": [2, "functions"],  
    279 |     "no-invalid-regexp": 2,  
    280 |     "no-irregular-whitespace": 2,  
    281 |     "no-iterator": 2,  
    282 |     "no-label-var": 2,  
    283 |     "no-labels": 2,  
    284 |     "no-lone-blocks": 2,  
    285 |     "no-lonely-if": 0,  
    286 |     "no-loop-func": 0,  
    287 |     "no-mixed-requires": 0,  
    288 |     "no-mixed-spaces-and-tabs": 2,  
    289 |     "no-multi-spaces": 2,  
    290 |     "no-multi-str": 2,  
    291 |     "no-multiple-empty-lines": [2, { "max": 1 }],  
    292 |     "no-native-reassign": 2,  
    293 |     "no-negated-in-lhs": 2,  
    294 |     "no-nested-ternary": 0,  
    295 |     "no-new": 2,  
    296 |     "no-new-func": 0,  
    297 |     "no-new-object": 2,  
    298 |     "no-new-require": 2,  
    299 |     "no-new-wrappers": 2,  
    300 |     "no-obj-calls": 2,  
    301 |     "no-octal": 2,  
    302 |     "no-octal-escape": 2,  
    303 |     "no-param-reassign": 0,  
    304 |     "no-path-concat": 0,  
    305 |     "no-process-env": 0,  
    306 |     "no-process-exit": 0,  
    307 |     "no-proto": 0,  
    308 |     "no-redeclare": 2,  
    309 |     "no-regex-spaces": 2,  
    310 |     "no-restricted-modules": 0,  
    311 |     "no-return-assign": 2,  
    312 |     "no-script-url": 0,  
    313 |     "no-self-compare": 2,  
    314 |     "no-sequences": 2,  
    315 |     "no-shadow": 0,  
    316 |     "no-shadow-restricted-names": 2,  
    317 |     "no-spaced-func": 2,  
    318 |     "no-sparse-arrays": 2,  
    319 |     "no-sync": 0,  
    320 |     "no-ternary": 0,  
    321 |     "no-this-before-super": 2,  
    322 |     "no-throw-literal": 2,  
    323 |     "no-trailing-spaces": 2,  
    324 |     "no-undef": 2,  
    325 |     "no-undef-init": 2,  
    326 |     "no-undefined": 0,  
    327 |     "no-underscore-dangle": 0,  
    328 |     "no-unexpected-multiline": 2,  
    329 |     "no-unneeded-ternary": 2,  
    330 |     "no-unreachable": 2,  
    331 |     "no-unused-expressions": 0,  
    332 |     "no-unused-vars": [2, { "vars": "all", "args": "none" }],  
    333 |     "no-use-before-define": 0,  
    334 |     "no-var": 0,  
    335 |     "no-void": 0,  
    336 |     "no-warning-comments": 0,  
    337 |     "no-with": 2,  
    338 |     "object-curly-spacing": 0,  
    339 |     "object-shorthand": 0,  
    340 |     "one-var": [2, { "initialized": "never" }],  
    341 |     "operator-assignment": 0,  
    342 |     "operator-linebreak": [2, "after", { "overrides": { "?": "before", ":": "before" } }],  
    343 |     "padded-blocks": 0,  
    344 |     "prefer-const": 0,  
    345 |     "quote-props": 0,  
    346 |     "quotes": [2, "single", "avoid-escape"],  
    347 |     "radix": 2,  
    348 |     "semi": [2, "never"],  
    349 |     "semi-spacing": 0,  
    350 |     "sort-vars": 0,  
    351 |     "space-after-keywords": [2, "always"],  
    352 |     "space-before-blocks": [2, "always"],  
    353 |     "space-before-function-paren": [2, "always"],  
    354 |     "space-in-parens": [2, "never"],  
    355 |     "space-infix-ops": 2,  
    356 |     "space-return-throw-case": 2,  
    357 |     "space-unary-ops": [2, { "words": true, "nonwords": false }],  
    358 |     "spaced-comment": [2, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!"] }],  
    359 |     "strict": 0,  
    360 |     "use-isnan": 2,  
    361 |     "valid-jsdoc": 0,  
    362 |     "valid-typeof": 2,  
    363 |     "vars-on-top": 0,  
    364 |     "wrap-iife": [2, "any"],  
    365 |     "wrap-regex": 0,  
    366 |     "yoda": [2, "never"]  
    367 |   }  
    368 | }
    369 | 
    370 | --------------------------------------------------------------------------------