首页 > 解决方案 > 将 style[hash].css 拆分为动态加载的块

问题描述

由于生成的输出的大小,我正在尝试将样式代码拆分为更小的块。我正在使用开发,react所以我解决了 javascript 加载React.lazy()

假设有一个大型应用程序,您可以打开 50 个不同的视图。并非所有视图都可供所有用户使用。

我在路由器中所做的是:

...
const view = React.lazy(() => import("./views/view"));
...

...
<view />
...

这样做的目的是将整个应用程序划分为 50 个js动态加载的独立文件,这很好。

然而,它并没有以同样的方式划分风格。因此,让我们看看其中一种观点:

import React, { Component } from "react";
import "../../scss/view.scss";

class view extends Component {
    ...
}

export default view;

因此,每个视图都有自己的scss专用于该视图的文件,这使得它们几乎是独立的。问题是 webpack 仍然只生成一个大style[hash].css文件。

网络包配置:

const HtmlWebPackPlugin = require("html-webpack-plugin");
const ExtractTextPlugin = require("extract-text-webpack-plugin");

const htmlPlugin = new HtmlWebPackPlugin({
    template: "./src/index.html",
    filename: "index.html"
});

const extractTextPlugin = new ExtractTextPlugin({
    filename: "css/style.[hash:8].css",
    allChunks: true
});

module.exports = {
    output: {
        filename: "js/main.[hash:8].js"
    },
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: "babel-loader"
            },
            {
                test: /\.(png|jpg|gif|ico|svg|eot|ttf|woff|woff2)$/,
                loader: "url-loader",
                options: {
                    limit: 25000,
                    outputPath: "/assets/",
                    name: "[name].[hash:8].[ext]"
                }
            },
            {
                test: /\.(scss|sass|css)$/i,
                use: ExtractTextPlugin.extract({
                    fallback: "style-loader",
                    use: [
                        { loader: "css-loader" },
                        { loader: "postcss-loader", options: { sourceMap: true } },
                        { loader: "sass-loader", options: { sourceMap: true } }
                    ]
                })
            }
        ]
    },
    resolve: {
        extensions: [".js", ".jsx", ".json"]
    },
    plugins: [htmlPlugin, extractTextPlugin],
    devServer: {
        historyApiFallback: {
            rewrites: [{ from: /^\/$/, to: "/index.html" }]
        }
    }
};

有什么方法可以使样式也根据它们的 js 文件动态生成和加载,例如,如果我打开视图 10,它会加载10.main[hash].js和加载10.style[hash].css

标签: javascriptreactjswebpacksasslazy-loading

解决方案


这个问题的答案是替换extract-text-webpack-plugin实际上缺少此功能的已弃用包(将样式拆分为相应的块)。

相反mini-css-extract-plugin应该使用它,它会自动工作。

更新的工作webpack配置文件:

const HtmlWebPackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

const htmlPlugin = new HtmlWebPackPlugin({
    template: "./src/index.html",
    filename: "index.html",
});

const miniCssExtractPlugin = new MiniCssExtractPlugin({
    filename: "css/style.[hash:8].css",
    chunkFilename: "css/[id].style.[hash:8].css",
});

module.exports = {
    output: {
        filename: "js/main.[hash:8].js",
    },
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: "babel-loader",
            },
            {
                test: /\.(png|jpg|jpeg|gif|ico|svg|eot|ttf|woff|woff2)$/,
                loader: "url-loader",
                options: {
                    limit: 25000,
                    outputPath: "/assets/",
                    name: "[name].[hash:8].[ext]",
                },
            },
            {
                test: /\.(scss|sass|css)$/i,
                use: [
                    MiniCssExtractPlugin.loader,
                    "css-loader",
                    "postcss-loader",
                    "sass-loader",
                ],
            },
        ],
    },
    resolve: {
        extensions: [".js", ".jsx", ".json"],
    },
    plugins: [htmlPlugin, miniCssExtractPlugin],
    devServer: {
        historyApiFallback: {
            rewrites: [{ from: /^\/$/, to: "/index.html" }],
        },
    },
};

推荐阅读