前言
webpack 4.0以前,我們通過extract-text-webpack-plugin插件,把css樣式從js文件中提取到單獨(dú)的css文件中。extract-text-webpack-plugin插件的優(yōu)缺點(diǎn):
image.png
更多介紹請看移步:https://webpack.docschina.org/plugins/extract-text-webpack-plugin/
webpack 4.0以后,官方推薦使用extract-text-webpack-plugin插件來打包c(diǎn)ss文件。
使用方法
把所有配置文件放到項(xiàng)目的根目錄下,運(yùn)行package.json
中的命令即可。當(dāng)然,webpack的入口、出口等基礎(chǔ)配置還需自行參照官網(wǎng)文檔完成配置。
為了更貼近實(shí)際應(yīng)用場景,本次采用三個(gè)配置文件,分別講解它們的配置以及注意事項(xiàng)。
webpack.common.js (公共配置文件)
- 開發(fā)環(huán)境和生產(chǎn)環(huán)境共用的配置,借助
webpack-merge
插件,可以merge到開發(fā)或生產(chǎn)環(huán)境,從而減少重復(fù)配置。 - 引入了Node環(huán)境變量
process.env.NODE_ENV
,可以根據(jù)傳入的環(huán)境參數(shù),動(dòng)態(tài)更改配置,具體請看代碼。
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: {
// 這里可以指定一個(gè) publicPath
// 默認(rèn)使用 webpackOptions.output中的publicPath
// publicPath的配置,和plugins中設(shè)置的filename和chunkFilename的名字有關(guān)
// 如果打包后,background屬性中的圖片顯示不出來,請檢查publicPath的配置是否有誤
publicPath: './',
// publicPath: devMode ? './' : '../', // 根據(jù)不同環(huán)境指定不同的publicPath
hmr: devMode, // 僅dev環(huán)境啟用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環(huán)境的配置文件)
- dev環(huán)境的配置,記得把
mode
設(shè)置為development
模式,否則webpack4會(huì)默認(rèn)為production
模式。
const merge = require('webpack-merge')
const common = require('./webpack.common')
const webpack = require('webpack')
module.exports = merge(common, {
mode: 'development'
})
webpack.prod.js(生產(chǎn)環(huán)境的配置文件)
- 生產(chǎn)環(huán)境的配置,默認(rèn)開啟tree-shaking和js代碼壓縮;
- 通過
optimize-css-assets-webpack-plugin
插件可以對css進(jìn)行壓縮,與此同時(shí),必須指定js壓縮插件(例子中使用terser-webpack-plugin
插件),否則webpack不再對js文件進(jìn)行壓縮; - 設(shè)置
optimization.splitChunks.cacheGroups
,可以將css代碼塊提取到單獨(dú)的文件中。
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: 生產(chǎn)環(huán)境打包的時(shí)候,會(huì)默認(rèn)開啟tree-shaking,如果不設(shè)置
sideEffects
,某些通過import
方式引入的css文件可能不會(huì)被打包,因?yàn)閠ree-shaking會(huì)甩掉引入后未使用的代碼。通常,css文件一般都是引入就好,很少使用里面的方法或變量,所以很容易被webpack認(rèn)為是沒有用的代碼,從而不會(huì)被打包。所以,不希望被tree-shaking的文件,請?jiān)?code>sideEffects中配置與之匹配的正則表達(dá)式。 -
NODE_ENV: 由于項(xiàng)目中用到了Node的環(huán)境變量,所以打包時(shí)需通過
NODE_ENV
傳入環(huán)境變量。這里的配置在macOS操作是沒有問題的,Windows系統(tǒng)的小伙伴,可以安裝一個(gè)叫cross-env
的npm包,使用方法略。
{
"sideEffects": [
"*.css",
"*.scss",
"*.sass"
],
"scripts": {
"build": "NODE_ENV=production webpack --config webpack.prod.js --progress", // 生產(chǎn)環(huán)境打包
"dev": "NODE_ENV=development webpack --config webpack.dev.js --progress", // dev環(huán)境打包
},
}
總結(jié)
- 不同環(huán)境下的打包,如果出現(xiàn)圖片顯示不了時(shí)(特別是css中的圖片),請檢查
publicPath
的配置。 -
mode: 'production'
會(huì)開啟tree-shaking和js代碼壓縮,但配置optimization. minimizer
會(huì)使默認(rèn)的壓縮功能失效。所以,指定css壓縮插件的同時(shí),務(wù)必指定js的壓縮插件。 -
mini-css-extract-plugin
插件,結(jié)合optimization.splitChunks.cacheGroups
配置,可以把css代碼打包到單獨(dú)的css文件,且可以設(shè)置存放路徑(通過設(shè)置插件的filename
和chunkFilename
)。
官方文檔: https://webpack.js.org/plugins/mini-css-extract-plugin/
如有錯(cuò)誤,歡迎在評論區(qū)指正或私聊我,謝謝!