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命令,打包生成的文件以下以下所示

相关文章
相关标签/搜索