简体   繁体   English

想将 webpack 到 output 分开。css 文件而不是合并为一个

[英]Would like webpack to output to separate .css files instead of combining into one

I am using MiniCssExtractPlugin and also have chunks specified for optimization:我正在使用MiniCssExtractPlugin并且还指定了用于优化的块:

splitChunks: {
            cacheGroups: {
                styles: {
                    name: 'styles',
                    test: /\.css$/,
                    chunks: 'all',
                    enforce: true,
                },
            },
        },

I believe the chunks causes my two ink CSS to be combined into a styles.[hash].css file after the dev or prod build:我相信这些块会导致我的两个墨水 CSS 在开发或产品构建后组合成 styles.[hash].css 文件:

import '../../ext/ink-3.1.10/css/ink.min.css';
import '../../ext/ink-3.1.10/css/ink-flex.min.css';

index.tsx索引.tsx

import { render } from 'react-dom';
import React from 'react';
import { Provider } from 'react-redux';
import App from './App';
import '../../ext/ink-3.1.10/css/ink.min.css';
import '../../ext/ink-3.1.10/css/ink-flex.min.css';
import './less/master.less';
import store from './store';
import { BrowserRouter as Router } from 'react-router-dom';

const globalAny: any = global;
globalAny.__base = `${__dirname}/`;


render(
    <Provider store={store}>
        <Router>
            <App />
        </Router>
    </Provider>,

    document.getElementById('app')
);

But I don't want the ink files to be combined.但我不希望合并ink文件。 But if I take chunks out, then my build no longer includes the two ink css files:但是如果我取出块,那么我的构建将不再包括两个墨水 css 文件:

If I leave optimization chunks in, then it's combining those two ink files into a styles.[hash].css and doing so causing weird style issues when I run the site.如果我留下优化块,那么它将这两个墨迹文件组合成一个 styles.[hash].css 并且这样做会在我运行该站点时导致奇怪的样式问题。

I'm new to webpack so don't assume I know completely what I'm doing 100% yet.我是 webpack 的新手,所以不要假设我完全知道我在做什么 100%。

How can I change this to output two separate css files for those ink files?对于这些墨水文件,如何将其更改为 output 两个单独的 css 文件?

webpack.config.js webpack.config.js

const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const TerserJSPlugin = require('terser-webpack-plugin');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CopyPlugin = require('copy-webpack-plugin');

const isProduction = process.env.NODE_ENV === 'production';

const html = () =>
    new HtmlWebPackPlugin({
        template: path.resolve(__dirname, 'src/client', 'index.html'),
        filename: 'index.html',
        hash: true,
    });

const copyAllOtherDistFiles = () =>
    new CopyPlugin({
        patterns: [
            { from: 'src/client/assets', to: 'lib/assets' },
            { from: 'package.json', to: './' },
            { from: 'ext/ink-3.1.10/js/ink-all.min.js', to: 'lib/js' },
            { from: 'ext/ink-3.1.10/js/autoload.min.js', to: 'lib/js' },
            { from: 'ext/js/jquery-2.2.3.min.js', to: 'lib/js' },
            { from: 'feed.xml', to: './' },
        ],
    });

module.exports = {
    entry: './src/client/index.tsx',
    output: {
        filename: 'scripts/app.[hash].bundle.js',
        publicPath: '/',
        path: path.resolve(__dirname, 'dist'),
    },
    resolve: {
        extensions: ['.ts', '.tsx', '.js'],
    },
    devtool: 'source-map',
    devServer: {
        open: true,
        writeToDisk: false,
        publicPath: '/',
        compress: true,
        historyApiFallback: {
            index: '/',
        },
        stats: 'errors-only',
        proxy: {
            '/api': {
                target: 'http://localhost:3000',
                secure: false,
                changeOrigin: true,
                logLevel: 'debug',
            },
        },
    },
    optimization: {
        minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
        splitChunks: {
            cacheGroups: {
                styles: {
                    name: 'styles',
                    test: /\.css$/,
                    chunks: 'all',
                    enforce: true,
                },
            },
        },
    },
    module: {
        rules: [
            {
                test: /\.(js)$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                },
            },
            {
                test: /\.(tsx|ts)?$/,
                use: 'ts-loader',
                exclude: /node_modules/,
            },
            {
                test: /\.html$/,
                use: [
                    {
                        loader: 'html-loader',
                    },
                ],
            },
            {
                test: /\.less$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader'],
            },
            {
                test: /\.css$/,
                use: [
                    {
                        loader: MiniCssExtractPlugin.loader,
                        options: {
                            publicPath: '../../',
                        },
                    },
                    'css-loader',
                ],
            },
            {
                test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
                loader: 'url-loader?limit=10000&mimetype=application/font-woff',
            },
            {
                test: /\.(png|svg|jpg|gif)$/,
                use: ['url-loader'],
            },
        ],
    },
    plugins: isProduction
        ? [
                new CleanWebpackPlugin(),
                copyAllOtherDistFiles(),
                new MiniCssExtractPlugin({
                    filename: 'lib/css/[name].[hash].css',
                }),
                html(),
          ]
        : [
                copyAllOtherDistFiles(),
                new MiniCssExtractPlugin({
                    filename: 'lib/css/[name].[hash].css',
                }),
                html(),
          ],
};

