NodeJS之npm腳本

1. package.json

{
  "name": "npm-build-boilerplate",
  "version": "1.0.0",
  "scripts": {
    ...
  },
  "devDependencies": {
    ...
  }
}

2. 項(xiàng)目結(jié)構(gòu)

項(xiàng)目結(jié)構(gòu)

3. 插件整理

3.1 編譯scss為css

npm install --save-dev node-sass

"scripts": { 
      "scss": "node-sass --output-style compressed -o dist/css src/scss"
}

從后向前看,查找src/scss目錄的SCSS文件,輸出(-o 標(biāo)識(shí))編譯的CSS到dist/css目錄,壓縮輸出文件(使用 --output-style 標(biāo)識(shí),設(shè)置選項(xiàng)值為"compressed")。
node-sass

3.2 PostCSS自動(dòng)給CSS加前綴

npm install --save-dev postcss-cli autoprefixer

"scripts": { 
      ... 
      "autoprefixer": "postcss -u autoprefixer -r dist/css/*"
}

嗨postcss,使用(-u標(biāo)識(shí)符)Autoprefixer替換(-r標(biāo)識(shí)符)dist/css目錄下的所有.css文件,給他們添加廠商前綴代碼。
配置你自己的構(gòu)建代碼有很多選項(xiàng)可以使用:postcss-cliautoprefixer

3.3 JavaScript 代碼檢查

npm i -D eslint
npm install --save-dev eslint 和上面的代碼有相關(guān)的效果
eslint --init // 譯者注:這里直接使用會(huì)拋錯(cuò)eslint找不到,因?yàn)檫@種使用方法必須安裝在全局,即通過 npm install i -g eslint方式安裝

"scripts": { 
      ... 
      "lint": "eslint src/js"
}

查找src/js目錄下的所有JavaScript文件,并根據(jù)剛才生成的規(guī)則進(jìn)行代碼檢測(cè)。
eslinteslint doceslint config

3.4 混淆壓縮JavaScript文件

npm i -D uglify-js

"scripts": { 
      ... 
      "uglify": "mkdir -p dist/js && uglifyjs src/js/*.js -m -o dist/js/app.js"
}

這個(gè)任務(wù)使用了兩個(gè)標(biāo)準(zhǔn)命令行特性:mkdir 和 &&。

  • 這個(gè)任務(wù)的第一部分“ mkdir -p dist/js”:如果不存在目錄(-p標(biāo)識(shí))就創(chuàng)建一個(gè)目錄結(jié)構(gòu)(mkdir),創(chuàng)建成功后執(zhí)行uglifyjs命令。&&幫助你連接多個(gè)命令,如果前一個(gè)命令成功執(zhí)行的話,就分別順序執(zhí)行剩余的命令。
  • 這個(gè)任務(wù)的第二部分告訴uglifyjs針對(duì)src/js/目錄下的所有JS文件(*.js),使用"mangle"命令(-m 標(biāo)識(shí)),輸出結(jié)果到dist/js/app.js文件中。這里是uglifyjs工具的全部配置選項(xiàng) list of options。
    讓我們來更新一下uglify任務(wù),創(chuàng)建一個(gè)dist/js/app.js的壓縮版本,鏈接另外一個(gè)uglifyjs的命令并傳參給"compress"(-c標(biāo)識(shí))。
"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"
}

UglifyJS2

3.5 壓縮圖片

npm i -D imagemin-cli

"scripts": { 
      ... "
      imagemin": "imagemin src/images dist/images -p"
}

這個(gè)任務(wù)告訴imagemin找到并壓縮src/images中的所有圖片并輸出到dist/images中。-p標(biāo)志在允許的情況下將圖片處理成漸進(jìn)圖片。更多配置可查看文檔 all available options
imagemin-cli

3.6 SVG精靈(Sprites)

npm i -D svgo svg-sprite-generator

