webpack 做爲目前主流的構建工具,其較快的版本迭代和複雜的配置方式,使得每次開發前不得不規劃至關部分時間來調試。這裏將記錄整個環境的搭建過程,爲新手提供基礎思路。vue
就像我在開發vue-sitemap
時同樣,構建工具每每須要達到下面幾個需求:node
以上三個做爲開發一個組件(package
)是基礎中基礎的需求,固然還有更多細節內容須要添加,因爲篇幅過長另加文章再說吧。(歡迎各位讀者評論留下你認爲須要的功能( • ̀ω•́ )✧)webpack
接下來咱們先從最基礎的開始,須要安裝 Node.js(10.x) 做爲全部代碼的運行環境, webpack 也是同樣。git
因爲我須要把項目發佈至 npm 的,使用命令初始化項目描述文件 package.json
github
npm init
複製代碼
初次化細節各位讀者找其餘文章補全吧,這裏不細說web
接下來看看目錄結構npm
│ 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 環境因而在這加上。json
yarn 是一款快速、可靠、安全的依賴管理工具。若是你以爲 npm 安裝時候較慢的話,不妨試試。promise
等依賴下載解決完畢以後,,在package.json
設置構建命令方便以後使用。安全
//# package.json
{
//...
"scripts": {
"build": "cross-env NODE_ENV=production webpack --propress --hide-modules",
}
}
複製代碼
這裏咱們能夠嘗試運行一下命令npm run build
嘗試可否構建成功,成功的狀況下在dist
目錄下會生成main.js
的文件。
建立 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,安裝依賴後就能嘗試斷點調試了。
值得一提的是,上面參考例子原文說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協同編輯!