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

为服务端EJS项目配置Webpack:动态插入构建资源

解决方案:动态在EJS中注入Webpack打包资源标签

嘿,我来帮你搞定这个Webpack和EJS的资源注入问题!你提到要用webpack-middleware,这个思路完全正确,接下来我一步步给你讲怎么配置,保证能动态插入打包后的JS和CSS标签。

第一步:安装所需依赖

首先得把必要的工具包装上,打开终端跑这个命令:

npm install webpack-dev-middleware webpack-hot-middleware express --save-dev

(如果你的项目已经用了Express,可以跳过express的安装)

第二步:调整Webpack配置

修改你的webpack.config.js,重点添加publicPath(确保浏览器能正确找到打包后的资源),以及开发环境的热更新支持(可选但能提升开发体验):

import path from 'path';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import CleanWebpackPlugin from 'clean-webpack-plugin';
import webpack from 'webpack';

const inProduction = process.argv[process.argv.length - 1]
 .match(/[a-z]+$/g)[0] === 'production';

const basic = {
 entry: {
 app: path.join(__dirname, 'frontend/source/scripts/main.js'),
 },
 output: {
 path: path.join(__dirname, 'frontend/build'),
 filename: '[name].[chunkhash].js',
 // 关键:设置publicPath,让浏览器知道资源的基础路径
 publicPath: '/frontend/build/'
 },
};

const module = {
 rules: [{
 test: /\.css$/,
 use: ExtractTextPlugin.extract({
 use: ['css-loader'],
 }),
 }, {
 test: /\.js$/,
 use: ['babel-loader'],
 exclude: ['/node_modules'],
 }, ],
};

const plugins = [
 new ExtractTextPlugin('[name].[contenthash].css'),
 new CleanWebpackPlugin('build'),
];

// 开发环境添加热更新插件,修改入口
if (!inProduction) {
 plugins.push(new webpack.HotModuleReplacementPlugin());
 basic.entry.app = ['webpack-hot-middleware/client?reload=true', basic.entry.app];
}

export default { ...basic, module, plugins };

第三步:配置Express服务器(核心逻辑)

创建一个server.js文件,把Webpack中间件集成进去,这样就能实时获取打包后的资源信息,然后传给EJS模板:

import express from 'express';
import webpack from 'webpack';
import webpackDevMiddleware from 'webpack-dev-middleware';
import webpackHotMiddleware from 'webpack-hot-middleware';
import webpackConfig from './webpack.config.js';
import path from 'path';

const app = express();
const compiler = webpack(webpackConfig);

// 配置Webpack Dev Middleware,负责编译和提供静态资源
app.use(webpackDevMiddleware(compiler, {
 publicPath: webpackConfig.output.publicPath,
 stats: { colors: true } // 控制台输出彩色日志,方便调试
}));

// 开发环境启用热更新,代码变动自动刷新浏览器
if (!inProduction) {
 app.use(webpackHotMiddleware(compiler));
}

// 设置EJS为模板引擎,指定EJS文件所在目录(根据你的实际路径调整)
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, './')); // 假设你的index.ejs在项目根目录,按需修改

// 处理路由,渲染index.ejs
app.get('*', (req, res) => {
 // 获取Webpack编译后的资源统计信息
 const stats = compiler.getStats().toJson();
 // 从stats里提取JS和CSS文件路径(兼容单文件和数组格式)
 const assets = {
 js: Array.isArray(stats.assetsByChunkName.app) 
 ? stats.assetsByChunkName.app.filter(asset => asset.endsWith('.js'))
 : [stats.assetsByChunkName.app].filter(asset => asset.endsWith('.js')),
 css: Array.isArray(stats.assetsByChunkName.app)
 ? stats.assetsByChunkName.app.filter(asset => asset.endsWith('.css'))
 : [stats.assetsByChunkName.app].filter(asset => asset.endsWith('.css'))
 };

 // 渲染EJS模板,把assets和你原本需要的变量(branches、commits等)传进去
 res.render('index', { assets, branches: req.branches, commits: req.commits, files: req.files, file: req.file });
});

// 启动服务器
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
 console.log(`服务器跑在端口 ${PORT} 啦!`);
});

第四步:修改index.ejs动态插入标签

最后更新你的index.ejs,利用传过来的assets变量生成对应的<link>和<script>标签:

<header class="header">Git Rendering</header>

<!-- 动态插入CSS样式 -->
<% if (assets && assets.css.length) { %>
 <% assets.css.forEach(cssFile => { %>
 <link rel="stylesheet" href="<%= '/frontend/build/' %><%= cssFile %>">
 <% }) %>
<% } %>

<main class="container">
 <% if (branches) { %>
 <%- include('branches'); %>
 <% } %>
 <% if (commits) { %>
 <%- include('commits'); %>
 <% } %>
 <% if (files) { %>
 <%- include('files'); %>
 <% } %>
 <% if (file) { %>
 <%- include('file'); %>
 <% } %>
</main>

<!-- 动态插入JS脚本 -->
<% if (assets && assets.js.length) { %>
 <% assets.js.forEach(jsFile => { %>
 <script src="<%= '/frontend/build/' %><%= jsFile %>"></script>
 <% }) %>
<% } %>

额外提示

  • 如果你的EJS文件不在根目录,记得修改app.set('views', ...)的路径为实际存放EJS的文件夹。
  • 生产环境下,你可以预先执行webpack --json > stats.json生成静态的资源统计文件,然后在服务器启动时读取这个文件,不用实时编译,性能会更好。
  • 如果后续要把资源部署到CDN,只需要修改Webpack的publicPath为CDN地址即可,EJS里的标签会自动用新路径。

内容的提问来源于stack exchange,提问作者Rami Chasygov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:56:39