webpack4.29.6搭建常用功能的環境
因專案需要,用webpack搭建一個常用功能的環境。
初步功能羅列如下:
自動配置多入口出口
less轉css
css字首自動補齊
css提取成單獨檔案
css壓縮
圖片壓縮
引入字型和svg js Babel 壓縮
css和js的分離/合併和過濾
1.建立並且進入資料夾
mkdir webpack4.29.6 && cd webpack4.29.6 複製程式碼
2.如下圖建立各個demo檔案和圖片

index.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>test</title> </head> <body> 隨便寫一些index2333 </body> </html> 複製程式碼
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>test</title> </head> <body> 隨便寫一些about2333 </body> </html> 複製程式碼
其他的檔案可以先空著,圖片先不匯入也沒關係。
3建立package.json(以下所有命令都是在webpack4.29.6資料夾下執行)
npm init -y 複製程式碼
4.安裝以下幾個依賴
(
webpack/webpack-cli這兩個需要注意,3.x以前版本是合併在一起的,4.x後拆分了 webpack-dev-server:起服務
html-webpack-plugin:動態生成html
webpack-merge:合併webpack配置檔案
)
npm install -D webpack webpack-cli webpack-dev-server html-webpack-plugin webpack-merge 複製程式碼
確保區域性依賴和全域性依賴版本都如下圖是最新的(看清楚了,webpack是4.29.6的,如果你因為網路問題裝成3.幾的,後面將全部報錯。這步很關鍵,不然你會有無窮盡的麻煩,如果實在不成功可以先把全域性node下的webpack相關檔案刪除,window在c盤/Program Files/nodejs/下)。

