将 style[hash].css 拆分为动态加载的块
split style[hash].css into dynamically loaded chunks
由于生成的输出的大小,我试图将样式代码拆分成更小的块。我正在使用 react
进行开发,所以我用 React.lazy()
.
解决了 javascript 加载问题
假设有一个大型应用程序可以打开 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
文件。
Webpack 配置:
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
?
此问题的答案是替换实际上缺少此功能(将样式拆分为相应块)的已弃用 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" }],
},
},
};
由于生成的输出的大小,我试图将样式代码拆分成更小的块。我正在使用 react
进行开发,所以我用 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
文件。
Webpack 配置:
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
?
此问题的答案是替换实际上缺少此功能(将样式拆分为相应块)的已弃用 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" }],
},
},
};