如何用tsify生成完整bundle?AMD/UMD打包异常问题咨询
解决AMD/UMD打包差异、浏览器报错及完整Bundle生成问题
我来帮你拆解并解决这些打包相关的问题,一步步来:
1. 为什么AMD只打包main.ts,UMD却包含所有依赖?
这俩模式的默认打包逻辑不一样:
- AMD模式:watchify底层依赖的browserify,默认会把npm安装的依赖(比如knockout)当作"外部模块",不会打包进bundle里——它默认假设你会用AMD加载器(比如RequireJS)去单独加载这些依赖,所以只打包了你自己写的main.ts代码。
- UMD模式:UMD是为了兼容CommonJS、AMD和浏览器全局变量三种环境设计的,所以它会把所有依赖都打包进bundle里,不需要外部加载器。但你遇到的报错,是因为UMD代码会先检查浏览器里有没有AMD的
define函数,而你没加载RequireJS,所以就抛出了define is not defined的错误。
2. 生成包含全部代码的AMD Bundle(适合浏览器)
要让AMD bundle把所有依赖都打包进去,你需要修改watchify的命令,明确告诉它不要把依赖当作外部模块,同时指定输出为AMD格式:
修改你的watch.sh里的命令:
watchify ts/main.ts -p tsify -o bundle.js --mode=amd --no-external
--mode=amd:强制输出AMD格式的模块代码--no-external:取消默认的"外部依赖"逻辑,把所有用到的模块(包括knockout)都打包进bundle.js
然后在浏览器里使用这个AMD bundle时,必须先引入RequireJS,因为浏览器本身不支持AMD的define语法:
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js"></script> <script src="bundle.js"></script> <script> // 加载你的main模块 require(['main'], function(mainModule) { // 这里可以调用main.ts里导出的功能 }); </script>
3. 修复UMD的浏览器报错问题
UMD报错是因为它优先尝试适配AMD环境,但你没加载RequireJS。要让UMD bundle直接在浏览器里运行,需要给它指定一个全局变量名称,让它在浏览器环境下把模块挂载到window对象上:
修改watch.sh的命令:
watchify ts/main.ts -p tsify -o bundle.js --mode=umd --standalone MyApp
--standalone MyApp:指定全局变量名,这样UMD代码会在浏览器里把你的模块暴露为window.MyApp,你直接在脚本里访问MyApp就能调用你的代码,完全不需要RequireJS。
这样打包后的UMD bundle会包含所有依赖,同时能在浏览器里直接运行,不会再报错。
4. 添加代码压缩支持
要给bundle做代码压缩,推荐用terser(它支持ES6+语法,比旧的uglify-js更适合TypeScript打包的代码):
首先全局安装terser:
npm i -g terser
然后把打包命令的输出管道到terser,生成压缩后的bundle:
AMD压缩版
watchify ts/main.ts -p tsify --mode=amd --no-external | terser -c -m > bundle.min.js
UMD压缩版
watchify ts/main.ts -p tsify --mode=umd --standalone MyApp | terser -c -m > bundle.min.js
-c:启用代码压缩(比如移除空格、合并语句)-m:启用变量名混淆(缩短变量名,减小文件体积)
最后验证
打包完成后,你可以打开bundle.js看看:
- AMD版本里会有
define包裹的完整代码,包括knockout的内容 - UMD版本里会有一段判断环境的代码,最后把你的模块挂载到全局变量上,所有依赖也都在里面
内容的提问来源于stack exchange,提问作者silviubogan
相关产品推荐
相关产品推荐

