前言
webpack 4.0以前,我們通過extract-text-webpack-plugin外掛,把css樣式從js檔案中提取到單獨的css檔案中。extract-text-webpack-plugin外掛的優缺點:
更多介紹請看移步:webpack.docschina.org/plugins/ext…
webpack 4.0以後,官方推薦使用extract-text-webpack-plugin外掛來打包css檔案。
使用方法
把所有配置檔案放到專案的根目錄下,執行package.json
中的命令即可。當然,webpack的入口、出口等基礎配置還需自行參照官網文件完成配置。
為了更貼近實際應用場景,本次採用三個配置檔案,分別講解它們的配置以及注意事項。
webpack.common.js (公共配置檔案)
- 開發環境和生產環境共用的配置,藉助
webpack-merge
外掛,可以merge到開發或生產環境,從而減少重複配置。 - 引入了Node環境變數
process.env.NODE_ENV
,可以根據傳入的環境引數,動態更改配置,具體請看程式碼。
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const devMode = process.env.NODE_ENV !== 'production'
module.exports = {
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/, // 可以打包字尾為sass/scss/css的檔案
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
// 這裡可以指定一個 publicPath
// 預設使用 webpackOptions.output中的publicPath
// publicPath的配置,和plugins中設定的filename和chunkFilename的名字有關
// 如果打包後,background屬性中的圖片顯示不出來,請檢查publicPath的配置是否有誤
publicPath: './',
// publicPath: devMode ? './' : '../', // 根據不同環境指定不同的publicPath
hmr: devMode, // 僅dev環境啟用HMR功能
},
},
'css-loader',
'sass-loader'
],
},
]
},
plugins: [
new MiniCssExtractPlugin({
// 這裡的配置和webpackOptions.output中的配置相似
// 即可以通過在名字前加路徑,來決定打包後的檔案存在的路徑
filename: devMode ? 'css/[name].css' : 'css/[name].[hash].css',
chunkFilename: devMode ? 'css/[id].css' : 'css/[id].[hash].css',
})
]
}
複製程式碼
webpack.dev.js(dev環境的配置檔案)
- dev環境的配置,記得把
mode
設定為development
模式,否則webpack4會預設為production
模式。
const merge = require('webpack-merge')
const common = require('./webpack.common')
const webpack = require('webpack')
module.exports = merge(common, {
mode: 'development'
})
複製程式碼
webpack.prod.js(生產環境的配置檔案)
- 生產環境的配置,預設開啟tree-shaking和js程式碼壓縮;
- 通過
optimize-css-assets-webpack-plugin
外掛可以對css進行壓縮,與此同時,必須指定js壓縮外掛(例子中使用terser-webpack-plugin
外掛),否則webpack不再對js檔案進行壓縮; - 設定
optimization.splitChunks.cacheGroups
,可以將css程式碼塊提取到單獨的檔案中。
const path = require('path')
const merge = require('webpack-merge')
const common = require('./webpack.common')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const TerserJSPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
module.exports = merge(common, {
mode: 'production',
optimization: {
minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
splitChunks: {
cacheGroups: {
styles: {
name: 'styles',
test: /\.css$/,
chunks: 'all',
enforce: true,
},
}
},
}
})
複製程式碼
package.json配置檔案
- sideEffects: 生產環境打包的時候,會預設開啟tree-shaking,如果不設定
sideEffects
,某些通過import
方式引入的css檔案可能不會被打包,因為tree-shaking會甩掉引入後未使用的程式碼。通常,css檔案一般都是引入就好,很少使用裡面的方法或變數,所以很容易被webpack認為是沒有用的程式碼,從而不會被打包。所以,不希望被tree-shaking的檔案,請在sideEffects
中配置與之匹配的正規表示式。 - NODE_ENV: 由於專案中用到了Node的環境變數,所以打包時需通過
NODE_ENV
傳入環境變數。這裡的配置在macOS操作是沒有問題的,Windows系統的小夥伴,可以安裝一個叫cross-env
的npm包,使用方法略。
{
"sideEffects": [
"*.css",
"*.scss",
"*.sass"
],
"scripts": {
"build": "NODE_ENV=production webpack --config webpack.prod.js --progress", // 生產環境打包
"dev": "NODE_ENV=development webpack --config webpack.dev.js --progress", // dev環境打包
},
}
複製程式碼
總結
- 不同環境下的打包,如果出現圖片顯示不了時(特別是css中的圖片),請檢查
publicPath
的配置。 mode: 'production'
會開啟tree-shaking和js程式碼壓縮,但配置optimization. minimizer
會使預設的壓縮功能失效。所以,指定css壓縮外掛的同時,務必指定js的壓縮外掛。mini-css-extract-plugin
外掛,結合optimization.splitChunks.cacheGroups
配置,可以把css程式碼打包到單獨的css檔案,且可以設定存放路徑(通過設定外掛的filename
和chunkFilename
)。
官方文件: webpack.js.org/plugins/min…
如有錯誤,歡迎在評論區指正或私聊我,謝謝!