Webpack多入口场景下如何获取另一chunk带哈希的文件名作为环境变量
解决方案
方案1:纯webpack内置API实现(无额外依赖,推荐)
直接在webpack配置中增加一个极简的自定义插件即可,完全在webpack编译流程内完成占位符替换,无需后置处理脚本。
修改后的webpack.config.js如下:
const path = require('path') module.exports = () => ({ entry: { init: path.resolve(__dirname, 'init.js'), bundle: path.resolve(__dirname, 'bundle.js'), }, output: { filename: '[name].[contenthash].js', path: path.resolve(__dirname, 'dist'), }, plugins: [ { apply(compiler) { // 在webpack输出资产前执行替换逻辑 compiler.hooks.emit.tap('ReplaceBundleHashPlugin', (compilation) => { // 获取带hash的bundle文件名 const bundleFileName = compilation.namedChunks.get('bundle').files[0] // 获取init输出资产的内容 const initChunk = compilation.namedChunks.get('init') const initAsset = compilation.assets[initChunk.files[0]] let initContent = initAsset.source() // 替换占位符 initContent = initContent.replace('[GET_BUNDLE_FILENAME_WITH_HASH_HERE]', bundleFileName) // 更新init的输出资产 compilation.assets[initChunk.files[0]] = { source: () => initContent, size: () => Buffer.byteLength(initContent, 'utf8') } }) } } ] })
方案说明
- 插件执行时机为webpack的
emit钩子阶段,此时所有chunk的contenthash已经计算完成,文件名已确定 - 直接修改webpack内存中待输出的init.js内容,替换效果和sed后置处理完全一致,但无需额外执行脚本
- 不依赖任何动态导入特性,编译后的代码兼容性和原有代码完全相同
方案2:使用DefinePlugin + 资产清单插件(适合多入口多占位符场景)
如果后续有多个需要注入的hash文件名,可以先通过assets-webpack-plugin生成资产清单,再通过DefinePlugin全局注入变量:
- 安装依赖:
npm install assets-webpack-plugin --save-dev - 修改webpack配置:
const path = require('path') const AssetsPlugin = require('assets-webpack-plugin') const webpack = require('webpack') module.exports = () => ({ entry: { init: path.resolve(__dirname, 'init.js'), bundle: path.resolve(__dirname, 'bundle.js'), }, output: { filename: '[name].[contenthash].js', path: path.resolve(__dirname, 'dist'), }, plugins: [ new AssetsPlugin({ filename: 'assets.json', path: path.resolve(__dirname, 'dist'), includeManifest: false }), // 编译前读取已生成的资产清单注入全局变量,首次编译需先执行一次生成assets.json new webpack.DefinePlugin({ BUNDLE_FILENAME: JSON.stringify(require('./dist/assets.json').bundle.js) }) ] })
- 修改init.js中的占位符为注入的全局变量即可:
const bundleScriptElement = document.createElement('script') bundleScriptElement.src = 'http://example.com/' + BUNDLE_FILENAME document.head.append(bundleScriptElement)
内容的提问来源于stack exchange,提问作者kolurbo
相关产品推荐
相关产品推荐

