webpack4.x抽取css【extract-text-webpack-plugin与mini-css-extract-plugin】

参考文档:
https://www.npmjs.com/package/extract-text-webpack-plugin
https://www.npmjs.com/package/mini-css-extract-plugin

项目的初始诉求是利用webpack来管理css(合并),并增加hash(性能优化),当前项目使用webpack版本为4.6.0。

开始选择的插件是extract-text-webpack-plugin,安装命令如下:

sudo npm install extract-text-webpack-plugin

此时webpack配置文件如下:

const path = require("path");
const htmlWebpackPlugin = require('html-webpack-plugin');
const cleanWebpackPlugin = require('clean-webpack-plugin');
const extractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
    entry: "./js/main.js",
    output: {
        path: path.resolve(__dirname, "build"),
        publicPath: "/build/",
        filename: "index.[chunkhash:8].js"
    },
    module: {
        rules: [
            {
                test: /.js$/ ,
                loader: 'babel-loader',
                exclude: /node_modules/
            },
            {
                test: /.css$/,
                use: extractTextPlugin.extract({
                    fallback: 'style-loader',
                    use: [
                        {
                            loader: 'css-loader',
                            options: {
                                url: false
                            }
                        }
                    ]
                })
            }
        ]
    },
    devtool: 'inline-source-map',
    mode: 'development',
    plugins: [
        new htmlWebpackPlugin({
            filename: '../index.html',
            template: 'html/index.html',
            inject: 'body'
        }),
        new htmlWebpackPlugin({
            filename: '../login.html',
            template: 'html/login.html',
            inject: 'body'
        }),
        new htmlWebpackPlugin({
            filename: '../mail.html',
            template: 'html/mail.html',
            inject: 'body'
        }),
        new htmlWebpackPlugin({
            filename: '../pinboard_copy_link.html',
            template: 'html/pinboard_copy_link.html',
            inject: 'body'
        }),
        new cleanWebpackPlugin(['build']),
        new extractTextPlugin({
            filename: 'focus.index.css'
        })
    ]
};

但是构建时会报如下错误:

Error: Chunk.entrypoints: Use Chunks.groupsIterable and filter by instanceof Entrypoint instead

检查以后发现原因是extract-text-webpack-plugin默认安装的版本是3.0.2,还不支持webpack的4.x版本。其实在初始安装时就有告警提示,只是被忽略了:

在这里插入图片描述

接下来看一下extract-text-webpack-plugin有没有方案来解决这个版本配套问题,百度以后了解到有extract-text-webpack-plugin有一个4.0的beta版本支持webpack4.x,把前面安装的extract-text-webpack-plugin的3.0.2版本卸载, 重新安装这个beta版本,安装命令如下:

sudo npm install --save-dev extract-text-webpack-plugin@next

此时可以正常构建了,也完成了第一个诉求——合并css,接下来是为css生成hash。

webpack配置文件的最后一部分更新为:

new extractTextPlugin({
    filename: 'focus.index.[contenthash:8].css'
})

但是构建时会报如下错误:

Error: Path variable [contenthash:8] not implemented in this context: focus.index.[contenthash:8].css

报错截图如下:

要用extract-text-webpack-plugin加hash看来是无解了,只能看看还有没有其他插件可以替代extract-text-webpack-plugin,又百度了一发,了解到可以用mini-css-extract-plugin替代extract-text-webpack-plugin,安装命令如下:

sudo npm install mini-css-extract-plugin

webpack配置文件更新如下(之前使用extract-text-webpack-plugin的部分已经注释):

const path = require("path");
const htmlWebpackPlugin = require('html-webpack-plugin');
const cleanWebpackPlugin = require('clean-webpack-plugin');
// const extractTextPlugin = require('extract-text-webpack-plugin');
const miniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
    entry: "./js/main.js",
    output: {
        path: path.resolve(__dirname, "build"),
        publicPath: "/build/",
        filename: "index.[chunkhash:8].js"
    },
    module: {
        rules: [
            {
                test: /.js$/ ,
                loader: 'babel-loader',
                exclude: /node_modules/
            },
            {
                test: /.css$/,
                // use: extractTextPlugin.extract({
                //     fallback: 'style-loader',
                //     use: [
                //         {
                //             loader: 'css-loader',
                //             options: {
                //                 url: false
                //             }
                //         }
                //     ]
                // })
                use: [
                    miniCssExtractPlugin.loader,
                    {
                        loader: 'css-loader',
                        options: {
                            url: false
                        }
                    }
                ]
            }
        ]
    },
    devtool: 'inline-source-map',
    mode: 'development',
    plugins: [
        new htmlWebpackPlugin({
            filename: '../index.html',
            template: 'html/index.html',
            inject: 'body'
        }),
        new htmlWebpackPlugin({
            filename: '../login.html',
            template: 'html/login.html',
            inject: 'body'
        }),
        new htmlWebpackPlugin({
            filename: '../mail.html',
            template: 'html/mail.html',
            inject: 'body'
        }),
        new htmlWebpackPlugin({
            filename: '../pinboard_copy_link.html',
            template: 'html/pinboard_copy_link.html',
            inject: 'body'
        }),
        new cleanWebpackPlugin(['build']),
        // new extractTextPlugin({
        //     filename: 'focus.index.[contenthash:8].css'
        // })
        new miniCssExtractPlugin({
            filename: 'focus.index.[contenthash:8].css'
        })
    ]
};

最后终于构建成功了

最后总结一下:

  1. 如果当前项目是webpack3.x版本,使用extract-text-webpack-plugin;
  2. 如果当前项目是webpack4.x版本(但已有extract-text-webpack-plugin配置),可以继续用extract-text-webpack-plugin,但必须用对应的beta版本,且这个beta版本不支持生成hash;
  3. 如果当前项目是webpack4.x版本且是新项目,使用mini-css-extract-plugin。
原文地址:https://www.cnblogs.com/baidei/p/13581890.html