webpack 最佳實踐
前言
本文講述的最佳實踐是從日常業務中總結而出的,不一定適合所有項目。畢竟每個公司或個人的項目不同,最佳實踐也會有所不同。但是可以從這篇文章借鑑吸收一點有用的東西,有問題的地方也歡迎大家積極吐槽指正
。
爲了避免出現 我這明明可以,你那怎麼不行
的尷尬情況,這裏列一下文章涉及到依賴的版本號。
├── webpack 5.39.1
├── webpack-cli 4.7.2
├── node 12.8.0
├── npm 6.10.2
正文
初始化項目
1. mkdir test-app && cd test-app
2. npm init
首先添加一個入口文件 /src/index.js
和 webpack 配置文件 webpack.config.js
,現在我們的目錄結構如下
test-app
├── src
| └── index.js
├── package.json
├── webpack.config.js
安裝 webpack
npm install webpack webpack-cli -D
開始搞事情
在 src/index.js
中隨便寫點東西
class Test {
constructor() {
document.writeTest('hello world')
}
}
new Test()
先來打個包看看啥效果, 執行命令 npx webpack
1.png
等待一段時間後,看到目錄有了變化, 新增了一個 dist
目錄,該目錄下有一個 main.js
文件
test-app
+ ├── dist
+ | └── main.js
├── src
| └── index.js
├── package.json
├── webpack.config.js
讓我們來看看 main.js
裏有點啥
new class{constructor(){document.writeTest("hello world")}};
這玩意都不用試,肯定不得行啊,得將 js 代碼轉成 es5 纔行。首先安裝下babel-loader
及幾個相關的依賴
配置 babel
-
babel-loader
-
@babel/core
-
@babel/preset-env
-
@babel/plugin-transform-runtime
-
@babel/plugin-proposal-decorators
-
@babel/plugin-proposal-class-properties
-
@babel/plugin-proposal-private-methods
-
@babel/runtime
-
@babel/runtime-corejs3
npm install babel-loader @babel/core @babel/preset-env @babel/plugin-transform-runtime @babel/plugin-proposal-decorators @babel/plugin-proposal-class-properties @babel/plugin-proposal-private-methods -D
npm install @babel/runtime @babel/runtime-corejs3 -s
修改 webpack.config.js
文件, 添加 babel-loader
配置
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.[contenthash:8].js',
},
module: {
rules: [
{
test: /\.(jsx|js)$/,
use: 'babel-loader',
exclude: /node_modules/,
},
]
}
}
根目錄下添加相應的 .babelrc
配置文件
{
"presets": ["@babel/preset-env"],
"plugins": [
["@babel/plugin-transform-runtime", {"corejs": 3}],
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-proposal-class-properties", { "loose": true }],
["@babel/plugin-proposal-private-methods", { "loose": true }]
]
}
再次執行命令 npx webpack
來打個包。完成後查看目錄結構
test-app
├── dist
+ | ├── bundle.b8ba1739.js
| ├── main.js
├── src
| └── index.js
+ ├── .babelrc
├── package.json
├── webpack.config.js
查看構建後的 bundle.b8ba1739.js
文件
(()=>{"use strict";new function n(){!function(n,t){if(!(n instanceof t))throw new TypeError("Cannot call a class as a function")}(this,n),document.writeTest("hello world")}})();
構建產物看着沒什麼問題了,接下來看下在瀏覽器中的實際效果。要看效果,肯定離不開 html
文件。
瀏覽器中觀看效果
作爲一個伸手黨直接從社區嫖來一個插件 html-webpack-plugin
,這個插件的作用是將打包產物引入到我們提前準備好的模板 .html
文件中,我們訪問這個文件就能直觀的看到效果了
先來安裝下插件
npm install html-webpack-plugin -D
接着創建一個 public
目錄, 用來存放靜態資源。新增一個 index.html
模板,放在 public 目錄下
test-app
├── dist
| ├── bundle.b8ba1739.js
| ├── main.js
├── src
| └── index.js
+ ├── public
+ | └── index.html
├── .babelrc
├── package.json
├── webpack.config.js
在 webpack.config.js
中配置 html-webpack-plugin
// 省略 ...
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// 省略 ...
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, './public/index.html'),
inject: 'body',
scriptLoading: 'blocking',
}),
]
}
再次執行命令 npx webpack
來打個包。打完包發現 dist
目錄下多了一個 index.html
文件。瀏覽器中打開 index.html
看看對不對
2.png
作爲一個 api 工程師,連 api 都能記錯。
3.png
修改下 src/index.js
代碼
class Test {
constructor() {
document.write('hello world')
}
}
new Test()
再次執行命令 npx webpack
來打個包。老步驟,先檢查下打包產物對不對
test-app
├── dist
| ├── bundle.b8ba1739.js
+ | ├── bundle.dc044571.js
| ├── index.html
| ├── main.js
├── src
| └── index.js
├── public
| └── index.html
├── .babelrc
├── package.json
├── webpack.config.js
看樣子應該沒錯,代碼修改了,打包後多了個 .js
文件。再看看效果對不對
4.png
界面上也出現了 hello world
。到這裏爲止,算是利用 webpack
走通了一個最小流程。
爲什麼說是最小,因爲到目前爲止這個配置在實際工作中 基本沒卵用 實用性不大
。細心一點的人已經看出來了,上面存在三個問題
-
每修改一次代碼,都要走一遍打包流程,然後自己手動打開 html 文件,預覽效果
-
第一次調用錯誤 api 的時候,報錯信息定位不精確
-
打包目錄下面
上次構建產物
也仍舊存在,時間長了會存在越來越多的無用代碼
作爲一個懶人,第三點可以忍,第一點和第二點忍不了。我們一個個來解決
實時更新並預覽效果
針對第一點,查閱 webpack
官網,發現官網就給指了一條明路
5.png
按照官網教程,首先安裝下 webpack-dev-server
npm install webpack-dev-server -D
再在 webpack.config.js
中添加相應的配置
// 省略 ...
module.exports = {
// 省略 ...
devServer: {
port: '3001', // 默認是 8080
hot: true,
stats: 'errors-only', // 終端僅打印 error
compress: true, // 是否啓用 gzip 壓縮
proxy: {
'/api': {
target: 'http://0.0.0.0:80',
pathRewrite: {
'/api': '',
},
},
},
},
}
在 package.json
> script
中添加一個命令
"dev": "webpack serve --open",
執行 npm run dev
,這個時候在動在瀏覽器中打開了 http://localhost:3001/
頁面。光自動打開還不夠啊,我們的目標是每次修改後不用構建
就能在瀏覽器中實時查看
。爲了測試這個功能是否生效,我們任意修改 src/index.js
文件並保存。發現瀏覽器中內容自動刷新生效了。
想了解更多關於 devServer
的可以閱讀以下兩篇文章
-
【Webpack】devServer 實驗報告
-
120 行代碼幫你瞭解 Webpack 下的 HMR 機制
sourcemap 配置
第一個問題好了,再來看看第二個問題 報錯信息定位不精確
。我們仍舊在官網找找看,有沒有對應的解決方案。通過 1 小時的文檔閱讀和 7 小時的摸魚,終於在一天後找到了解決方法。
我們在 webpack.config.js
中添加配置
// 省略 ...
module.exports = {
// 省略 ...
devtool: 'eval-cheap-module-source-map',
}
這個配置什麼意思呢,它會告訴我們錯誤是在原始代碼
的哪一行發生的。廢話不多說,先來看看效果
6.png
點進去看看是什麼情況
28.png
7.png
這麼精準的定位,一天可以改100
個 bug 了。
但是!!!這玩意好歸好,生產環境可不能亂用。這裏建議
開發環境
最佳:eval-cheap-module-source-map生產環境
最佳:hidden-source-map
什麼?你上下嘴皮子吧嗒一合,說最佳就最佳?沒有拿得出手的理由我們是不會信的
8.png
造謠是不可能造謠的,這輩子都不會。我也是吸收了這篇文章 萬字長文:關於 sourcemap,這篇文章就夠了 的精華才總結出來的。
一萬字的文章總結成兩句話,10 秒鐘吸收
9.png
世事總是這麼奇妙,按照上面的思路,在解決第二個問題的時候又帶出了一個新的問題,某些配置可能需要區分環境來設置,不同的環境設置合適的配置。就像在解決一個bug A
的過程中,發現了一個新的 bug B
。看來在解決上面第三個問題之前,得先解決這個 區分環境配置
的問題了。
拆分環境
按照一般慣例,我們會有 開發
、測試
、預發
、生產
幾個環境。但是我個人很多情況下 開發
和 測試
環境是同一套配置,所以我這裏直接省略 測試
這個環境。
修改下目錄結構
test-app
+ ├── build
+ | ├── webpack.base.js
+ | ├── webpack.dev.js
+ | ├── webpack.pre.js
+ | ├── webpack.pro.js
├── dist
├── ├── bundle.b8ba1739.js
├── ├── bundle.dc044571.js
| ├── index.html
| ├── main.js
├── src
| └── index.js
├── public
| └── index.html
├── .babelrc
├── package.json
從目錄中就可以看出一點東西,我們刪除了原先根目錄下的 webpack.config.js
文件。新增了一個 build
目錄。在 build
目錄下我們需要建一個 webpack.base.js
文件。用來存放各個環境公共的配置,畢竟不可能所有配置在各個環境中都不一樣。然後按照我們各自項目實際的需求來建立不同環境的配置文件。
先修改公共配置文件 webpack.base.js
。原先的 devServe
配置由於只有開發環境有;devtool
各個環境不一樣,所以這兩個配置從公共配置裏移除了
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const rootDir = process.cwd();
module.exports = {
entry: path.resolve(rootDir, 'src/index.js'),
output: {
path: path.resolve(rootDir, 'dist'),
filename: 'bundle.[contenthash:8].js',
},
module: {
rules: [
{
test: /\.(jsx|js)$/,
use: 'babel-loader',
include: path.resolve(rootDir, 'src'),
exclude: /node_modules/,
},
]
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(rootDir, 'public/index.html'),
inject: 'body',
scriptLoading: 'blocking',
}),
],
}
接下來配置各個環境的配置,這裏主要用到一個 webpack-merge
插件,用來合併公共配置,執行 npm install webpack-merge -D
修改 webpack.dev.js
const { merge } = require('webpack-merge');
const baseConfig = require('./webpack.base');
module.exports = merge(baseConfig, {
mode: 'development',
devtool: 'eval-cheap-module-source-map',
devServer: {
port: '3001', // 默認是 8080
hot: true,
stats: 'errors-only', // 終端僅打印 error
compress: true, // 是否啓用 gzip 壓縮
proxy: {
'/api': {
target: 'http://0.0.0.0:80',
pathRewrite: {
'/api': '',
},
},
},
},
});
因爲這裏不涉及到實際的項目開發,所以這裏預發
和生產
兩個環境的文件先配置成一樣的,大家可以根據自己的實際需要來進行不同的配置。
-
webpack.pre.js
-
webpack.pro.js
const { merge } = require('webpack-merge');
const baseConfig = require('./webpack.base');
module.exports = merge(baseConfig, {
mode: 'production',
devtool: 'hidden-source-map',
});
看到仔細的人已經發現,配置中多了一個 mode
屬性,這個會在後面解釋一波,這裏先不講
修改 package.json 中的命令
"scripts": {
"dev": "webpack serve --config build/webpack.dev.js --open",
"build:pro": "npx webpack --config build/webpack.pro.js",
},
再次執行 npm run dev
看看效果
10.png
看來是沒問題了,現在已經成功把 webpack.config.js
文件根據環境進行拆分成了多個文件。
現在來回顧下之前提出的第三個問題
11.png
這個項目小的時候其實問題不大,但是當項目大了之後,每次打包都增加幾百上千的文件,還是有點恐怖的。所以還是把這個問題也順帶解決下好了。
打包時清除上次構建產物
我們的目標是每次打包時刪除上次打包的產物,保證打包目錄下所有文件都是新的,社區查找一番後,找到一個插件clean-webpack-plugin
,來看下這個插件的介紹
12.png
比較懶,所以直接上截圖了。老步驟,先安裝 npm install clean-webpack-plugin -D
然後直接將文檔中的示例代碼借鑑
到我們的項目中。修改 webpack.base.js
// 省略...
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
// 省略...
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(rootDir, 'public/index.html'),
inject: 'body',
scriptLoading: 'blocking',
}),
new CleanWebpackPlugin(),
],
}
試下效果,執行 npm run build:pro
打個包。查看目錄
test-app
├── build
| ├── webpack.base.js
| ├── webpack.dev.js
| ├── webpack.pre.js
| ├── webpack.pro.js
├── dist
| ├── bundle.fd44c2eb.js
| ├── bundle.fd44c2eb.js.map
| ├── index.html
├── src
| └── index.js
├── public
| └── index.html
├── .babelrc
├── package.json
dist
目錄下原先存在的 main.js
、bundle.b8ba1739.js
等前幾次打包產物已經自動清除了。到這裏第三個問題也解決了
功能完善
添加 css 和 less 支持
爲什麼不添加 sass
支持?因爲我不用 sass
首先,在 src
目錄下添加一個 index.less
文件
.test {
color: red;
}
修改 src/index.js
文件,在文件中引用剛纔添加的 less
文件
import './index.less'
class Test {
constructor() {
this.renderDiv()
}
renderDiv() {
const div = document.createElement('div')
div.className = 'test'
div.innerHTML = 'hello world'
document.body.appendChild(div)
}
}
new Test()
執行 npm run dev
等待 10 分鐘後,頁面遲遲沒有加載任何東西,打開控制檯一看
13.png
英語 8 級的我立馬讀懂了報錯:"你 可能 需要 一個 什麼什麼 loader 來 處理 這個 文件 類型, 目前 沒有 loaders 被配置 來 process 這個 文件"
再結合官網的說明
14.png
到了這裏,我好像隱約明白了 webpack
的真諦:雖然很多時候我不行,但是很多大佬會讓我行
。呸,什麼叫不行?這叫 靈活可插拔
,正是這種特性,讓 webpack 可靈活支持各種複雜場景的自定義配置。
忘了正事兒,既然問題找到了,就好解決了,找到幾個處理 css
和 less
的 loader 就行
首先安裝 loader
npm install less style-loader css-loader less-loader -D
再修改 webpack.base.js
文件
// 省略...
module.exports = {
// 省略...
module: {
rules: [
// 省略...
{
test: /\.(le|c)ss$/,
exclude: /node_modules/,
use: ['style-loader', 'css-loader', 'less-loader']
},
]
},
// 省略...
}
再次執行 npm run dev
,查看效果
15.png
css module
這一塊是基於上面的模塊修改的,解決 css
命名混亂和衝突的。不需要的話可以直接跳過這一塊。
修改 webpack.base.js
// 省略...
module.exports = {
// 省略...
module: {
rules: [
// 省略...
{
test: /\.(le|c)ss$/,
exclude: /node_modules/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: {
compileType: 'module',
localIdentName: "[local]__[hash:base64:5]",
},
},
},
'less-loader'
]
},
]
},
// 省略...
}
執行 npm run dev
來看看效果
16.png
給 class
樣式名稱後加上一個哈希串,具體的配置可以看 css-loader 官網
css 自動添加前綴
首先安裝插件
npm install autoprefixer postcss postcss-loader -D
修改 webpack.base.js
配置文件
// 省略...
const autoprefixer = require('autoprefixer');
module.exports = {
// 省略...
module: {
rules: [
// 省略...
{
test: /\.(le|c)ss$/,
exclude: /node_modules/,
use: [
// 省略...
'less-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
["autoprefixer"],
],
},
},
}
]
},
]
},
// 省略...
}
打包後抽離 css 文件
首先安裝 mini-css-extract-plugin
插件
npm install mini-css-extract-plugin -D
修改 webpack.base.js
配置文件
// 省略...
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
// 省略...
module: {
rules: [
// 省略...
{
test: /\.(le|c)ss$/,
exclude: /node_modules/,
use: [
MiniCssExtractPlugin.loader,
// 省略...
]
},
]
},
plugins: [
// 省略...
new MiniCssExtractPlugin({
filename: 'css/[name].css',
}),
],
}
執行 npm run build:pro
打個包看看效果。
17.png
可以看到 css 已經被抽離出來了
壓縮打包後的 css 文件
首先安裝 optimize-css-assets-webpack-plugin
插件
npm install optimize-css-assets-webpack-plugin -D
修改 webpack.base.js
配置文件
// 省略...
const OptimizeCssPlugin = require('optimize-css-assets-webpack-plugin');
module.exports = {
// 省略...
plugins: [
// 省略...
new MiniCssExtractPlugin({
filename: 'css/[name].css',
}),
new OptimizeCssPlugin(),
],
}
執行 npm run build:pro
打個包看看效果。
.test__1PSRs{color:red;transition-duration:.4s}
可以看出 css 已經被壓縮了
複製靜態資源到打包目錄
有些時候有些第三方的 js 插件沒有提供 npm 包,只提供了一個 cdn 地址或者一份文件需要自己下載下來。通常我們下載下來之後放在我們的 public/js
目錄下面,然後 public/index.html
文件裏直接用 script
標籤引入。這個時候不管是 npm run dev
開發時,還是 npm run build:pro
構建後,這個 js 文件都是找不到的。我們可以嘗試下
在 public/js
新加一個 test.js
的空文件,啥內容都不用。然後在 public/index.html
中引入這個文件
<!DOCTYPE html>
<html lang="en">
<head>
// 省略
</head>
<body>
<div id="root"></div>
<script src="./js/test.js"></script>
</body>
</html>
執行 npm run dev
查看效果
18.png
這裏我們可以用 copy-webpack-plugin
這個插件,在構建的時候,將 public/js
的靜態資源複製到 dist
目錄下,這樣文件就能找到了
安裝插件 npm install copy-webpack-plugin -D
修改 webpack.base.js
配置文件
// 省略...
const CopyWebpackPlugin = require('copy-webpack-plugin');
const rootDir = process.cwd();
module.exports = {
// 省略...
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(rootDir, 'public/index.html'),
inject: 'body',
scriptLoading: 'blocking',
}),
new CleanWebpackPlugin(),
new CopyWebpackPlugin({
patterns: [
{
from: '*.js',
context: path.resolve(rootDir, "public/js"),
to: path.resolve(rootDir, 'dist/js'),
},
],
})
new MiniCssExtractPlugin({
filename: 'css/[name].css',
}),
new OptimizeCssPlugin(),
],
}
執行 npm run dev
查看效果
19.png
靜態文件已經可以正常加載了。
資源加載器
項目中難免要引入一些圖標、圖片等資源,在不做任何處理的情況下,我們嘗試下在代碼中引用圖片,修改 src/index.js
文件如下
import wuhanjiayou from '../public/asset/a.jpeg'
class Test {
constructor() {
this.renderImg()
}
renderImg() {
const img = document.createElement('img')
img.src = wuhanjiayou
document.body.appendChild(img)
}
}
new Test()
執行 npm run dev
看下效果,報了個熟悉的錯
20.png
按照以往的套路,直接引用社區的三件套 raw-loader
、url-loader
、file-loader
,安裝依賴,配置依賴,一通操作下來就解決了問題。現在我們使用 webpack5
就方便多了,不用安裝任何依賴,直接修改 webpack.base.js
配置文件
// 省略...
rules: [
{
test: /\.(png|jpg|gif|jpeg|webp|svg|eot|ttf|woff|woff2)$/,
type: 'asset',
},
]
沒錯,就是這麼簡單。type
屬性還有其他幾個值,具體可以看 官方文檔
配置已經修改好了,執行 npm run dev
再來看下效果
21.png
搞定!
上面講到的東西基本夠小項目的日常開發需求了,常用的 loader 和 plugin 都已經有所涉及。但是,如果你的項目特別複雜,需求又比較小衆,社區沒有現成的 loader 和 plugin 可以借鑑,那麼只能自己動手實現
一個了。
22.png
可能在一部分人眼中,loader 和 plugin 是比較神祕的,也不可能想着自己去造一個輪子。但是當碰到問題又沒有現成的解決方案的時候,那就不得不自己造了。
看了這篇文章 Webpack - 手把手教你寫一個 loader / plugin 應該能很快上手
項目優化
剛纔也講到了,上面的一通操作基本夠小項目開發使用了。爲什麼是小項目?大項目不行嗎?當一個項目大到路由都有幾百個
的時候,一次熱更新就需要十幾二十多秒,一次打包要半個小時。開發時,一次代碼改動保存就要等 20 秒
,這擱誰誰都忍不了啊。這個時候就需要想點辦法來優化。
loader 配置優化
這個其實上面已經做了。明確告訴 loader,哪些文件不用做處理 (exclude),或者只處理哪些文件 (include)。
{
test: /\.(jsx|js)$/,
use: 'babel-loader',
// include: [path.resolve(rootDir, 'src')]
// exclude: /node_modules/,
},
一般傾向於使用 include
,但是如果怕漏處理一些文件的話,粗暴點,使用 exclude: /node_modules/
也可以。
這部分測試了下,提升速度不是很明顯,應該算錦上添花吧
緩存
先說下 webpack5
之前是怎麼做的。
利用 cache-loader
將結果緩存中磁盤中;利用 hard-source-webpack-plugin
將結果緩存在 node_modules/.cache
下提升二次打包速度;利用 DllReferencePlugin
將變化不頻繁的第三方庫提前單獨
打包成動態鏈接庫,提升真正業務代碼的打包速度
webpack5 自帶了持久化緩存,配置如下
開發環境 webpack.dev.js
cache: {
type: 'memory'
},
生產環境 webpack.pro.js
cache: {
type: 'filesystem',
buildDependencies: {
config: [__filename]
}
},
這個測試了下前後的打包時間
23.png
24.png
數據是這個數據:
-
第一次:
12592 ms
-
第二次:
920 ms
但是我心裏默數了下,二次打包大概在 3 秒左右,咱也不知道控制檯的計時邏輯是什麼
25.png
如果在構建時,你主動確定要放棄舊的緩存的話,可以傳一個新的 version
參數來放棄使用緩存
cache: {
type: 'filesystem',
buildDependencies: {
config: [__filename]
},
version: 'new_version'
},
代碼拆分
optimization: {
splitChunks: {
chunks: 'all',
}
}
這個在 mode: production
時是默認開啓的,但是默認情況下只會對按需加載的代碼進行分割。如果我們要對一開始就加載的代碼也做分割處理,就要進行如上配置。
從官網截了一張圖:
26.png
大家的項目可能都有所不同,相對應的最佳的配置可能也有所不同,所以這裏就補貼具體的配置了,大家有需要的可以看官網的文檔對自己的項目進行配置 官網 optimization.splitChunks 更多配置、「Webpack」從 0 到 1 學會 code splitting
mode
mode: production
在上面出現了這麼多次,也沒有具體說有哪些功能。其實當設置 mode: production
時,webpack
已經默認開啓了一些優化措施。
27.png
這裏面的一些東西由於篇幅較大也不做一一說明了,反正只要記得 mode: production
已經給我們做了一系列優化,真的想知道有哪些優化的,我找了篇文章,有興趣的可以看看 mode 詳解
happypack
利用 happypack
插件進行多線程打包,按照官網文檔進行配置
// 省略...
const Happypack = require('happypack');
const os = require('os')
const happyThreadPool = Happypack.ThreadPool({ size: os.cpus().length })
// 省略...
rules: [
{
test: /\.(jsx|js)$/,
// use: 'babel-loader',
use: 'Happypack/loader?id=js',
exclude: /node_modules/,
},
]
plugins: [
new Happypack({
id: 'js', // 這個 id 值爲上面 Happypack/loader?id=js 問號後跟的參數
use: ['babel-loader'],
threadPool: happyThreadPool
}),
]
由於本篇文章寫的是個 demo,沒有業務代碼,所以這個打包出來的時間基本沒變化甚至還多了 1 秒
,這裏就不貼效果圖了。這是因爲happypack
執行也需要時間,如果項目比較小的話,就不需要配置了。js
處理完之後那就是要處理css
了, 按照處理js
的方式,ctrl+c/ctrl+v
處理css
。
執行 npm run build:pro
ERROR in ./src/index.less
Module build failed (from ./node_modules/Happypack/loader.js):
Error: You forgot to add 'mini-css-extract-plugin' plugin (i.e. `{ plugins: [new MiniCssExtractPlugin()] }`), please read https://github.com/webpack-contrib/mini-css-extract-plugin#getting-started
報錯說忘記添加了mini-css-extract-plugin
插件,但是明明已經添加了,經過試驗,發現是 mini-css-extract-plugin
這個插件引起 happypack
報錯的。終於,在經過 百度
、谷歌
等一系列騷操作後,我放棄了,沒找到解決方法
尷尬. png
現在擺在面前的就三條路:
-
放棄使用
happypack
-
使用
happypack
優化js
和css
,放棄使用mini-css-extract-plugin
-
使用
happypack
優化js
,放棄優化css
,保留mini-css-extract-plugin
知道咋解決的或有更好的方式的可以在下方留言,讓我白嫖 借鑑下。
thread-loader
如果採用上面第一種,放棄使用 happypack
,可以用 thread-loader
代替下。而且這個配置非常簡單。
先安裝: npm install thread-loader -D
,再修改配置
// 省略...
rules: [
{
test: /\.(jsx|js)$/,
use: ['thread-loader', 'babel-loader'],
exclude: /node_modules/,
},
{
test: /\.(le|c)ss$/,
exclude: /node_modules/,
use: [
MiniCssExtractPlugin.loader,
'thread-loader',
{
loader: 'css-loader',
options: {
modules: {
compileType: 'module',
localIdentName: "[local]__[hash:base64:5]",
},
},
},
'less-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
["autoprefixer"],
],
},
},
}
],
},
]
到這裏應該可以應付一般的項目了。由於這篇文章主要講述 webpack 的應用,所以很多知識點沒有細講,也沒有精力細講,但是很多涉及到的知識點都推薦了相應的文章,有興趣的朋友可以看一下。
參考文獻:
-
webpack5
-
webpack4 升級到 5
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/f7Syl4pPiijUTSNUWms75A