"scripts": { 
      ... 
      "icons": "svgo -f src/images/icons && mkdir -p dist/images && svg-sprite-generate -d src/images/icons -o dist/images/icons.svg"
}

注意icons任務(wù)通過兩個(gè)&&引導(dǎo)符做了三件事情:

  1. 使用svgo傳參一個(gè)SVG目錄(-f標(biāo)識(shí)),這個(gè)操作壓縮了目錄內(nèi)的全部SVG文件;
  2. 如果不存在'dist/images'目錄則創(chuàng)建該目錄(使用mkdir -p命令);
  3. 使用svg-sprite-generator,傳參一個(gè)SVG目錄(-d標(biāo)識(shí))以及輸出處理后的SVG文件的目錄路徑名(-o標(biāo)識(shí))。

安裝svg-sprite-generator,用于自動(dòng)處理并整合多個(gè)SVG文件為一個(gè)SVG文件(更多處理方案:more on that technique here)。

3.7 通過BrowserSync提供服務(wù)、自動(dòng)監(jiān)測(cè)并注入變更

npm i -D browser-sync

BrowserSync,它可以做如下事情:?jiǎn)?dòng)一個(gè)本地服務(wù),向連接的瀏覽器自動(dòng)注入更新的文件,并同步瀏覽器的點(diǎn)擊和滾動(dòng)。

"scripts": { 
      ... 
      "serve": "browser-sync start --server --files 'dist/css/*.css, dist/js/*.js'"
}

BrowserSync任務(wù)默認(rèn)使用當(dāng)前根目錄下的路徑啟動(dòng)一個(gè)服務(wù)器(--server標(biāo)識(shí)),--files標(biāo)識(shí)告訴BrowserSync去監(jiān)測(cè)dist目錄的CSS或JS文件,一旦有任何變化,則自動(dòng)向頁(yè)面注入變化的文件。

3.8 分組任務(wù)

使用以上任務(wù)我們可以做到如下功能:

  • 編譯SCSS到CSS并自動(dòng)添加廠商前綴
  • 對(duì)Javascript進(jìn)行代碼檢查及混淆壓縮
  • 壓縮圖片
  • 整合整個(gè)文件夾內(nèi)的SVG文件為一個(gè)SVG文件
  • 啟動(dòng)一個(gè)本地服務(wù)并向連接至該服務(wù)的瀏覽器自動(dòng)注入更新。

這還不是全部?jī)?nèi)容!

4. 合并任務(wù)

4.1 合并CSS任務(wù)

我們會(huì)添加一個(gè)新的任務(wù),用于合并兩個(gè)CSS相關(guān)的任務(wù)(處理SASS和執(zhí)行加前綴的Autoprefixer),有了這個(gè)任務(wù)我們就不用分別執(zhí)行兩個(gè)相關(guān)任務(wù)了:

"scripts": { 
      ... 
      "build:css": "npm run scss && npm run autoprefixer"
}

4.2 合并JavaScript任務(wù)

"scripts": { 
      ... 
      "build:js": "npm run lint && npm run uglify"
}

我們可以通過npm run build:js一步調(diào)用,來進(jìn)行代碼檢測(cè)、混淆壓縮JavaScript代碼了!

4.3 合并剩余任務(wù)

對(duì)于圖片任務(wù)、其他剩余構(gòu)建任務(wù),我們可以用相同的方法把他們變成一個(gè)任務(wù):

"scripts": { 
      ... 
      "build:images": "npm run imagemin && npm run icons", 
      "build:all": "npm run build:css && npm run build:js && npm run build:images"
}

4.4 變更監(jiān)控

我們的任務(wù)不斷的需要對(duì)文件做一些變更,我們不斷的需要切回命令行去運(yùn)行相應(yīng)的任務(wù)。針對(duì)這個(gè)問題,我們可以添加一個(gè)任務(wù)來監(jiān)聽文件變更,讓文件在變更的時(shí)候自動(dòng)執(zhí)行這些任務(wù)。這里我推薦使用onchange插件,安裝方法如下:

