闽公网安备 35020302035485号
const path = require("path");
const glob = require("glob");
const toObject = require("./scripts/toObject");
const { VueLoaderPlugin } = require("vue-loader");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const FixStyleOnlyEntriesPlugin = require("webpack-fix-style-only-entries");
module.exports = (env, options) => {
const jsSetting = {
mode: "production",
entry: {
index: path.resolve(__dirname, "src/js/entry/index.js"),
},
output: {
path: path.resolve(__dirname, "apps/statics/dist/"),
filename: "js/[name].js",
},
target: ["web", "es5"],
module: {
rules: [
{
test: /.m?js$/,
include: path.resolve(__dirname, "src"),
exclude: /(node_modules|bower_components)/,
use: [
{
loader: "babel-loader",
options: {
plugins: ["@babel/plugin-transform-runtime"],
},
},
],
},
{
test: /.vue$/,
use: ["vue-loader"],
},
{
test: /.s?css$/i,
use: ["vue-style-loader", "css-loader", "sass-loader"],
},
{
test: /\.(png|jpe?g|gif|svg)$/i,
use: [
{
loader: "url-loader",
options: {
name: "[path][name].[ext]",
context: "src",
fallback: require.resolve("file-loader"),
limit: 8192,
},
},
],
},
{
test: /\.(woff|woff2|eot|ttf|otf|)$/,
use: [
{
loader: "file-loader",
options: {
name: "[path][name].[ext]",
context: "src",
},
},
],
},
],
},
plugins: [
new VueLoaderPlugin(),
new MiniCssExtractPlugin({
filename: "style/[name].css",
}),
new CleanWebpackPlugin({ verbose: true }),
],
resolve: {
alias: {
src: path.resolve(__dirname, "src/"),
apps: path.resolve(__dirname, "apps/"),
},
},
externals: {
vue: "Vue",
axios: "axios",
jquery: "jQuery",
},
},
const cssSetting = {
mode: "production",
entry: {
...toObject(glob.sync("apps/statics/scss/*/.scss")),
},
output: {
path: path.resolve(__dirname, ""),
},
module: {
rules: [
{
test: /.s?css$/i,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: { url: false },
},
"postcss-loader",
{
loader: "sass-loader",
options: {
implementation: require("sass"),
sassOptions: {
outputStyle: "expanded",
},
},
},
],
},
],
},
plugins: [new FixStyleOnlyEntriesPlugin(), new MiniCssExtractPlugin({})],
resolve: {
alias: {
src: path.resolve(__dirname, "src/"),
apps: path.resolve(__dirname, "apps/"),
},
},
},
if (options.mode == "development") {
jsSetting.devtool = "eval-source-map";
}
return [cssSetting, jsSetting];
};
为了简化内容,我已经移除了大部分的 entry 文件,并仅保留了说明所需的必要部分。在我们的项目中,我们首先构建 CSS,然后是 JavaScript。对于 css 文件,我们使用了一个名为 glob 的库来检测所有的.scss 文件。toObject 是一个自定义函数,用于生成如下的键值对:{
"apps/statics/scss/index": "apps/statics/scss/index.scss",
// ...
}
所以基本上,这些就是我们项目所需的内容:const path = require("path");
const glob = require("glob");
const toObject = require("./scripts/toObject");
const { VueLoaderPlugin } = require("vue-loader");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const PreventOutputJSPlugin = require("./scripts/PreventOutputJSPlugin");
module.exports = (env, options) => {
const isProd = options.mode === "production";
const cssSetting = {
mode: "development",
context: __dirname,
devtool: false,
entry: {
...toObject(glob.sync("apps/statics/scss/**/*.scss")),
},
output: {
path: path.resolve(__dirname, ""),
},
module: {
rules: [
{
test: /\\.scss$/,
use: ["postcss-loader", "sass-loader"],
type: "css",
},
],
},
plugins: [new PreventOutputJSPlugin()],
resolve: {
alias: {
src: path.resolve(__dirname, "src/"),
apps: path.resolve(__dirname, "apps/"),
},
},
optimization: {
minimize: false,
},
};
const jsSetting = {
context: __dirname,
devtool: false,
entry: {
index: path.resolve(__dirname, "src/js/entry/index.js"),
},
output: {
path: path.resolve(__dirname, "apps/statics/dist/"),
filename: "js/[name].js",
},
target: ["web", "es5"],
module: {
rules: [
{
test: /\\.vue$/,
loader: "vue-loader",
options: {
experimentalInlineMatchResource: true,
},
},
{
test: /\\.scss$/,
use: [
{
loader: "style-loader",
options: { esModule: false },
},
"css-loader",
"postcss-loader",
"sass-loader",
],
type: "javascript/auto",
},
{
test: /\\.css$/,
use: [
{
loader: "style-loader",
options: { esModule: false },
},
"css-loader",
],
type: "javascript/auto",
},
{
test: /\\.(png|jpe?g|gif|svg)$/i,
type: "asset/inline",
},
{
test: /\\.(woff|woff2|eot|ttf|otf|)$/,
type: "asset/resource",
},
],
},
plugins: [new VueLoaderPlugin()],
resolve: {
alias: {
src: path.resolve(__dirname, "src/"),
apps: path.resolve(__dirname, "apps/"),
node_modules: path.resolve(__dirname, "node_modules/"),
},
},
externals: {
vue: "Vue",
axios: "axios",
jquery: "jQuery",
},
optimization: {
minimize: isProd,
},
};
if (isProd) {
jsSetting.plugins.push(new CleanWebpackPlugin({ verbose: true }));
}
return [cssSetting, jsSetting];
};
对于 CSS 文件,我们不需要 css-loader 或 MiniCssExtractPlugin 来构建.scss。对于 JavaScript 文件,大多数配置与之前相同。我们的项目大约有 40 个 JavaScript 文件和 90 个 CSS 文件需要构建,让我们看看构建性能:
开发服务器热构建时间:约 300 毫秒
{
loader: 'css-loader',
options: { url: false }
}
而当前版本的 Rspack(v0.2.9)还不支持这一点。尽管它的构建速度仍然比 Webpack 快得多,但它也会在我们的终端上留下大量错误信息。在与我的团队成员讨论后,我们决定现在不替换它。我已经将其作为功能请求报告给 Rspack 的 Github 问题,并希望这个功能能尽快实现。