翻译原文:http://www.cnblogs.com/zldream1106/p/5204599.htmlphp
英文原文:https://css-tricks.com/why-npm-scripts/css
如下是访客Damon Bauer发布的一篇文章。近来直接使用node package提供的命令行界面的情绪持续高涨,反之,人们对经过运行任务从而屏蔽抽象功能的热情逐渐降温。在必定程度是,你不管如何都要使用npm,而同时npm提供了脚本功能,为何不用呢?可是咱们使用npm的脚本功能的缘由有不少。Damon会帮咱们理解这样作的缘由,并确切的告诉咱们如何经过这种方式来完成前端构建过程当中的大部分重要任务。html
我已经在项目中使用npm scripts 有大概半年的时间。在这以前,我使用Gulp,再以前是 Grunt。 Gulp和Grunt很好用,他们高效的自动完成了不少我以前须要手动完成的工做,帮助我更快的工做。可是我却开始以为我在这些工具上花费的精力要比花在我本身代码上的精力多得多。前端
Grunt, Gulp, Broccoli, Brunch和相似的工具都须要将本身的任务配置的适合他们的范型和结构,这些工具每个都须要学习他们不一样的语法、奇怪的用法和特有的方法。这增长了编码复杂度、构建复杂度,使得你关注修复工具问题更甚于写代码。node
因为这些构建工具依赖于包装了核心命令行工具的插件,并基于这个核心工具作了进一步的抽象,这使得出错的状况变得更加复杂。git
若是你对当前的构建系统很满意,而且它可以很好的完成你的需求的话,就请继续使用吧!不要由于npm scripts愈来愈流行就盲目的使用它,应该把精力集中在写代码而不是学习更多的工具。若是你开始以为本身正在和使用的工具战斗,那么这个时候我建议你考虑使用一下npm scripts。github
若是你如今作好决定想要调研或使用npm scripts,那么请继续阅读本文!本文将会提供大量的案例任务,同时基于这些任务我也建立了npm-build-boilerplate 以方便你学习。那么下面让咱们开始吧!shell
咱们会花费大量的时间在`package.json`文件上。这个文件描述了咱们须要的全部的依赖和脚本。如下是个人boilerplate项目中的一部份内容:npm
1 { 2 "name": "npm-build-boilerplate", 3 "version": "1.0.0", 4 "scripts": { 5 ... 6 }, 7 "devDependencies": { 8 ... 9 } 10 }
接下来咱们将逐步建立`package.json`文件。咱们的脚本会写入scripts对象中,全部咱们要使用的工具都会被安装而且写入devDependencies对象中。在开始以前,如下是本文中的项目结构:json
我是SCSS的重度用户,平时工做都依赖SCSS。为了将SCSS编译成CSS,我使用了node-sass。首先,咱们须要安装node-sass,在命令行下运行如下代码:
npm install --save-dev node-sass
这个命令会在当前目录下安装node-sass,并添加到`package.json`的devDependencies对象中。当其余人使用你的项目时会很是方便,由于他们已经有了运行项目所需的全部内容。只要安装过一次,使用时在命令行运行如下代码便可:
node-sass --output-style compressed -o dist/css src/scss
让咱们看一下这个命令作了什么:从后向前看,查找`src/scss`目录的SCSS文件,输出(-o 标识)编译的CSS到`dist/css`目录,压缩输出文件(使用 )。--output-style 标识,设置选项值为"compressed"
如今咱们知道了在命令行中如何工做,那么让咱们把它放到npm scirpt中。在`package.json`的scripts对象中添加以下内容:
"scripts": { "scss": "node-sass --output-style compressed -o dist/css src/scss" }
如今回到命令行并运行:
npm run scss
能够看到这样运行的输出结果和直接在命令行使用node-sass命令获得的结果一致。
只要把你想要运行的任务名从scss替换成你想要的名字便可。
As you will see, many of the command line tools we'll use have numerous options you can use to configure it exactly you see fit. For instance, here's the list of (node-sass options). Here's a different setup show how to pass multiple options:
你将看到,咱们使用的不少命令行工具都有不少的配置项,你可使用配置项来精确完成你想要作的工做。好比,这是node-sass的选项列表,如下展现了传多个配置项的配置方法:
"scripts": { "scss": "node-sass --output-style nested --indent-type tab --indent-width 4 -o dist/css src/scss" }
咱们已经可以把SCSS编译成CSS,如今咱们但愿经过Autoprefixer和PostCSS自动给CSS代码添加厂商前缀,咱们能够经过空格分隔的方式从而同时安装多个模块:
npm install --save-dev postcss-cli autoprefixer
由于PostCSS默认不作任何事情,因此咱们安装了两个模块。PostCSS依赖其余的插件来处理你提供的CSS,好比Autoprefixer。
安装并保存必要工具到devDependencies后,在你的scripts对象中添加一个新任务:
"scripts": { ... "autoprefixer": "postcss -u autoprefixer -r dist/css/*" }
这个任务的意思是:嗨postcss,使用(-u标识符)Autoprefixer替换(-r标识符)`dist/css`目录下的全部`.css`文件,给他们添加厂商前缀代码。就是这样简单!想要修改默认浏览器前缀?只要给脚本添加以下代码便可:
"autoprefixer": "postcss -u autoprefixer --autoprefixer.browsers '> 5%, ie 9' -r dist/css/*"
再次申明,配置你本身的构建代码有不少选项可使用:postcss-cli 和 autoprefixer。
对于写代码来讲,保持标准格式和样式是很是重要的,它可以确保错误最小化并提升开发效率。"代码检查"帮助咱们自动化的完成了这个工做,因此咱们经过使用 eslint 来进行代码检查。
再次如上文所述,安装eslint的包,此次让咱们使用快捷方式:
npm i -D eslint
这和以下代码是同样的效果:
npm install --save-dev eslint
安装完成后,咱们给eslint配置一些运行代码的基本规则。使用以下代码开始一个向导:、
eslint --init // 译者注:这里直接使用会抛错eslint找不到,由于这种使用方法必须安装在全局,即经过 npm install i -g eslint方式安装
我建议选择"回答代码风格问题"并回答提问的相关问题。这个过程当中eslint会在你的项目根目录下生成一个新文件,并检测你的相关代码。
如今,让咱们把代码风格检测任务添加到`package.json`的scripts对象中:
"scripts": { ... "lint": "eslint src/js" }
咱们的任务仅有13字符!它会查找`src/js`目录下的全部JavaScript文件,并根据刚才生成的规则进行代码检测。固然,若是感兴趣的话你能够详细配置各类规则:get crazy with the options
让咱们继续,下面咱们须要使用uglify-js来混淆压缩JavaScript文件,首先须要安装uglify-js:
npm i -D uglify-js
而后咱们能够在`package.json`里建立压缩混合任务:
"scripts": { ... "uglify": "mkdir -p dist/js && uglifyjs src/js/*.js -m -o dist/js/app.js" }
npm scripts的任务的本质是:能够重复执行的、命令行任务的快捷方式(别名),这也是npm scripts的优势之一。这就意味着你能够直接在脚本里使用标准命令行代码!这个任务使用了两个标准命令行特性:mkdir 和 &&。
这个任务的第一部分“ mkdir -p dist/js
”:若是不存在目录(-p标识)就建立一个目录结构(mkdir),建立成功后执行uglifyjs命令。&&帮助你链接多个命令,若是前一个命令成功执行的话,就分别顺序执行剩余的命令。
这个任务的第二部分告诉uglifyjs针对`src/js/`目录下的全部JS文件(`*.js`),使用"mangle"命令(-m 标识),输出结果到`dist/js/app.js`文件中。这里是uglifyjs工具的所有配置选项 list of options。
让咱们来更新一下uglify任务,建立一个`dist/js/app.js`的压缩版本,连接另一个uglifyjs的命令并传参给"compress"(-c标识)。
"scripts": { ... "uglify": "mkdir -p dist/js && uglifyjs src/js/*.js -m -o dist/js/app.js && uglifyjs src/js/*.js -m -c -o dist/js/app.min.js" }
下面咱们将进行图片压缩的工做。根据httparchive.org的数据统计,网络上前1000名的网站平均页面大小为1.9M,其中图片占了1.1M(with images accounting for 1.1mb of that total)。因此提升网页加载速度的其中一个好办法就是减少图片大小。
安装 imagemin-cli:
npm i -D imagemin-cli
Imagemin很是棒,它能够压缩大多数图片类型,包括GIF、JPG、PNG和SVG。 使用以下代码能够将一整个文件夹的图片所有压缩:
"scripts": { ... "imagemin": "imagemin src/images dist/images -p", }
这个任务告诉imagemin找到并压缩`src/images`中的全部图片并输出到`dist/images`中。-p标志在容许的状况下将图片处理成渐进图片。更多配置可查看文档 all available options
关于SVG的讨论近年来逐渐火热,SVG有众多优势:在全部的设备上保持松散结构、可经过CSS编辑、对读屏软件友好。然而,SVG编辑软件常常会产生大量的冗余代码。幸运的是,svgo能够帮助你自动删除这些冗余信息(咱们立刻就会安装svgo)。
接下来咱们来安装svg-sprite-generator,用于自动处理并整合多个SVG文件为一个SVG文件(更多处理方案:more on that technique here)。
npm i -D svgo svg-sprite-generator
你如今应该已经熟悉了这个过程——添加一个任务在你的`package.json`scripts对象中:
"scripts": { ... "icons": "svgo -f src/images/icons && mkdir -p dist/images && svg-sprite-generate -d src/images/icons -o dist/images/icons.svg" }
注意icons任务经过两个&&引导符作了三件事情: 1.使用svgo传参一个SVG目录(-f标识),这个操做压缩了目录内的所有SVG文件;2.若是不存在'dist/images'目录则建立该目录(使用mkdir -p命令);3.使用svg-sprite-generator,传参一个SVG目录(-d标识)以及输出处理后的SVG文件的目录路径名(-o标识)。
最后一个插件是BrowserSync,它能够作以下事情:启动一个本地服务,向链接的浏览器自动注入更新的文件,并同步浏览器的点击和滚动。安装并添加任务的代码以下:
npm i -D browser-sync "scripts": { ... "serve": "browser-sync start --server --files 'dist/css/*.css, dist/js/*.js'" }
BrowserSync任务默认使用当前根目录下的路径启动一个服务器(--server标识),--files标识告诉BrowserSync去监测`dist`目录的CSS或JS文件,一旦有任何变化,则自动向页面注入变化的文件。
你能够同时打开多个浏览器(甚至在不一样的设备上),他们都会实时更新文件变化的!
使用以上任务咱们能够作到以下功能:
这还不是所有内容!
Let's add a task that combines the two CSS related tasks (preprocessing Sass and running Autoprefixer), so we don't have to run each one separately:
咱们会添加一个新的任务,用于合并两个CSS相关的任务(处理SASS和执行加前缀的Autoprefixer),有了这个任务咱们就不用分别执行两个相关任务了:
"scripts": { ... "build:css": "npm run scss && npm run autoprefixer" }
当你运行npm run build:css时,这个任务会告诉命令行去执行npm run scss,当这个任务成功完成后,会接着(&&)执行
npm run autoprefixer。
就像这个build:css任务同样,咱们能够把JavaScript任务也连接到一块儿以方便执行:
"scripts": { ... "build:js": "npm run lint && npm run uglify" }
如今,咱们能够经过npm run build:js一步调用,来进行代码检测、混淆压缩JavaScript代码了!
对于图片任务、其余剩余构建任务,咱们能够用相同的方法把他们变成一个任务:
"scripts": { ... "build:images": "npm run imagemin && npm run icons", "build:all": "npm run build:css && npm run build:js && npm run build:images", }
至此,咱们的任务不断的须要对文件作一些变动,咱们不断的须要切回命令行去运行相应的任务。针对这个问题,咱们能够添加一个任务来监听文件变动,让文件在变动的时候自动执行这些任务。这里我推荐使用onchange插件,安装方法以下:
npm i -D onchange
让咱们来给CSS和JavaScript设置监控任务:
"scripts": { ... "watch:css": "onchange 'src/scss/*.scss' -- npm run build:css", "watch:js": "onchange 'src/js/*.js' -- npm run build:js", }
这些任务能够分解以下:onchange须要你传参想要监控的文件路径(字符串),这里咱们传的是SCSS和JS源文件,咱们想要运行的命令跟在--以后,这个命令当路径内的文件发生增删改的时候就会被当即执行。
再添加一个包,parallelshell:
npm i -D parallelshell
再次给scriopts对象添加一个新任务:
"scripts": { ... "watch:all": "parallelshell 'npm run serve' 'npm run watch:css' 'npm run watch:js'" }
parallelshell支持多个参数字符串,它会给npm run传多个任务用于执行。
为何时候parallelshell去合并多个任务,而不是像以前的任务同样使用&&呢?最开始我也尝试这么作了,可是问题是:&&连接多个命令到一块,须要等待每个命令成功完成后才会执行下一个任务。然而当咱们运行watch命令时,这些命令一直都不会结束!这样咱们就会卡在一个无限循环里。
所以,使用parallelshell使得咱们能够同时执行多个watch命令。(译者注:后来在评论里有人推荐使用npm-run-all插件来代替parallelshell,它支持这种用法能够一次性检测所有watch任务更加方便:"watch": "npm-run-all --parallel serve watch:*")
这个任务使用了BrowserSync的npm run serve任务启动了一个服务,而后对CSS和JavaScript文件执行了监控命令,一旦CSS或JavaScript文件有变动,监控任务就会执行相应的构建(build)任务。因为BrowserSync被设置成监控`dist`目录下的变动,因此它会自动的向相关联的URL内注入新的文件,真是太棒了!
npm有大量能够实用的插件(ots of baked in tasks ),让咱们再添加一个新的任务来看看这些插件对构建脚本的影响:
"scripts": { ... "postinstall": "npm run watch:all" }
当你在命令行中执行npm install的时候postinstall会当即执行,当团队合做时这个功能很是有用。当别人复制了你的项目并运行了npm install的时候,咱们的watch:all任务就会立刻执行,别人立刻就会准备好一切开发环境:启动一个服务、打开一个浏览器窗口、监控文件变动。
太棒了!我但愿你可以经过本文学习了一些使用npm scripts构建过程和经常使用命令行的方法。
万一你忘记了什么知识点,我用以上全部提到的任务建立了一个npm-build-boilerplate 项目以方便你学习。若是有任何问题或者评论,请推特我( tweet at me)或者在下方留言,我会尽我所能的帮助您!
---- 翻译完 ----