5.建立三個webpack配置文字(1.common2.dev3.prod)並且分別寫入
touch webpack.common.js webpack.dev.js webpack.prod.js 複製程式碼
webpack.common.js:
const path = require("path"); const HtmlWebpackPlugin = require("html-webpack-plugin"); module.exports = { entry: { index: "./src/js/index.js" }, output: { //[name] 輸出名稱等於輸入名稱[contenthash:8] 八位hash filename: "[name].[contenthash:8].js", //你應該知道的node path 知識: http://nodejs.cn/api/path.html path: path.resolve(__dirname, "dist") }, module: { rules: [ ] }, plugins: [ new HtmlWebpackPlugin({ filename: "index.html", template: "./src/index.html" }) ] }; 複製程式碼
webpack.dev.js:
const merge = require("webpack-merge"); const common = require("./webpack.common.js"); module.exports = merge(common, { mode: "development", //開啟除錯 devtool: "source-map", devServer: { //設定基本目錄結構 contentBase: "./dist", //伺服器的IP地址,可以使用IP也可以使用localhost host: "localhost", //服務端壓縮是否開啟 compress: true, //配置服務埠號 port: 8090 } }); 複製程式碼
webpack.prod.js:
const merge = require("webpack-merge"); const common = require("./webpack.common.js"); module.exports = merge(common, { mode: "production", }); 複製程式碼
6.修改下package.json中的script物件
"scripts": { "dev": "webpack-dev-server --config webpack.dev.js", "build": "rimraf dist && webpack --config webpack.prod.js" }, 複製程式碼
7.嘗試啟動服務或者打包
啟動服務:
npm run dev 複製程式碼
打包: (rimraf dist: 打包前刪除了rimraf資料夾再重新生成)
npm run build 複製程式碼
dist:

這樣便成功了第一步。
因為修改了配置檔案每步都要重啟服務比較麻煩,我們這裡引入nodemon。並且新增一條命令
npm install -D nodemon 複製程式碼
// 監聽webpack.common.js檔案,有變動的話就重新啟動 npm run dev
"startdev": "nodemon --watch webpack.common.js --execnpm run dev " 複製程式碼
package.json:

開始正式配置專案常見的功能
前面打包的檔案圖片可以看到只打出了index.html,這裡看看怎麼引入多個html
webpack.common.js: 在入口增加多一個about.js和外掛多生產一個例項即可:

但是手動新增有點搓,嘗試用node遍歷自動匯入:
在根目錄新建一個multi.page.js檔案:
multi.page.js:
// 多入口出口處理 const path = require("path"); const fs = require("fs"); const htmlWebpackPlugin = require("html-webpack-plugin"); const pagesPath = path.resolve("./src"); var pageList = []; function readPages() { fs.readdirSync(pagesPath).forEach(e => { var fullPath = pagesPath + "/" + e; if (e.includes("html")) { var baseName = e.slice(0, e.indexOf(".")); pageList.push({ entry: pagesPath + "\\js\\" + baseName + ".js", chunkName: baseName, template: pagesPath +'\\'+ e }); } }); return pageList; } // 入口 exports.getEntryPages = function() { return readPages().reduce((r, page) => { r[page.chunkName] = page.entry; return r; }, {}); }; //出口 exports.htmlPlugins = function() { var list = readPages().map(page => { var options = { filename: page.chunkName + ".html", template: page.template, chunks: [page.chunkName] }; return new htmlWebpackPlugin(options); }); return list; }; 複製程式碼
webpack.common.js:
const path = require("path"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const multiPage = require("./multi.page"); module.exports = { //entry: { //index: "./src/js/index.js", //about: "./src/js/about.js" //}, entry: multiPage.getEntryPages(), output: { //[name] 輸出名稱等於輸入名稱[contenthash:8] 八位hash filename: "[name].[contenthash:8].js", //你應該知道的node path 知識: http://nodejs.cn/api/path.html path: path.resolve(__dirname, "dist") }, module: { rules: [] }, plugins: [ // new HtmlWebpackPlugin({ //filename: "index.html", //template: "./src/index.html" // }), // new HtmlWebpackPlugin({ //filename: "about.html", //template: "./src/about.html" // }) ...multiPage.htmlPlugins() ] }; 複製程式碼
就是將手動引入匯出改善成nodejs自動遍歷
後面就是常見功能了,先暫時寫到webpack.common.js裡面方便除錯,最後按需切到webpack.dev.js或者webpack.prod.js
處理css(這裡我以less為例)安裝以下依賴
npm install -D css-loader style-loader less less-loader 複製程式碼
修改webpack.common.js:
module: { rules: [ { test: /\.less$/, use: ["style-loader", "css-loader", "less-loader"], include: path.resolve(__dirname, "./src") // 制定路徑提升效能 } ] }, 複製程式碼
修改index.js引入index.less,並且隨意寫點樣式
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>test</title> </head> <body> <div class="test"> 隨便寫點什麼 這裡不要自己引入css和js 全部交給webpack來處理 </div> </body> </html> 複製程式碼
index.js:
import index from "../css/index.less"; 複製程式碼
index.less
body { display: flex; background: #666; .test { color: #ff0; } } 複製程式碼
就會發現相關樣式在head style 裡了
再優化一步,將style提出來
安裝依賴mini-css-extract-plugin
npm install -D mini-css-extract-plugin 複製程式碼
webpack.common.js 引進依賴、修改規則和產出,檔案總體如下
webpack.common.js:
const path = require("path"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const multiPage = require("./multi.page"); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); //提取css檔案 module.exports = { //entry: { //index: "./src/js/index.js", //about: "./src/js/about.js" //}, entry: multiPage.getEntryPages(), output: { //[name] 輸出名稱等於輸入名稱[contenthash:8] 八位hash filename: "[name].[contenthash:8].js", //你應該知道的node path 知識: http://nodejs.cn/api/path.html path: path.resolve(__dirname, "dist") }, module: { rules: [ { test: /\.less$/, // use: ["style-loader", "css-loader", "less-loader"], use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"], include: path.resolve(__dirname, "./src") // 制定路徑提升效能 } ] }, plugins: [ // new HtmlWebpackPlugin({ //filename: "index.html", //template: "./src/index.html" // }), // new HtmlWebpackPlugin({ //filename: "about.html", //template: "./src/about.html" // }) ...multiPage.htmlPlugins(), new MiniCssExtractPlugin({ filename: "css/[name].[contenthash:8].css" }) ] }; 複製程式碼
繼續優化將css字首自動補齊
安裝依賴:
npm install -D postcss-loader autoprefixer 複製程式碼
修改package.json:
"browserslist": [ "> 1%", "last 2 versions", "not ie <= 8" ] 複製程式碼
修改webpack.common.js:
--- use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"], +++use: [ MiniCssExtractPlugin.loader, "css-loader", { loader: "postcss-loader", options: { plugins: () => [require("autoprefixer")()] } }, "less-loader" ], 複製程式碼
最後壓縮css檔案
安裝依賴:
npm install -D optimize-css-assets-webpack-plugin 複製程式碼
修改webpack.common.js:
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin') new OptimizeCssAssetsPlugin({ assetNameRegExp: /\.css$/g, cssProcessor: require('cssnano'), //用於優化\最小化CSS的CSS處理器,預設為cssnano cssProcessorOptions: { safe: true, discardComments: { removeAll: true } }, //傳遞給cssProcessor的選項,預設為{} canPrint: true//一個布林值,指示外掛是否可以將訊息列印到控制檯,預設為true }), 複製程式碼
檢視一下結果 原始檔:

打包後的:

另外補充一句,看到頭部這裡莫名其妙引入了一個這個style和相關樣式,一臉懵逼還未找到問題所在。

引入圖片以及對圖片進行壓縮
npm install -D css-loader file-loader html-withimg-loader image-webpack-loader 複製程式碼
webpack.common.js:
{ test: /\.(svg|png|jpe?g|gif)$/i, use: [ { loader: "url-loader", options: { limit: 1, name: "images/[name].[contenthash:8].[ext]", publicPath: "../" } }, { loader: "image-webpack-loader", options: { pngquant: { quality: "70-80", speed: 1 } } } ] }, { test: /\.html$/, use:[ 'html-withimg-loader' ] } 複製程式碼
引入字型
修改webpack.common.js:
{ test: /\.(woff|woff2|eot|ttf|otf)$/, use: [ { loader: "file-loader", options: { name: "assets/[name].[contenthash:8].[ext]", publicPath: "../" } } ] } 複製程式碼
babel 升級後有點小噁心..不想說了 後面再根據專案豐富css和js的提取和合並過濾