webpack 做爲目前主流的構建工具,其較快的版本迭代和複雜的配置方式,使得每次開發前不得不規劃至關部分時間來調試。這裏將記錄整個環境的搭建過程,爲新手提供基礎思路。vue
就像我在開發vue-sitemap
時同樣,構建工具每每須要達到下面幾個需求:node
以上三個做爲開發一個組件(package
)是基礎中基礎的需求,固然還有更多細節內容須要添加,因爲篇幅過長另加文章再說吧。(歡迎各位讀者評論留下你認爲須要的功能( • ̀ω•́ )✧)webpack
接下來咱們先從最基礎的開始,須要安裝 Node.js(10.x) 做爲全部代碼的運行環境, webpack 也是同樣。git
因爲我須要把項目發佈至 npm 的,使用命令初始化項目描述文件 package.json
github
npm init
初次化細節各位讀者找其餘文章補全吧,這裏不細說
接下來看看目錄結構web
│ package.json //項目描述文件 │ README.md //GitHub建立倉庫時默認建立 ├─src //源代碼目錄 │ index.js //入口文件 ├─tests //測試代碼目錄 │ ├─dist //生產文件的目錄 │ └─docs //文檔目錄
npm install -D webpack webpack-cli cross-env //or //yarn add webpack webpack-cli cross-env -D
這裏使用的 webpack v4,後續設置也是基於4來設置,cross-env
是幫助在 win 下能正常使用環境變量的包,我開發在 win 環境因而在這加上。yarn 是一款快速、可靠、安全的依賴管理工具。若是你以爲 npm 安裝時候較慢的話,不妨試試。npm
等依賴下載解決完畢以後,,在package.json
設置構建命令方便以後使用。json
//# package.json { //... "scripts": { "build": "cross-env NODE_ENV=production webpack --propress --hide-modules", } }
這裏咱們能夠嘗試運行一下命令npm run build
嘗試可否構建成功,成功的狀況下在dist
目錄下會生成main.js
的文件。promise
建立 webpack.config.js
文件來配置 webpack 。爲知足咱們的第一個須要生成三種模式的代碼:安全
//# webpack.config.js const package = require('./package.json') const path = require('path') const config = { entry: "./src/index.js", //入口文件 output: { //輸出設置 path: path.resolve(__dirname, "./dist"), filename: `${package.name}.js` }, resolve: { alias: { "@": path.resolve(__dirname, "./src") } } } if (process.env.NODE_ENV === "umd") { config.optimization = { minimize: false }; config.output.library = package.name; config.output.libraryTarget = "umd2"; config.output.filename = `${package.name}.js`; } if (process.env.NODE_ENV === "umd:min") { config.output.library = package.name; config.output.libraryTarget = 'umd2'; config.output.filename = `${package.name}.min.js`; } if (process.env.NODE_ENV === "es") { config.output.library = package.name; config.output.libraryTarget = "amd"; config.output.filename = `${package.name}.es.js`; } if (process.env.NODE_ENV === "commonjs") { config.output.library = package.name; config.output.libraryTarget = "commonjs2"; config.output.filename = `${package.name}.common.js`; } module.exports = config
爲 package.json
添加新的運行命令
//# package.json { "version": "0.1.0", "name": "vscode-mocha-webpack-example", "description": "用於管理導航、麪包屑及路由等基於vue的功能整合", "main": "./src/index.js", "scripts": { "build": "npm run build:commonjs && npm run build:es && npm run build:umd && npm run build:umd:min", "build:umd": "cross-env NODE_ENV=umd webpack --mode=production --progress --hide-modules", "build:umd:min": "cross-env NODE_ENV=umd:min webpack --mode=production --progress --hide-modules", "build:es": "cross-env NODE_ENV=es webpack --mode=production --progress --hide-modules", "build:commonjs": "cross-env NODE_ENV=commonjs webpack --mode=production --progress --hide-modules" } ... }
運行npm run build
就會 CommonJS/UMD/ES Modules 三種模式生成對應的文件。
大概是這樣子:
├─dist │ vscode-mocha-webpack-example.common.js │ vscode-mocha-webpack-example.es.js │ vscode-mocha-webpack-example.min.js │ vscode-mocha-webpack-example.js
爲了使你的構建文件成爲最終發佈包的一部分,你必須聲明它們。將如下內容添加到package.json:
"main": "dist/vscode-mocha-webpack-example.common.js", "module": "dist/vscode-mocha-webpack-example.es.js", "jsnext:main": "dist/vscode-mocha-webpack-example.es.js", "files": [ "dist", "src" ],
files
部分告訴npm在發佈時打包這些文件夾(不然,它們將被忽略,由於它們列在.gitignore
文件中)main
定義CommonJS構建的終端jsnext:main
和module
定義了ES2015構建的終端(咱們定義了兩個終端,由於jsnext:main
是最先使用的規範,而module
則更符合標準規範)。經過 babel
使得咱們使用最新的語法,而沒必要擔憂運行環境不支持的問題。在webpack
的下咱們須要用到babel-loader
來導入babel
支持,關於最新的兼容設置還需使用上babel-preset-env
:
npm install -D babel babel-cli babel-preset-env //or //yarn add babel babel-cli babel-preset-env -D
接着在.babelrc
文件裏設置babel兼容的規則:
{ "presets": [ [ "env", { "useBuiltIns": false, "modules": false } ] ] }
當咱們使用最新語法編寫 JavaScript 時,webpack 會匹配將全部 JS 文件給 babel
的處理。
const package = require('./package.json') const path = require('path') const config = { entry: "./src/index.js", output: { path: path.resolve(__dirname, "./dist"), filename: `${package.name}.js` }, resolve: { alias: { "@": path.resolve(__dirname, "./src") } }, module: { rules: [ { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ } ] } } ... module.exports = config
當運行構建時webpack
便會加載babel
及其相關的設置將代碼轉換並生成,到這步構建相關的設置基本完成。
相信對自動化測試有所瞭解的讀者應該對mocha
並不陌生,不瞭解的能夠先去補補相關知識再往下看。簡單的測試較多使用mocha
來進行處理,還有斷言庫chai
和提供promise支持的chai-as-promised
等等,下面先把這些依賴安裝上:
npm install -D mocha mocha-webpack chai chai-as-promised //or //yarn add mocha mocha-webpack chai chai-as-promised -D
測試代碼想使用es新特性時可使用
mocha-webpack
這個插件。
而後在package.json
添加上測試命令:
{ //... "scripts": { "build": "npm run build:commonjs && npm run build:es && npm run build:umd && npm run build:umd:min", "build:umd": "cross-env NODE_ENV=umd webpack --mode=production --progress --hide-modules", "build:umd:min": "cross-env NODE_ENV=umd:min webpack --mode=production --progress --hide-modules", "build:es": "cross-env NODE_ENV=es webpack --mode=production --progress --hide-modules", "test": "cross-env NODE_ENV=test mocha-webpack tests/**/*.spec.js" } //... }
.babelrc
也須要設置一下:
{ //... "env": { "test": { "presets": [ [ "env", { "modules": false, "targets": { "node": "current" } } ] ] } } }
爲了能測試添加tests/unit/example.spec.js
和src/index.js
兩個文件,代碼以下:
├─src │ index.js └─tests └─unit example.spec.js
//# src/index.js export function getRole(user){ switch(user){ case "Packy": return "admin" case "Joan": return "reader" } } //# tests/unit/example.spec.js import { assert } from "chai"; import { getRole } from "@/index"; describe('Testing', ()=>{ it('Packy is admin', () => { assert.equal(getRole('Packy'), 'admin') }) it("Joan is reader", () => { assert.equal(getRole("Joan"), "reader") }); })
如今運行測試命令就能得出測試結果了:
npm run test
大概輸出是這個樣子:
WEBPACK Compiling... [======================= ] 91% (additional chunk assets processing) WEBPACK Compiled successfully in 5893ms MOCHA Testing... Testing √ Packy is admin √ Joan is reader 2 passing (39ms) MOCHA Tests completed successfully
有了測試還得知道測試是否都覆蓋了全部代碼(據說基本要到80%,有些團隊可能要求更高90~95%),那如何得知?
nyc
這個包就能幫助到我去檢驗測試覆蓋率,首先先安裝依賴:
npm install -D nyc babel-plugin-istanbul
再設置檢查範圍和添加命令:
//# package.json { ... "scripts": { "build": "npm run build:commonjs && npm run build:es && npm run build:umd && npm run build:umd:min", "build:umd": "cross-env NODE_ENV=umd webpack --mode=production --progress --hide-modules", "build:umd:min": "cross-env NODE_ENV=umd:min webpack --mode=production --progress --hide-modules", "build:es": "cross-env NODE_ENV=es webpack --mode=production --progress --hide-modules", "build:commonjs": "cross-env NODE_ENV=commonjs webpack --mode=production --progress --hide-modules", "test": "cross-env NODE_ENV=test nyc mocha-webpack tests/**/*.spec.js" }, ... "nyc": { "include": [ "src/**" ], "instrument": false, "sourceMap": false } ... }
安裝依賴中也看到babel
也須要添加相關的設置:
//# .babelrc { ... "env": { "test": { "presets": [ [ "env", { "modules": false, "targets": { "node": "current" } } ] ], "plugins": [ "istanbul" ] } } }
運行npm run test
將會獲得如下內容:
WEBPACK Compiling... [======================= ] 91% (additional chunk assets processing) WEBPACK Compiled successfully in 5893ms MOCHA Testing... Testing √ Packy is admin √ Joan is reader 2 passing (39ms) MOCHA Tests completed successfully ----------|----------|----------|----------|----------|-------------------| File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s | ----------|----------|----------|----------|----------|-------------------| All files | 100 | 100 | 100 | 100 | | index.js | 100 | 100 | 100 | 100 | | ----------|----------|----------|----------|----------|-------------------|
簡單說一下這四欄東西表明什麼意思:
Statement coverage
聲明覆蓋率,程序中的每一個語句都已執行嗎?Branch coverage
分支覆蓋率,是否已執行每一個控制結構的每一個分支(也稱爲DD路徑)(例如if和case語句)?例如,給定if語句,是否已執行true和false分支?Function coverage
方法覆蓋率,是否已調用程序中的每一個函數(或子例程)?Line coverage
行代碼覆蓋,是否已執行源文件中的每一個可執行的行?不在覆蓋範圍內的代碼的行數會在Uncovered Line
這欄顯示。
在測試中想使用async/await語法,需新增setup.js文件並在入口處添加babel-polyfill
:
require("babel-polyfill");
並在.babelrc
修改useBuiltIns
爲entry
:
{ ... "env": { "test": { "presets": [ [ "env", { "useBuiltIns": "entry", "modules": false, "targets": { "node": "current" } } ] ], "plugins": [ "istanbul" ] } } }
接下來在src/index.js
和tests/example.spec.js
兩個文件添加新的代碼:
//# src/index.js export function getUsers(){ return new Promise((resolve, reject)=>{ setTimeout(()=>{ console.log('123') resolve(['Packy', 'Joan']) }, 1000) }) } //# tests/unit/example.spec.js describe('GetUsers', ()=>{ it('get result is Array', async ()=>{ const users = await getUsers(); assert.isArray(users, "[message]"); }) })
運行測試就能看到效果!
想在VS Code斷點調試代碼須要額外增長一些設置,添加如下代碼至 webpack.config.js
。
//# webpack.config.js //... if (process.env.NODE_ENV === "test") { config.devtool = "eval-source-map"; config.output = Object.assign(config.output, { devtoolModuleFilenameTemplate: "[absolute-resource-path]", devtoolFallbackModuleFilenameTemplate: '[absolute-resource-path]?[hash]' }); } module.exports = config;
打開 VS Code 調試面板在下拉選項中選擇添加配置(或者直接建立並打開.vscode/launch.json
文件):
// 使用 IntelliSense 瞭解相關屬性。 // 懸停以查看現有屬性的描述。 // 欲瞭解更多信息,請訪問: https://go.microsoft.com/fwlink/?linkid=830387 { "version": "0.2.0", "configurations": [ { "type": "node", "request": "launch", "name": "Mocha-webpack Tests", "program": "${workspaceFolder}/node_modules/mocha-webpack/bin/mocha-webpack", "args": [ "--full-trace", "--timeout", "999999", "--colors", "tests/**/*.js" ], "sourceMaps": true, "env": { "NODE_ENV": "test" }, "internalConsoleOptions": "openOnSessionStart" }] }
在src
目錄下的源代碼或是tests
目錄下的測試代碼都能得到斷點效果,想立刻嘗試能夠下載本文例子vscode-mocha-webpack-example,安裝依賴後就能嘗試斷點調試了。
設置參考源自 vscode-ts-webpack-node-debug-example
值得一提的是,上面參考例子原文說devtool
使用eval
相關的設置並不能斷點,可是在使用mocha-webpack
調試時上面例子並不能實現斷點。在我和公司小夥伴多番尋找vscode
和mocha-webpack
的issue後,通過各類嘗試下發現設置成eval-source-map
便能實現最佳斷點效果(eval也能實現可是因爲斷點sourcemap指向的源是生成後的文件致使在斷點時多少會產生偏移)。
吐槽:在使用nvm
切換nodejs
環境時發現npm
下載不了,打開github的下載連接直接404了,驚悚地發現npm
整個搬走 (`Д´*)9 ┴┴,爲解決這個問題請下載最新版本v1.1.7
的nvm
。
最後:
個人動力來自你的指頭,請用你的指頭使勁給我個贊吧!d(´ω` )
以爲本文有幫助的話不要忘記點一下收藏φ(>ω<*) 哦!
同時歡迎各路新手、大神在本文下方吐槽留言,謝謝參與討論的各位仁兄!( • ̀ω•́ )✧
下面是本文完整例子,記得star一下!
同時很是感謝 Mather協同編輯!