npm i -D onchange

"scripts": { 
      ... 
      "watch:css": "onchange 'src/scss/*.scss' -- npm run build:css", 
      "watch:js": "onchange 'src/js/*.js' -- npm run build:js"
}

onchange需要你傳參想要監(jiān)控的文件路徑(字符串),這里我們傳的是SCSS和JS源文件,我們想要運(yùn)行的命令跟在--之后,這個(gè)命令當(dāng)路徑內(nèi)的文件發(fā)生增刪改的時(shí)候就會(huì)被立即執(zhí)行。

4.5 讓我們?cè)偬砑右粋€(gè)監(jiān)控命令來完成我們的npm scripts構(gòu)建過程。

再添加一個(gè)包,parallelshell

npm i -D parallelshell

"scripts": { 
      ... 
      "watch:all": "parallelshell 'npm run serve' 'npm run watch:css' 'npm run watch:js'"
}

parallelshell支持多個(gè)參數(shù)字符串,它會(huì)給npm run傳多個(gè)任務(wù)用于執(zhí)行。

為什么時(shí)候parallelshell去合并多個(gè)任務(wù),而不是像之前的任務(wù)一樣使用&&呢?最開始我也嘗試這么做了,但是問題是:&&鏈接多個(gè)命令到一塊,需要等待每一個(gè)命令成功完成后才會(huì)執(zhí)行下一個(gè)任務(wù)。然而當(dāng)我們運(yùn)行watch命令時(shí),這些命令一直都不會(huì)結(jié)束!這樣我們就會(huì)卡在一個(gè)無限循環(huán)里。
因此,使用parallelshell使得我們可以同時(shí)執(zhí)行多個(gè)watch命令。(譯者注:后來在評(píng)論里有人推薦使用npm-run-all插件來代替parallelshell,它支持這種用法可以一次性檢測(cè)全部watch任務(wù)更加方便:"watch": "npm-run-all --parallel serve watch:*")
這個(gè)任務(wù)使用了BrowserSync的npm run serve任務(wù)啟動(dòng)了一個(gè)服務(wù),然后對(duì)CSS和JavaScript文件執(zhí)行了監(jiān)控命令,一旦CSS或JavaScript文件有變更,監(jiān)控任務(wù)就會(huì)執(zhí)行相應(yīng)的構(gòu)建(build)任務(wù)。由于BrowserSync被設(shè)置成監(jiān)控dist目錄下的變更,所以它會(huì)自動(dòng)的向相關(guān)聯(lián)的URL內(nèi)注入新的文件,真是太棒了!

4.6 其他實(shí)用任務(wù)

npm有大量可以實(shí)用的插件(ots of baked in tasks ),讓我們?cè)偬砑右粋€(gè)新的任務(wù)來看看這些插件對(duì)構(gòu)建腳本的影響:

"scripts": { 
      ... 
      "postinstall": "npm run watch:all"
}

當(dāng)你在命令行中執(zhí)行npm install的時(shí)候postinstall會(huì)立即執(zhí)行,當(dāng)團(tuán)隊(duì)合作時(shí)這個(gè)功能非常有用。當(dāng)別人復(fù)制了你的項(xiàng)目并運(yùn)行了npm install的時(shí)候,我們的watch:all任務(wù)就會(huì)馬上執(zhí)行,別人馬上就會(huì)準(zhǔn)備好一切開發(fā)環(huán)境:?jiǎn)?dòng)一個(gè)服務(wù)、打開一個(gè)瀏覽器窗口、監(jiān)控文件變更。

4.7 打包

萬(wàn)一你忘記了什么知識(shí)點(diǎn),我用以上所有提到的任務(wù)創(chuàng)建了一個(gè)npm-build-boilerplate 項(xiàng)目以方便你學(xué)習(xí)。

99. 相關(guān)文章

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容