You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Webpack多目录配置文件合并问题及Widget构建配置需求

解决Middleman Widgets的Webpack配置问题

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:36:13