UPDATE:更新:

Only thing now is that:现在唯一的事情是:

  1. Also the ink css files to be in the root of lib/css ?墨水 css 文件也位于lib/cssroot中? It looks like it's putting it into my __dirname and into ext for some reason still instead of next to the lib\css next to my main css.看起来它出于某种原因仍将其放入我的__dirname和 ext 中,而不是在我的main css 旁边的lib\css旁边。

  2. it seems like I'm getting dups of the ink css created?好像我得到了创建的墨水 css 的副本? It's in a and in and in the script looks like it's appended to the app bundle as part of the path?它在 a 和 in 中,并且在脚本中看起来像是作为路径的一部分附加到应用程序包? seems weird看起来很奇怪

  3. I need there to be 2 ink files generated and included in the index.html .我需要生成 2 个墨水文件并将其包含在index.html中。 It's combining those two ink css files ( ink and ink flex) into one ink css file.它将这两种墨水 css 文件( ink和墨水柔性)组合成一个ink css 文件。 That causes problems for me.这给我带来了问题。 Looks like the chunking logic isn't creating separate files yet still for the files I included in index.tsx ?看起来分块逻辑还没有为我包含在index.tsx中的文件创建单独的文件?

webpack.config.js webpack.config.js

const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const TerserJSPlugin = require('terser-webpack-plugin');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CopyPlugin = require('copy-webpack-plugin');

const isProduction = process.env.NODE_ENV === 'production';

const html = () =>
    new HtmlWebPackPlugin({
        template: path.resolve(__dirname, 'src/client', 'index.html'),
        filename: 'index.html',
        hash: true,
    });

const copyAllOtherDistFiles = () =>
    new CopyPlugin({
        patterns: [
            { from: 'src/client/assets', to: 'lib/assets' },
            { from: 'package.json', to: './' },
            { from: 'ext/ink-3.1.10/js/ink-all.min.js', to: 'lib/js' },
            { from: 'ext/ink-3.1.10/js/autoload.min.js', to: 'lib/js' },
            { from: 'ext/js/jquery-2.2.3.min.js', to: 'lib/js' },
            { from: 'feed.xml', to: './' },
        ],
    });

module.exports = {
    entry: './src/client/index.tsx',
    output: {
        filename: 'scripts/app.[hash].bundle.js',
        publicPath: '/',
        path: path.resolve(__dirname, 'dist'),
    },
    resolve: {
        extensions: ['.ts', '.tsx', '.js'],
    },
    devtool: 'source-map',
    devServer: {
        open: true,
        writeToDisk: false,
        publicPath: '/',
        compress: true,
        historyApiFallback: {
            index: '/',
        },
        stats: 'errors-only',
        proxy: {
            '/api': {
                target: 'http://localhost:3000',
                secure: false,
                changeOrigin: true,
                logLevel: 'debug',
            },
        },
    },
    optimization: {
        minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
        splitChunks: {
            cacheGroups: {
                styles: {
                    name(module) {
                        const match = module.context.match(/[\\/](.*).css/);

                        if (!match) {
                            return false;
                        }

                        const moduleName = match[1];

                        return moduleName;
                    },
                    test: /\.css$/,
                    chunks: 'all',
                    enforce: true,
                },
            },
        },
    },
    module: {
        rules: [
            {
                test: /\.(js)$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                },
            },
            {
                test: /\.(tsx|ts)?$/,
                use: 'ts-loader',
                exclude: /node_modules/,
            },
            {
                test: /\.html$/,
                use: [
                    {
                        loader: 'html-loader',
                    },
                ],
            },
            {
                test: /\.less$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader'],
            },
            {
                test: /\.css$/,
                use: [
                    {
                        loader: MiniCssExtractPlugin.loader,
                        options: {
                            publicPath: '../../',
                        },
                    },
                    'css-loader',
                ],
            },
            {
                test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
                loader: 'url-loader?limit=10000&mimetype=application/font-woff',
            },
            {
                test: /\.(png|svg|jpg|gif)$/,
                use: ['url-loader'],
            },
        ],
    },
    plugins: isProduction
        ? [
                new CleanWebpackPlugin(),
                copyAllOtherDistFiles(),
                new MiniCssExtractPlugin({
                    filename: 'lib/css/[name].[hash].css',
                }),
                html(),
          ]
        : [
                copyAllOtherDistFiles(),
                new MiniCssExtractPlugin({
                    filename: 'lib/css/[name].[hash].css',
                }),
                html(),
          ],
};

