mini-css-extract-plugin簡介
將css單獨打包成一個檔案的外掛,它為每個包含css的js檔案都建立一個css檔案。它支援css和sourceMaps的按需載入。
目前只有在webpack V4版本才支援使用該外掛
和extract-text-webpack-plugin相比:
- 非同步載入
- 無重複編譯,效能有所提升
- 用法簡單
- 之支援css分割
例子:
-
支援HMR
* Install *
npm install --save-dev mini-css-extract-plugin
簡單的例子
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); module.exports={ plugins:[ new MiniCssExtractPlugin({ // Options similar to the same options in webpackOptions.output // both options are optional filename: "[name].css", chunkFilename: "[id].css" }) ], module: { rules: [ { test: /\.css$/, use: [ { loader: MiniCssExtractPlugin.loader, options: { // you can specify a publicPath here // by default it use publicPath in webpackOptions.output publicPath: '../' } }, "css-loader" ] } ] } }
高階的配置
這個外掛應該只在生產環境構建中使用,並且在loader鏈中不應該有style-loader,特別是我們在開發模式中使用HMR時。
下面是一個在開發模式中使用HMR並在生產環境構建的檔案中提出出css樣式的示例。
(各個loader的配置根據你的需求進行自定義修改)
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const devMode = process.env.NODE_ENV !== 'production' module.exports = { plugins: [ new MiniCssExtractPlugin({ // Options similar to the same options in webpackOptions.output // both options are optional filename: devMode ? '[name].css' : '[name].[hash].css', chunkFilename: devMode ? '[id].css' : '[id].[hash].css', }) ], module: { rules: [ { test: /\.(sa|sc|c)ss$/, use: [ devMode ? 'style-loader' : MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader', ], } ] } }
生產環境最小化
等到webpack V5時,有可能會將css壓縮功能進行整合,但是在webpack V4,我們還需要手動使用optimize-css-assets-webpack-plugin來進行css的壓縮。配置wepack的optimization.minimizer選項來覆蓋webpack的預設配置。同時也要指定一個js壓縮器。
wepack.config.js
const UglifyJsPlugin = require("uglifyjs-webpack-plugin"); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); module.exports={ optimization: { minimizer: [ new UglifyJsPlugin({ cache: true, parallel: true, sourceMap: true // set to true if you want JS source maps }), new OptimizeCSSAssetsPlugin({}) ] }, plugins: [ new MiniCssExtractPlugin({ filename: "[name].css", chunkFilename: "[id].css" }) ], module: { rules: [ { test: /\.css$/, use: [ MiniCssExtractPlugin.loader, "css-loader" ] } ] } } }
其他功能
使用預載入或內聯CSS
執行時程式碼通過link 或 style標籤檢測已經新增的css,當在服務端注入css為了在服務端進行渲染時是非常有用的。link標籤的href屬性用來匹配被載入的css塊的URL,data-href屬性也可以在link和style標籤上使用,當使用內聯樣式的時候必須使用href.
提取所有的css到一個檔案中
類似於 extract-text-webpack-plugin的作用,可以使用optimization.splitChunks.cacheGroups來將css提取到一個檔案中
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); module.exports = { optimization: { splitChunks: { cacheGroups: { styles: { name: 'styles', test: /\.css$/, chunks: 'all', enforce: true } } } }, plugins: [ new MiniCssExtractPlugin({ filename: "[name].css", }) ], module: { rules: [ { test: /\.css$/, use: [ MiniCssExtractPlugin.loader, "css-loader" ] } ] } }
根據webpack 的 entry 提取 css
還可以根據webpack entry提取CSS。如果動態匯入路由,但希望根據條目將CSS繫結在一起,那麼這一點尤其有用。這也防止了使用ExtractTextPlugin時出現的CSS複製問題。
webpack.config.js
const path = require('path'); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); function recursiveIssuer(m) { if (m.issuer) { return recursiveIssuer(m.issuer); } else if (m.name) { return m.name; } else { return false; } } module.exports = { entry: { foo: path.resolve(__dirname, 'src/foo'), bar: path.resolve(__dirname, 'src/bar') }, plugins: [ new MiniCssExtractPlugin({ filename: "[name].css", }) ], module: { rules: [ { test: /\.css$/, use: [ MiniCssExtractPlugin.loader, "css-loader" ] } ] }, optimization:{ splitChunks:{ cacheGroups:{ fooStyles:{ fooStyles: { name: 'foo', test: (m,c,entry = 'foo') => m.constructor.name === 'CssModule' && recursiveIssuer(m) === entry, chunks: 'all', enforce: true } } } } } }