Webpack多目录配置文件合并问题及Widget构建配置需求
Hey there, let's work through this Webpack setup for your Middleman widgets step by step. I'll build out a complete config that hits all your requirements: independent JS/CSS per widget, shared global config, and centralized widget-specific settings in the webpack-configurations directory.
完整Webpack配置代码
"use strict"; const path = require("path"); const fs = require("fs"); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const { CleanWebpackPlugin } = require("clean-webpack-plugin"); // 读取webpack-configurations目录下的所有Widget专属配置 const widgetConfigsDir = path.resolve(__dirname, "webpack-configurations"); const widgetConfigs = fs.readdirSync(widgetConfigsDir) .filter(file => file.endsWith(".js")) .reduce((acc, file) => { const widgetName = file.replace(".js", ""); acc[widgetName] = require(path.join(widgetConfigsDir, file)); return acc; }, {}); // 动态生成多入口配置:每个Widget对应一个打包入口 const entry = Object.keys(widgetConfigs).reduce((acc, widgetName) => { // 优先用配置文件里指定的入口, fallback到默认路径 acc[widgetName] = widgetConfigs[widgetName].entry || path.resolve(__dirname, `src/widgets/${widgetName}/index.js`); return acc; }, {}); module.exports = { mode: process.env.NODE_ENV || "development", entry: entry, output: { path: path.resolve(__dirname, "build/widgets"), filename: "[name].js", // 输出文件以Widget名称命名,保证独立性 publicPath: "/widgets/" }, module: { rules: [ // JS处理:支持ES6+,注入全局配置 { test: /\.js$/, exclude: /node_modules/, use: { loader: "babel-loader", options: { presets: ["@babel/preset-env"], plugins: [ ["@babel/plugin-transform-runtime"], // 把全局配置注入到所有Widget代码中 ["babel-plugin-transform-define", { "process.env.GLOBAL_APP_CONFIG": JSON.stringify(require("./global-config.js")) }] ] } } }, // CSS处理:每个Widget输出独立的CSS文件 { test: /\.css$/, use: [ MiniCssExtractPlugin.loader, "css-loader", "postcss-loader" // 可选:处理自动前缀、样式兼容 ] }, // SCSS/SASS支持(如果你的Widget用预处理器) { test: /\.s[ac]ss$/i, use: [ MiniCssExtractPlugin.loader, "css-loader", "sass-loader" ] } ] }, plugins: [ // 打包前清理旧的输出文件 new CleanWebpackPlugin(), // 输出与Widget同名的独立CSS文件 new MiniCssExtractPlugin({ filename: "[name].css" }) ], optimization: { // 提取多Widget共享的依赖到单独文件,减少重复打包 splitChunks: { chunks: "all", name: "shared" // 共享代码会打包成shared.js和shared.css } } };
关键细节解释
1. 集中管理Widget专属配置
在webpack-configurations目录下,每个Widget对应一个.js配置文件,比如webpack-configurations/hero-slider.js:
module.exports = { entry: path.resolve(__dirname, "../src/widgets/hero-slider/main.js"), // 还可以添加该Widget专属的babel插件、loader规则等 };
Webpack会自动读取这些文件,动态生成入口,不用手动修改主配置。
2. 全局配置共享
通过babel-plugin-transform-define,你可以把全局配置(比如API地址、环境变量)注入到所有Widget的代码中,在Widget里直接用process.env.GLOBAL_APP_CONFIG访问即可,不用每个Widget单独导入。
3. 独立输出文件
每个Widget的JS和CSS都会以自身名称命名(比如hero-slider.js、hero-slider.css),完全独立,不会互相干扰。共享的依赖会被提取到shared.js和shared.css,优化加载体积。
4. Middleman集成
把Webpack的输出目录build/widgets配置到Middleman的config.rb:
set :js_dir, "build/widgets" set :css_dir, "build/widgets"
然后在Middleman模板中引用对应Widget的资源:
<%= javascript_include_tag "hero-slider" %> <%= stylesheet_link_tag "hero-slider" %>
额外优化建议
- 开发环境添加
webpack-dev-server实现热重载,修改代码实时刷新。 - 生产环境开启
TerserPlugin压缩JS、CssMinimizerPlugin压缩CSS,减小文件体积。 - 给特定Widget添加专属loader规则,比如某个Widget需要处理SVG或字体文件。
内容的提问来源于stack exchange,提问作者Chris Hough

