版权声明:此文章转载自凹凸实验室(http://aotu.io/notes/2016/02/26/use-npm-script-instead-of-gulp/)。
如需转载请联系听云College团队成员阮小乙,邮箱:ruanqy#tingyun.com
现在前端自动化的配套工具估计都离不开gulp或者是grunt,有一些或许会用上webpack辅助用上最新的ES6语法等;但是不知道大家在使用gulp众多插件的时候有没有碰到过一些问题,比如:有一些插件你仅仅需要用到其中一点点的API、插件更新速度非常慢、有一些插件碰到bug的时候调试起来非常麻烦等。所以总结一下gulp或者grunt其实都会有以下问题:
依赖于插件作者
调试很不方便
插件文档说明不连贯
而如果直接使用npm scripts完全可以避免这些问题,在我们package.json里面的scripts属性直接定义需要执行的任务,比如npm start和npm test其实就是npm run start和npm run test的缩写,我们可以在scripts里面定义各种需要的任务,举个最简单的例子(清除dist目录):
# 1.用gulp插件来实现 var gulp = require('gulp'); var del = require('del'); gulp.task('clean', function() { del(['./dist/**/*']).then(paths => { console.log('Deleted files and folders:/n', paths.join('/n')); }); }); # 2.用npm scripts来实现 # package.json配置 ... "scripts": { clean: "rimraf ./dist" }, "devDependencies": { "rimraf": "^2.5.2" }
从上面示例代码可以看出明显直接用npm scripts实现的同一个功能相对gulp要简单得多,当然这个功能比较简单,如果碰到复杂的一些任务肯定就有反对的声音了。那我们将细细将上面三点来阐述。
依赖于插件作者
当你需要使用到最新的或者不那么流行的技术时,根本就没有插件给你使用;或者一些插件已经过时了。最新Babel 6已经发布,很多API明显修改了,所以很多gulp插件根本不适用于最新版本。
这个时候你就必须等待作者来更新插件,或者你自己去fix这些问题,这会导致你不能及时用上最新版本的工具。相反,当你直接使用npm scripts的时候,你只需要直接找到可以实现的工具即可。这意味着当新版本的Mocha、Babel、Webpack、Browserify发布的时候,你就可以马上用上这些版本。
就目前插件数量来说,没有什么可以打败npm包:
Gulp大约有2100个插件,Grunt大约有5400个,而npm提供了227000个包,而且每天以400的速度在增加
调试很不方便
由于gulp增加了一层抽象,所以会有潜在的bug:
是否基础工具崩溃了?
是否Grunt/Gulp插件崩溃了?
是否配置文件出错了?
是否用了不稳定的版本?
而直接使用npm scripts直接避免了第2点跟第3点,而由于不使用那么多插件,那么包相对较少,第4点也很少会碰到。
插件文档说明不连贯
相比有用过很多插件的人都知道,一些核心的工具文档写得总比包装起来的Gulp插件要清晰得多。举个简单的例子来说,如果我需要用到gulp-eslint插件,那么就可能会不断在gulp-eslint的文档跟ESLint网站切换,必须对比看看两者存在些什么区别。
Gulp和Grunt之所以这么流行,主要有下面4个点:
开发者认为npm scripts需要能写命令行的技能
开发者认为npm scripts能处理的能力不足够
开发者觉得Gulp的流对于快速构建是很有必要的
开发者认为npm scripts不能跨平台运行
开发者认为npm scripts需要能写命令行的技能
其实你完全不需要精通于Unix或者Windows的命令行脚本,比如你不知道在Unix下面删除一个目录的命令是:rm -rf,这其实没啥问题,你完全可以使用rimraf,同时它也是跨平台的。在这里推荐一个工具包资源网站:libraries.io
开发者认为npm scripts能处理的能力不足够
npm scripts其实比你想象中的要强大,主要依赖于预处理和后置处理钩子,比如下面例子:
{ "name": "npm-scripts-demo", "version": "1.0.0", "description": "npm scripts demo", "scripts": { "prebuild": "echo I run before the build script", "build": "cross-env NODE_ENV=production webpack", "postbuild": "echo I run after the build script" } }
正如上面例子一样,prebuild定义的脚本会比build任务先执行,而postbuild定义的脚本会比build任务后执行,因为相对于build来说,增加了一个前缀pre和post,所以当我执行npm run build的时候会自动地顺序执行prebuild -> build -> postbuild。
同时你可以将一个大的任务不断拆分成小的任务,比如:
{ "name": "npm-scripts-demo", "version": "1.0.0", "description": "npm scripts demo", "scripts": { "clean": "rimraf ./dist && mkdir dist", "prebuild": "npm run clean", "build": "cross-env NODE_ENV=production webpack" } }
在上面例子中将clean任务抽离出来了,当你执行npm run build的时候,会先自动执行npm run prebuild任务,那就相当于执行了npm run clean任务了,注意上面的&&表示先后顺序执行,区别于&表示同时执行。
npm scripts的一些缺点
不得不承认,用npm scripts来写自动化构建任务还是存在一些不足:不能在JSON文件里面写注释。有一些方法可以弥补这方面的不足:
写功能相对小而独立并且命名好的脚本名字
脚本跟文档分离(将文档写进READ.md)
直接分离脚本写进Makefile等独立的文件
推荐使用第一种,脚本名字本来就应该能够直接描述功能。
Task automation with npm run – James Holliday
Advanced front-end automation with npm scripts – Kate Hudson
How to use npm as a build tool – Kieth Girkel
Introduction to npm as a Build Tool – Marcus Hammarberg
Gulp is awesome, but do we really need it? – Gonto
NPM Scripts for Build Tooling – Andrew Burgess
想阅读更多技术文章,请访问听云技术博客,访问听云官方网站感受更多应用性能优化魔力。