Webpack之MiniCssExtractPlugin插件用法詳解

1、插件的做用

This plugin extracts CSS into separate files. It creates a CSS file per JS file which contains CSS. It supports On-Demand-Loading of CSS and SourceMaps.css

用某度翻譯後:「該插件將CSS提取到單獨的文件中。它爲每一個包含CSS的JS文件建立一個CSS文件。它支持CSS和SourceMap的按需加載。」html

包含CSS的JS文件,JS文件不是指組件對應的JS文件,是指打包後生成的JS文件。 webpack

2、插件的優勢

在Webpack4.0以前,是用ExtractTextWebpackPlugin插件來提取css的,與其相比有以下優勢git

  • 異步加載
  • 沒有重複的編譯(性能)
  • 更容易使用
  • 特定於CSS

3、插件的簡單用法

搭建個簡單的Wenpack Demo,演示一下。github

先安裝MiniCssExtractPlugin插件。web

npm install --save-dev mini-css-extract-plugin
複製代碼

安裝成功後,在webpack.config.js文件中配置。npm

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
    entry: {
        main: "./src/main.js",
    },
    plugins:[
        new MiniCssExtractPlugin(),
    ],
    module:{
        rules:[
            {
                test: /\.css$/,
                use:[MiniCssExtractPlugin.loader,'css-loader']
            },
        ]
    }
}
複製代碼

入口文件爲main.js瀏覽器

import './css/main.css'
import './index'
console.log('main')
複製代碼

index.jsbash

import './css/index.css'
import './index'
console.log('main')
複製代碼

main.cssindex.css內容同樣異步

.class{
    color:red
}
複製代碼

執行命令webpack,能夠在dist文件夾中看到打包生成的三個文件

項目中有兩個包含CSS的JS文件,可是隻打包生成了一個CSS文件,證明了上面 「它爲每一個包含CSS的JS文件建立一個CSS文件」中的包含CSS的JS文件是指打包後生成的JS文件

在瀏覽器打開index.html,在開發者工具中能夠看到以下圖所示

打包生成的CSS文件用link標籤引入

若是沒有用MiniCssExtractPlugin插件呢,改一下webpack.config.js文件中配置。

module:{
    rules:[
        {
            test: /\.css$/,
            use:['style-loader','css-loader']
        },
    ]
}
複製代碼

再執行webpack命令。在瀏覽器打開index.html,會發現樣式在頭部用<style></style>嵌入式引入。

看到這裏也應該明白了MiniCssExtractPlugin插件的做用,就是提取JS中的CSS樣式,用link外部引入,減小JS文件的大小,簡稱CCSS樣式分離。

MiniCssExtractPlugin插件不能和style-loader共用

4、插件的參數

filename

控制從打包後的入口JS文件中提取CSS樣式生成的CSS文件的名稱。

module.exports = {
    entry: {
        main: "./src/main.js",
    },
    plugins:[
        new MiniCssExtractPlugin({
            filename: '[name]-test.css',
        }),
    ]
}
複製代碼

執行webpack命令,能夠在dist文件夾中看到打包生成的CSS文件名稱爲main-test.css

chunkFilename

控制從打包後的非入口JS文件中提取CSS樣式生成的CSS文件的名稱。

module.exports = {
    entry: {
        main: "./src/main.js",
    },
    plugins:[
        new MiniCssExtractPlugin({
            filename: '[name]-test.css',
            chunkFilename: '[name]-test.css'
        }),
    ]
}
複製代碼

main.js

import './css/main.css'
import(/*webpackChunkName: "index"*/ './index')
console.log('main')
複製代碼

執行webpack命令,能夠在dist文件夾中看到非入口JS文件index.bundle.js提取出來的CSS文件名爲index-test.css

moduleFilename

該參數的值是個函數,主要應用多入口場景,控制從打包後的入口JS文件中提取CSS樣式生成的CSS文件的名稱。

若是和filename參數共用,filename將不起做用。

module.exports = {
    entry: {
        main: "./src/main.js",
        main1: "./src/main1.js",
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: 'css/[name].css',
            moduleFilename: (
                { name }) => {
                    return `${name}.css`
                },
        }),
    ],
}
複製代碼

執行webpack命令,打包生成的文件以下圖所示

ignoreOrder

控制css的引入順序不一致是否警告,true表示警告,false表示不警告。

簡單的說,就是在js裏css的引入順序致使的問題,多個css的在js裏的引入順序不一樣,就會有這個警告。例如,在1.js 裏,引入的順序是a.css, b.css; 在2.js裏,引入順序是b.css,a.css,出現了這種引入順序不一樣,就致使了警告。在兩個js裏把引入順序調成一致,就沒問題了。在1.js和2.js裏的引入順序都調整成a.css, b.css 就沒有那個警告了。

固然也能夠設置ignoreOrder參數爲false,關閉這些警告。

具體能夠看官網的這個issue

5、插件loader的參數

publicPath

