npm
很多模块有一个或多个需要配置到PATH路径下的可执行模块,npm让这个工作变得十分简单(实际上npm本身也是通过bin属性安装为一个可执行命令的)
如果要用npm的这个功能,在package.json里边配置一个bin属性。bin属性是一个已命令名称为key,本地文件名称为value的map如下:
{ "bin" : { "myapp" : "./cli.js" } }
模块安装的时候,若是全局安装,则npm会为bin中配置的文件在bin目录下创建一个软连接(对于windows系统,默认会在C:UsersusernameAppDataRoamingnpm目录下),若是局部安装,则会在项目内的./node_modules/.bin/目录下创建一个软链接。
因此,按上面的例子,当你安装myapp的时候,npm就会为cli.js在/usr/local/bin/myapp路径创建一个软链接。
如果你的模块只有一个可执行文件,并且它的命令名称和模块名称一样,你可以只写一个字符串来代替上面那种配置,例如:
{ "name": "my-program","version": "1.2.5","bin": "./path/to/program" }
作用和如下写法相同:
{ "name": "my-program","bin" : { "my-program" : "./path/to/program" } }
script
npm 会在项目的 package.json 文件中寻找 scripts 区域,其中包括npm test和npm start等命令。
其实npm test和npm start是npm run test和npm run start的简写。事实上,你可以使用npm run来运行scripts里的任何条目。
使用npm run的方便之处在于,npm会自动把node_modules/.bin加入$PATH,这样你可以直接运行依赖程序和开发依赖程序,不用全局安装了。只要npm上的包提供命令行接口,你就可以直接使用它们,方便吧?当然,你总是可以自己写一个简单的小程序。
{
"name": "test","version": "0.1.0","description": "A testing package",}
这个例子里我们定义了应用的入口文件( main )为 index ,当其他应用引用了我们的模块 require('test') 时,这个 main 的值 index.js 文件被调用。
文件模块 文件夹做为模块 核心模块 三方库模块(尝试在它的/node_modules文件夹中加载相应模块。如果没有找到,会继续查找上级目录,直到到达顶层目录。)=》
模块包装(在模块代码被执行前,Node.js会使用一个包装函数对其包装) =》
模块缓存(模块在第一次加载后会被缓存。) 循环依赖 =》
module对象
分配给module.exports的导出值必须能立刻获取到,当使用回调时其不能正常执行。
Caching
模块在加载之后会被缓存下来. 即多次require('foo')调用得到的是相同对象.
这样多次模块调用,但模块中的代码只会被执行一次. 该特点使得未完成的模块被返回,解决循环引用问题.
如果需要模块代码执行多次,可以export一个方法,然后多次调用即可.
因此,不要随便更改模块导出的变量
Loading from node_modules文件夹
如果模块以/开头则按绝对路径寻找模块 以./和../开头按相对路径寻找. 其他情况按核心模块或第三方模块寻找.
如果需要载入的模块不是core模块,也不是路径模块,则会从node_modules文件夹中寻找,寻找规则为从当前路径同级的
node_modules开始寻找,逐级向父路径寻找
例如 '/home/ry/projects/foo.js' 调用了 require('bar.js') 则寻找路径为:
/home/ry/projects/node_modules/bar.js
/home/ry/node_modules/bar.js
/home/node_modules/bar.js
/node_modules/bar.js
babel 在浏览器上用法与在 node上不同, 因为它本身是将ES6转化为commonJS格式。
除了 gulp,还有其它自动化构建工具(grunt 也是流行的构建工具),但由于 gulp 基于 node 的流(streams)实现,因此速度更快。
内存操作
Stream的整个操作过程,都在内存中进行。因此,相比Grunt,使用Stream的Gulp进行多步操作并不需要创建中间文件,可以省去额外的src和dest。
Gulp错误处理
Gulp有一个比较令人头疼的问题是,如果管道中有任意一个插件运行失败,整个Gulp进程就会挂掉。尤其在使用gulp.watch()做即时更新的时候,仅仅是临时更改了代码产生了语法错误,就可能使得watch挂掉,又需要到控制台里开启一遍。
对错误进行处理就可以改善这个问题。
但这种方法可能会需要在多个位置加入on("error"),此时推荐gulp-plumber,这个插件可以很方便地处理整个管道内的错误。
task方法还可以指定按顺序运行的一组任务。
gulp.task('build',['css','js','imgs']);
上面代码先指定build任务,它由css、js、imgs三个任务所组成,task方法会并发执行这三个任务。注意,由于每个任务都是异步调用,所以没有办法保证js任务的开始运行的时间,正是css任务运行结束。
如果希望各个任务严格按次序运行,可以把前一个任务写成后一个任务的依赖模块。
gulp.task('css',['greet'],function () {
// Deal with CSS here
});
上面代码表明,css任务依赖greet任务,所以css一定会在greet运行完成后再运行。
babel-cli babel-preset-2015用于以ES6解析执行gulpfile.babel.js文件本身(packjson的 "babel": { "presets": ["es2015"] },gulpfile.babel.js);
gulp-babel 用于处理经过gulp数据流的文件, 也需要babel-preset-2015
babel-preset-2015本身是一种规范,所以上述两种情况都要用到。另外,对包引入的选择方式,是gulp里写好的。npm只管执行,你(用户)只管给gulp把依赖包 npm install了就好。
gulp原生并不支持es6语法,但是我们可以告诉gulp使用babel将gulpfile转换为es5,方法就是将gulpfile命名为gulpfile.babel.js
说明白点,就是一个是用来转化gulpfile.babel.js文件本身的,一个是用来操作文件中控制的数据流的。