在此处输入图像描述 在此处输入图像描述

I console.log'd out the matches here to try to troubleshoot:我在这里 console.log'd 了匹配项以尝试排除故障:

[
  '/Users/xxxxx/code/other/projects/xxxxx/ext/ink-3.1.10/css',
  'Users/xxxxx/code/other/projects/xxxxx/ext/ink-3.1.10',
  index: 0,
  input: '/Users/xxxxx/code/other/projects/xxxxx/ext/ink-3.1.10/css',
  groups: undefined
]
match[1]: /Users/xxxxx/code/other/projects/xxxxx/src/client/ext/ink-3.1.10

[
  '/Users/xxxxx/code/other/projects/xxxxx/ext/ink-3.1.10/css',
  'Users/xxxxx/code/other/projects/xxxxx/ext/ink-3.1.10',
  index: 0,
  input: '/Users/xxxxx/code/other/projects/xxxxx/ext/ink-3.1.10/css',
  groups: undefined
]
match[1]: /Users/xxxxx/code/other/projects/xxxxx/src/client/ext/ink-3.1.10

[
  '/Users/xxxxx/code/other/projects/xxxxx/ext/ink-3.1.10/css',
  'Users/xxxxx/code/other/projects/xxxxx/ext/ink-3.1.10',
  index: 0,
  input: '/Users/xxxxx/code/other/projects/xxxxx/ext/ink-3.1.10/css',
  groups: undefined
]
match[1]: /Users/xxxxx/code/other/projects/xxxxx/src/client/ext/ink-3.1.10

[
  '/Users/xxxxx/code/other/projects/xxxxx/ext/ink-3.1.10/css',
  'Users/xxxxx/code/other/projects/xxxxx/ext/ink-3.1.10',
  index: 0,
  input: '/Users/xxxxx/code/other/projects/xxxxx/ext/ink-3.1.10/css',
  groups: undefined
]
match[1]: /Users/xxxxx/code/other/projects/xxxxx/src/client/ext/ink-3.1.10

Please try changing your cacheGroup name configuration:请尝试更改您的cacheGroup 名称配置:

splitChunks: {
   cacheGroups: {
      styles: {
          name(module) {
             const match = module.context.match(/[\\/](.*).css/);

             if (!match) {
                return false;
             }

             const moduleName = match[1];

             return moduleName;
          },
          test: /\.css$/,
          chunks: 'all',
          enforce: true,
       },
   },
},

By defining name: 'styles' you told webpack that every module that is imported and match /\.css$/ regex should be wrap together in one chunk named "styles".通过定义name: 'styles'您告诉 webpack 导入并匹配/\.css$/正则表达式的每个模块都应该包装在一个名为“styles”的块中。

the name property of cacheGroup can also be a function. cacheGroupname属性也可以是 function。 This function gets the module (object containing lots of data on a give file) and does the following:这个 function 获取模块(在给定文件中包含大量数据的对象)并执行以下操作:

  1. if false returned: - Doesn't add this module(file) to this chunk group.如果返回 false: - 不将此模块(文件)添加到此块组。
  2. if a string is returned - push this module(file) to a chunk with this name.如果返回字符串 - 将此模块(文件)推送到具有此名称的块中。

So from one cache group you could generate multiple chunks, depending on what you are returning for each file.因此,您可以从一个缓存组生成多个块,具体取决于您为每个文件返回的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM