webpack mini-css-extract-plugin => 在单个条目上输出多个 css 文件

Posted

技术标签:

【中文标题】webpack mini-css-extract-plugin => 在单个条目上输出多个 css 文件【英文标题】:webpack mini-css-extract-plugin => output multiple css-files on single entry 【发布时间】:2019-09-04 17:17:45 【问题描述】:

如何为我的古腾堡块设置 webpack 以提取多个 css 文件并根据样式表的名称捆绑这些文件。

Zack Gordon 在 webpack 3 中使用了 Extract Text Plugin,这非常有效。但是对于 webpack 4,我不得不切换到 mini-css-extract-plugin,我无法再让它工作了。

在下面查看我当前的设置,这样你就可以看到我正在尝试做什么。

这是我的项目文件夹:

Plugin folder
|-- [src]
|   |-- [block1]
|   |   |-- block1.js
|   |   |-- style.scss
|   |   `-- editor.scss
|   |-- [block2]
|   |   |-- block2.js
|   |   |-- style.scss
|   |   `-- editor.scss
|   `-- index.js
`-- [build]
    |-- index.js
    |-- style.build.css
    `-- editor.build.css

在block1.js/block2.js中:

import './style.scss'
import './editor.scss'

在 index.js 中:

import './block1'
import './block2'

在 webpack.config.js 中:

const defaultConfig = require("./node_modules/@wordpress/scripts/config/webpack.config");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = 
    ...defaultConfig,
    optimization: 
        ...defaultConfig.optimization,
        splitChunks: 
            cacheGroups: 
                style: 
                    name: 'style',
                    test: /style\.s?css$/,
                    chunks: 'all',
                    enforce: true,
                ,
                editor: 
                    name: 'editor',
                    test: /editor\.s?css$/,
                    chunks: 'all',
                    enforce: true,
                ,
            ,
        ,
    ,
    plugins: [
        ...defaultConfig.plugins,
        new MiniCssExtractPlugin(
            filename: 'blocks.[name].build.css'
            ),
    ],
    module: 
        ...defaultConfig.module,
        rules: [
            ...defaultConfig.module.rules,
            
                test: /\.s?css$/,
                exclude: /node_modules/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'postcss-loader',
                    'sass-loader'
                ],
            ,

        ]
    ,
;

预期输出:

[build]
|-- blocks.editor.build.css
|-- index.js
|-- blocks.style.build.css

当前输出:

[build]
|-- blocks.editor.build.css
|-- editor.js
|-- index.js
|-- blocks.style.build.css
|-- style.js
`-- (...and indentical map files)

当前设置会产生两个我不需要的额外 js 文件(style.js/editor.js),但最大的问题是它还会导致块无法在 Wordpress 中加载。当我不使用 splitChunks 时它会加载,但是所有 css 都捆绑在一个文件中......我需要两个。

比较: 没有 splitChunks 的 index.js:

/******/    // Load entry module and return exports
/******/    return __webpack_require__(__webpack_require__.s = "./src/index.js");
/******/ )

带有 splitChunks 的 index.js:

/******/    // add entry module to deferred list
/******/    deferredModules.push(["./src/index.js","editor","style"]);
/******/    // run deferred modules when ready
/******/    return checkDeferredModules();
/******/ )

【问题讨论】:

SplitChunks 优化似乎增加了某种依赖(延迟列表),因此捆绑的 index.js 是无用的。无论如何,幸运的是我找到了绕过这个问题的方法,通过在 src 文件夹中为 css 文件添加一个额外的单独入口点:css.js。这个额外的入口点处理块文件夹中 css 文件的导入。我从块文件夹中的 index.js 文件中删除了 css 导入。这再次向构建文件夹(css.js)添加了额外的无用文件,但我可以忽略它。也许这不是正确的方法,但它现在对我有用。 我也有同样的问题。由于某种原因,block1.js 中的 import scss 不会运行,除非我删除了导入。大多数示例也使用提取 css 插件而不是迷你提取。 【参考方案1】:

查看我的评论,更改了我的设置,现在它可以工作了: (好吧,它不再是一个条目了,但是嘿 :-)

项目文件夹:

Plugin folder
|-- [src]
|   |-- [block1]
|   |   |-- block1.js
|   |   |-- style.scss
|   |   `-- editor.scss
|   |-- [block2]
|   |   |-- block2.js
|   |   |-- style.scss
|   |   `-- editor.scss
|   `-- index.js
|   `-- css.js
`-- [build]
    |-- index.js
    |-- style.build.css
    `-- editor.build.css

在 css.js 中:

import './block1/style.scss'
import './block1/editor.scss'
import './block2/style.scss'
import './block2/editor.scss'

在 webpack.config.js 中:

const defaultConfig = require("./node_modules/@wordpress/scripts/config/webpack.config");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = 
    ...defaultConfig,
    entry: 
        index: path.resolve( process.cwd(), 'src', 'index.js' ),
        css: path.resolve( process.cwd(), 'src', 'css.js' ),
    ,
    optimization: 
        ...defaultConfig.optimization,
        splitChunks: 
            cacheGroups: 
                style: 
                    name: 'style',
                    test: /style\.s?css$/,
                    chunks: 'all',
                    enforce: true,
                ,
                editor: 
                    name: 'editor',
                    test: /editor\.s?css$/,
                    chunks: 'all',
                    enforce: true,
                ,
            ,
        ,
    ,
    plugins: [
        ...defaultConfig.plugins,
        new MiniCssExtractPlugin(
            filename: 'blocks.[name].build.css'
            ),
    ],
    module: 
        ...defaultConfig.module,
        rules: [
            ...defaultConfig.module.rules,
            
                test: /\.s?css$/,
                exclude: /node_modules/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'postcss-loader',
                    'sass-loader'
                ],
            ,

        ]
    ,
;

输出构建文件夹:

[build]
|-- blocks.editor.build.css
|-- index.js
|-- blocks.style.build.css
|-- style.js (ignore)
|-- editor.js (ignore)
|-- css.js (ignore)
`-- (...and indentical map files)

【讨论】:

您可能需要查看ignore-emit-webpack-plugin 以阻止创建额外的 .js 文件。 I saw it used in this answer. 感谢您的评论,我在 github 中查找了该插件:看起来很有希望,我想我稍后会在项目完成时尝试一下。【参考方案2】:

您实际上不需要多个条目。使用当前解决方案中的配置,您只需要一个选项即可使其按您想要的方式工作。 filename 选项必须在块名称的基础上动态设置。

plugins: [
    new MiniCssExtractPlugin(
      filename: ( chunk ) => `$chunk.name.replace('/js/', '/css/').css`,
    )
],

这将为每个块创建一个.css 文件。由于您已经拥有styleeditor 块,它将创建style.css 和'editor.css',每个都在js 文件中导入相应的css 或scss。

查看documentations

它看起来像这样,唯一的添加是将 filename 更改为 MiniCssExtractPlugin 选项,并删除 css 条目。这应该可以。

module.exports = 
    ...defaultConfig,
    entry: 
        index: path.resolve( process.cwd(), 'src', 'index.js' ),
    ,
    optimization: 
        ...defaultConfig.optimization,
        splitChunks: 
            cacheGroups: 
                style: 
                    name: 'style',
                    test: /style\.s?css$/,
                    chunks: 'all',
                    enforce: true,
                ,
                editor: 
                    name: 'editor',
                    test: /editor\.s?css$/,
                    chunks: 'all',
                    enforce: true,
                ,
            ,
        ,
    ,
    plugins: [
        ...defaultConfig.plugins,
        new MiniCssExtractPlugin(
          filename: ( chunk ) => `$chunk.name.replace('/js/', '/css/').css`,
          // chunkFilename: "[name].css"
        )
    ],
    module: 
        ...defaultConfig.module,
        rules: [
            ...defaultConfig.module.rules,
            
                test: /\.s?css$/,
                exclude: /node_modules/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'postcss-loader',
                    'sass-loader'
                ],
            ,

        ]
    ,
;

【讨论】:

以上是关于webpack mini-css-extract-plugin => 在单个条目上输出多个 css 文件的主要内容,如果未能解决你的问题,请参考以下文章

Webpack:安装 webpack 和 webpack-cli 后运行 webpack 时仍然报错

安装webpack后还是提示webpack不是内部命令

【webpack】--config 的使用

# Webpack 学习Webpack 搭建 Vue项目

# Webpack 学习Webpack 搭建 Vue项目

Webpack教程: Webpack安装