使用Gulp+Browserify打包Vendor文件的问题及Morris.js适配疑问
我正在开发Orchard Core主题,需要打包核心模块供其他模块使用:将Bootstrap、jQuery纳入theme.vendor.js,使应用该主题的模块可直接使用jQuery的$。通过Gulp+Browserify分别打包Vendor.ts与Main.ts后,浏览器出现依赖未正确暴露的问题,部分包还存在调用"jQuery"而非"jquery"或"$"的情况。
更新1
已实现独立的应用包与Vendor包生成,jQuery、Bootstrap可外部引用,但Morris.js(morris.js06)仍无法正常工作。
应用TypeScript代码:
import "raphael"; import { Morris } from "morris.js06";
Gulp打包配置:
var bundler = browserify({ entries: ['wwwroot/scripts/App.ts'], cache: {}, packageCache: {} }); packageReferencesArray.forEach(function (packageReference) { console.log('Excluding ' + packageReference.packageName); bundler.exclude(packageReference.packageName); bundler.external(packageReference.packageName); }); bundler.external('Morris');
输出文件中出现morris_js06.Morris.Area调用,浏览器中该对象不存在,但Morris本身已定义,疑似Browserify未遵循.external指令。
请问如何配置Gulp+Browserify,生成能在浏览器正确暴露依赖的vendor.js?
1. 配置Vendor打包,主动暴露全局变量
先编写vendor.ts,明确将依赖挂载到window对象,同时统一jQuery的别名:
// vendor.ts import * as $ from 'jquery'; // 同时绑定jQuery和$到全局,解决部分库调用jQuery的问题 window.jQuery = $; window.$ = $; // Bootstrap依赖jQuery,导入后会自动绑定 import 'bootstrap'; // 处理Morris.js依赖的Raphael import * as Raphael from 'raphael'; window.Raphael = Raphael; // 将Morris暴露到全局 import * as Morris from 'morris.js06'; window.Morris = Morris;
然后配置Gulp打包vendor.js,确保Browserify将这些依赖打包并输出到全局:
// Gulp配置 - 打包Vendor gulp.task('build-vendor', function() { return browserify('wwwroot/scripts/vendor.ts', { debug: true, extensions: ['.ts'] }) .plugin('tsify') // 处理TypeScript文件 .bundle() .pipe(source('theme.vendor.js')) .pipe(buffer()) .pipe(sourcemaps.init({loadMaps: true})) .pipe(uglify()) // 可选,生产环境压缩 .pipe(sourcemaps.write('./')) .pipe(gulp.dest('wwwroot/dist')); });
2. 简化应用包的外部依赖配置
在应用包的Browserify配置中,直接指定外部依赖数组,避免循环调用exclude和external,同时注意包名的大小写一致性:
// Gulp配置 - 打包应用代码 gulp.task('build-app', function() { // 明确标记为外部依赖的包名,注意都是npm包的原始名称 const externalPackages = ['jquery', 'bootstrap', 'raphael', 'morris.js06']; return browserify('wwwroot/scripts/App.ts', { debug: true, extensions: ['.ts'], external: externalPackages // 直接声明外部依赖 }) .plugin('tsify') .bundle() .pipe(source('app.js')) .pipe(buffer()) .pipe(sourcemaps.init({loadMaps: true})) .pipe(uglify()) .pipe(sourcemaps.write('./')) .pipe(gulp.dest('wwwroot/dist')); });
3. 修复Morris.js的调用问题
你遇到的morris_js06.Morris.Area未找到的问题,是因为TypeScript导入后Browserify给模块添加了命名空间,但你已经将Morris暴露到全局window.Morris,因此可以直接使用全局对象:
// 修改后的App.ts import "raphael"; // 保留导入以确保类型提示,Browserify不会打包它 // 移除import { Morris } from "morris.js06";,直接使用全局Morris // 直接调用全局Morris实例 new Morris.Area({ // 你的图表配置项 });
如果需要保留TypeScript的类型提示,可在项目根目录的typings.d.ts中添加全局声明:
// typings.d.ts declare var Morris: typeof import('morris.js06').Morris;
4. 确保页面加载顺序正确
在Orchard Core主题的布局文件中,必须先加载theme.vendor.js,再加载应用代码:
<script src="~/dist/theme.vendor.js"></script> <script src="~/dist/app.js"></script>
内容的提问来源于stack exchange,提问作者Will Comeaux

