解决esbuild无法打包KotlinJS生成的ES模块hiom的问题
解决esbuild打包KotlinJS生成的ES模块hiom的兼容问题
问题根源
KotlinJS通过useEsModules()生成的ESM输出中,可能混合了ESM语法与CommonJS风格的动态require调用,导致esbuild处理时出现识别冲突:既无法将其作为纯ESM打包(触发external要求),标记external后运行时又因环境不支持动态require报错。
可行解决方案
方案1:注入shim兼容动态require
通过esbuild的inject功能,为运行环境添加一个兼容ESM的require模拟,让hiom中的动态require调用转为合法的import():
- 创建
require-shim.js文件:
window.require = async (modulePath) => { const module = await import(modulePath); return module.default || module; };
- 修改esbuild配置:
module.exports = { entryPoints: ['src/index.js'], bundle: true, format: 'esm', outfile: 'dist/bundle.js', inject: ['./require-shim.js'], // 注入shim处理动态require external: [], // 不将hiom设为external resolveExtensions: ['.mjs', '.js'], // 优先识别KotlinJS的ESM文件 };
- 确保index.html用ESM方式加载打包文件:
<script type="module" src="dist/bundle.js"></script>
方案2:优化KotlinJS的ESM输出配置
调整KotlinJS的构建脚本,强制生成更纯净的ESM代码,避免动态require:
// build.gradle.kts kotlin { js(IR) { browser { commonWebpackConfig { configureWebpack { resolve.set("extensions", listOf(".mjs", ".js")) output.set("libraryTarget", "module") } } } binaries.executable() useEsModules() // 禁用CommonJS风格的模块生成 compilations.all { kotlinOptions { moduleKind = "es" } } } }
同时检查Kotlin代码,将所有kotlin.js.require调用替换为ESM的import()语法。
方案3:配置esbuild优先识别ESM入口
告诉esbuild优先读取hiom的ESM入口文件:
// esbuild.config.js module.exports = { entryPoints: ['src/index.js'], bundle: true, format: 'esm', outfile: 'dist/bundle.js', external: [], resolveExtensions: ['.mjs', '.js'], // 优先加载.mjs格式的ESM文件 mainFields: ['module', 'main'], // 优先读取package.json的module字段 };
如果hiom的package.json没有module字段,手动添加并指向其ESM入口文件(比如"module": "./kotlin/hiom.mjs")。
方案4:预转译hiom为纯净ESM
先用esbuild单独转译hiom,再纳入主项目打包:
- 执行转译命令:
esbuild node_modules/hiom/kotlin/my-project-applications-my-server.js --format=esm --outfile=node_modules/hiom/kotlin/my-project-applications-my-server-esm.mjs
- 在主项目配置中添加别名,指向转译后的文件:
module.exports = { entryPoints: ['src/index.js'], bundle: true, format: 'esm', outfile: 'dist/bundle.js', alias: { 'hiom/kotlin/my-project-applications-my-server': 'hiom/kotlin/my-project-applications-my-server-esm.mjs' }, external: [] };
验证注意事项
- 清理
node_modules和dist目录,重新构建避免缓存干扰 - 确保项目
package.json中已设置"type": "module"
内容的提问来源于stack exchange,提问作者Jan Vladimir Mostert
相关产品推荐
相关产品推荐