默認值是webpackOptions.output,以下面所示,默認值就是path.resolve(__dirname, 'dist')

module.exports = {
    output: {
        filename: "[name].bundle.js",
        path: path.resolve(__dirname, 'dist'),
    },
}
複製代碼

做用是指定目標文件的定製公共路徑。有點難理解,下面用一個實例來解釋。

main.css

body{
    background: url('./LOGO.png');
}
複製代碼

main.js入口文件

import './css/main.css'
console.log('main')
複製代碼

由於main.css中引入圖片,要用file-loader處理一下。在webpack.config.js中這麼配置

module.exports = {
    module: {
        rules: [
            {
                test: /\.png$/,
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            name: 'img/[name].[hash:8].[ext]'
                        }
                    }
                ]
            },
        ],
    },
};
複製代碼

執行webpack命令,打包生成的CSS文件以下main.css以下所示

圖片放在 dist文件夾下 img文件夾中,這時在瀏覽器打開 index.html,圖片是能夠加載出來。

若是改一下生成的CSS文件路徑。

module.exports = {
    plugins:[
        new MiniCssExtractPlugin({
            filename: 'css/[name].css',
        }),
    ]
}
複製代碼

再執行webpack命令,打包生成的CSS文件以下main.css以下所示

圖片仍是放在 dist文件夾下 img文件夾中,可是在瀏覽器打開 index.html圖片沒法加載出來

由於main.css 中圖片的引用路徑是img/LOGO.af6d901d.png,顯然路徑不對,因此圖片沒法加載出來,要把圖片的引用路徑改爲../img/LOGO.af6d901d.png才能夠加載出來。

可是不可能去修改打包生成的文件,那要如何解決這個錯誤呢?此時publicPath參數的做用就體現出來了,能夠利用publicPath參數來修改圖片的引用路徑,修改一下webpack.config.js的配置。

module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    {
                        loader:MiniCssExtractPlugin.loader,
                        options:{
                            publicPath:'../'
                        }
                    },
                'css-loader']
            },
        ],
    }
}
複製代碼

再執行webpack命令,打包生成的CSS文件以下main.css以下所示

在瀏覽器打開index.html圖片能夠加載出來

publicPath的做用指定目標文件的定製公共路徑,能夠理解爲指定../img/LOGO.af6d901d.pngimg前面的路徑../

esModule

默認值爲false,表明MiniCssExtractPlugin生成使用CommonJS模塊語法的JS模塊。

若爲true,表明MiniCssExtractPlugin生成使用ES6模塊語法的JS模塊。

hmr

默認爲false,爲true時啓動樣式文件熱更新。

在不啓用樣式文件熱更新時,修改CSS源文件的時候,修改的樣式不會自動在頁面上顯示,須要手動刷新頁面,纔會加載變化。啓動樣式文件熱更新後,再也不須要刷新整個頁面,修改的樣式就能夠自動在頁面上顯示。

上面說到過MiniCssExtractPlugin插件不能和style-loader共用,通常在開發環境中配置style-loader,在生產環境中配置MiniCssExtractPlugin插件。其實style-loader也能夠實現樣式文件熱更新。

HMR is an opt-in feature that only affects modules containing HMR code. One example would be patching styling through the style-loader. In order for patching to work, the style-loader implements the HMR interface; when it receives an update through HMR, it replaces the old styles with the new ones.

可是MiniCssExtractPlugin插件的樣式文件熱更新比style-loader更強大一些。好比說在public文件夾中的index.html引入一個CSS樣式文件,若是修改了這個CSS樣式文件的源碼,使用style-loader是不會觸發樣式文件熱更新,由於style-loader只熱更新JS中引入的樣式,但MiniCssExtractPlugin插件會熱更新加載全部的樣式。

通常只在生產環境中將hmr設置爲true

module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    {
                        loader:MiniCssExtractPlugin.loader,
                        options:{
                            publicPath:'../',
                            hmr: process.env.NODE_ENV === 'development',
                        }
                    },
                'css-loader']
            },
        ],
    }
}
複製代碼

reloadAll

if hmr does not work, this is a forceful method.

通常配合hrm參數使用,爲true時,表示樣式文件熱更新不起做用時從新加載所有樣式。

module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    {
                        loader:MiniCssExtractPlugin.loader,
                        options:{
                            publicPath:'../',
                            hmr: process.env.NODE_ENV === 'development',
                            reloadAll: true
                        }
                    },
                'css-loader']
            },
        ],
    }
}
複製代碼

6、將全部CSS提取到一個文件中

用SplitChunks插件去實現。SplitChunks插件的具體用法能夠看我另外一篇文章:Webpack之SplitChunks插件用法詳解

module.exports = {
    optimization: {
        splitChunks: {
            cacheGroups: {
                styles: {
                    name: 'styles',
                    test: /\.css$/,
                    chunks: 'all',
                    enforce: true,
                },
            },
        },
    },
}
複製代碼

執行webpack命令,打包生成的文件以下以下所示

相關文章
相關標籤/搜索