使用Browserify动态编译所需模块
使用Browserify动态编译所需模块
我正在使用Browserify将一个大型的Node.js应用程序编译成一个单独的文件(使用选项--bare
和--ignore-missing
[避免在Express中与lib-cov
出现问题])。我有一些代码根据目录中可用的内容动态加载模块:\n
var fs = require('fs'), path = require('path'); fs.readdirSync(__dirname).forEach(function (file) { if (file !== 'index.js' && fs.statSync(path.join(__dirname, file)).isFile()) { module.exports[file.substring(0, file.length-3)] = require(path.join(__dirname, file)); } });
\n我在我的应用程序中遇到了奇怪的错误,加载了来自我编译文件所在目录的任意文本文件。我认为这是因为路径不再正确设置,并且Browserify无法像这样动态加载时require()
到正确的文件。\n除了创建一个静态的index.js
文件外,是否有一种与Browserify开箱即用兼容的动态要求模块目录的首选方法?
使用Browserify编译动态要求的模块出现问题的原因是在Browserify的默认行为中,它只会编译并包含在入口文件(app.js)中直接require的模块,而不会编译那些在运行时动态require的模块。这导致了在使用bulk-require插件时,无法将controllers目录中的所有模块编译到最终的app.js文件中。
为了解决这个问题,可以使用bulkify插件。bulkify是一个Browserify的转换插件,它可以使得Browserify在编译时能够识别并包含动态require的模块。
首先,在app.js文件中引入bulk-require模块,并使用bulk函数动态require controllers目录下的所有模块。
var bulk = require('bulk-require'); // Require all of the scripts in the controllers directory bulk(__dirname, ['controllers/**/*.js']);
然后,在gulpfile中的js任务中使用browserify插件,并将transform选项设置为['bulkify'],以便在编译时使用bulkify转换插件。
gulp.task('js', function () { return gulp.src('./src/js/init.js') .pipe(browserify({ transform: ['bulkify'] })) .pipe(rename('app.js')) .pipe(uglify()) .pipe(gulp.dest('./dest/js')); });
通过以上配置,Browserify会在编译时识别并包含controllers目录下的所有模块,从而解决了动态require模块无法被编译的问题。
问题的原因是在使用Browserify编译动态所需的模块时,require函数无法正确地加载这些模块。解决方法是使用require-globify插件来支持加载Glob模式的模块,并通过一个小技巧在编译时添加所有文件而不执行它们。
具体的解决方法如下:
1. 首先,安装require-globify插件。
2. 在代码中添加以下代码片段,用于编译Glob模式的文件,但不要调用此函数(这是一个hack):
// Hack to compile Glob files. Don´t call this function! function ಠ_ಠ() { require('views/**/*.js', { glob: true }) }
3. 当需要时,可以使用类似以下的代码来加载和执行特定的文件:
var homePage = require('views/'+currentView)
通过这种方式,可以欺骗静态分析器,使其认为已经使用了这些动态加载的模块。
至于为什么只有在将require("app/*.js")放在同一个文件中时,require("app/" + module)才能正常工作,原因是所需的JS文件虽然被包含在编译后的JS中,但无法直接访问。通过上述的解决方法,可以绕过这个问题,正确加载和执行所需的模块。