【轉】Why npm Scripts?

翻譯原文: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

如下三個問題我已經遇到過屢次:

  • 若是當前的命令行工具中沒有你想用的插件,那麼你將一籌莫展(除非你本身寫一個)。
  • 你要用的插件包裝了舊版的工具,因此使用的插件和當前核心工具的特性、文檔不可以徹底匹配一致。
  • 錯誤提示不夠友好。若是插件掛了的話,極可能無法一路追蹤這個錯誤直到核心工具,這時我很沮喪的發現本身並不清楚如何debug這個錯誤。

可是,請記住...

若是你對當前的構建系統很滿意,而且它可以很好的完成你的需求的話,就請繼續使用吧!不要由於npm scripts愈來愈流行就盲目的使用它,應該把精力集中在寫代碼而不是學習更多的工具。若是你開始以爲本身正在和使用的工具戰鬥,那麼這個時候我建議你考慮使用一下npm scripts。github

若是你如今作好決定想要調研或使用npm scripts,那麼請繼續閱讀本文!本文將會提供大量的案例任務,同時基於這些任務我也建立了npm-build-boilerplate 以方便你學習。那麼下面讓咱們開始吧!shell

寫npm scripts

咱們會花費大量的時間在`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爲css

我是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命令獲得的結果一致。

本文剩餘部分建立的任何一個npm script,均可以像上例同樣使用命令行運行。

只要把你想要運行的任務名從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"
}

使用PostCSS自動給CSS加前綴

咱們已經可以把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-cliautoprefixer
 

JavaScript 代碼檢查

對於寫代碼來講,保持標準格式和樣式是很是重要的,它可以確保錯誤最小化並提升開發效率。"代碼檢查"幫助咱們自動化的完成了這個工做,因此咱們經過使用 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

混淆壓縮JavaScript文件

讓咱們繼續,下面咱們須要使用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精靈(Sprites)

關於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提供服務、自動監測並注入變動

最後一個插件是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文件,一旦有任何變化,則自動向頁面注入變化的文件。

你能夠同時打開多個瀏覽器(甚至在不一樣的設備上),他們都會實時更新文件變化的!

分組任務

使用以上任務咱們能夠作到以下功能:

  • 編譯SCSS到CSS並自動添加廠商前綴
  • 對Javascript進行代碼檢查及混淆壓縮
  • 壓縮圖片
  • 整合整個文件夾內的SVG文件爲一個SVG文件
  • 啓動一個本地服務並向鏈接至該服務的瀏覽器自動注入更新。

這還不是所有內容!

合併CSS任務

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任務也連接到一塊兒以方便執行:

合併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源文件,咱們想要運行的命令跟在--以後,這個命令當路徑內的文件發生增刪改的時候就會被當即執行。

讓咱們再添加一個監控命令來完成咱們的npm scripts構建過程。

再添加一個包,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)或者在下方留言,我會盡我所能的幫助您!

 

---- 翻譯完 ----

相關文章
相關標籤/搜索