如何将node_modules包含在一个单独的browserify供应商bundle中

27

我正在尝试将一个AngularJS应用程序转换为使用browserify。我已经使用napa将所有的bower包安装在node_modules中。现在我想将它们browserify为单独的供应商捆绑包,并将它们声明为'external'依赖项。我想给它们命名别名,这样我就可以使用"require('angular')"而不是"require('angular/angular')",因为似乎你可以通过externals来做到这一点。

我看过的例子(如http://benclinkinbeard.com/posts/external-bundles-for-faster-browserify-builds/)都假定我已经将供应商文件下载到了一个'lib'目录中。我只想从node_modules中捆绑我的供应商文件,这似乎很容易,但我不知道怎么做。

3个回答

41

我也曾尝试过同样的事情。我认为你需要针对供应商捆绑包使用--require,并针对应用程序使用--export,以便不会将依赖项捆绑两次。

这对我来说是可行的,我使用了browserify的api和gulp(我的node_modules是lodash和pixijs):

var gulp = require('gulp');
var browserify = require('browserify');
var handleErrors = require('../util/handleErrors');
var source = require('vinyl-source-stream');


gulp.task('libs', function () {
  return browserify()
    .require('lodash')
    .require('pixi.js')
    .bundle()
    .on('error', handleErrors)
    .pipe(source('libs.js'))
    .pipe(gulp.dest('./build/'));
});

gulp.task('scripts', function () {
  return browserify('./src/main.js')
    .external('lodash')
    .external('pixi.js')
    .bundle()
    .on('error', handleErrors)
    .pipe(source('main.js'))
    .pipe(gulp.dest('./build/'));
});

gulp.task('watch', function(){
  gulp.watch('src/**', ['scripts']);
});

gulp.task('default', ['libs', 'scripts', 'watch']);

当然,这个解决方案很难维护...所以我修改了browserify的源码,让它可以接受requireexternal中的数组,然后你就可以这样做了,我觉得这样更好:

var gulp         = require('gulp');
var browserify   = require('browserify');
var handleErrors = require('../util/handleErrors');
var source       = require('vinyl-source-stream');

var packageJson = require('../../package.json');
var dependencies = Object.keys(packageJson && packageJson.dependencies || {});


gulp.task('libs', function () {
  return browserify()
    .require(dependencies)
    .bundle()
    .on('error', handleErrors)
    .pipe(source('libs.js'))
    .pipe(gulp.dest('./build/'));
});

gulp.task('scripts', function () {
  return browserify('./src/main.js')
    .external(dependencies)
    .bundle()
    .on('error', handleErrors)
    .pipe(source('main.js'))
    .pipe(gulp.dest('./build/'));
});

gulp.task('watch', function(){
  gulp.watch('package.json', ['libs']);
  gulp.watch('src/**', ['scripts']);
});

gulp.task('default', ['libs', 'scripts', 'watch']);

这是我最好想到的... 如果你找到更好的方法,请告诉我。


感谢您的回复,Oscar。我现在暂停了我的Browserify之旅,所以不幸的是无法验证这个答案。当我重新审视这个问题时,我会尝试记住测试并接受您的答案。 - kpg
1
所以我修补了browserify,你能否把它作为pull request发送过来? - CheapSteaks
3
你好,这个补丁已经被合并到这里了。 - Oscar Morante
有没有可能只获取前端依赖项,而不是获取 package.json 中的所有依赖项(其中包括 gulp 本身)?我不想在 browserify 捆绑包中捆绑 gulp 本身。 - apple16
@apple16 这就是为什么要使用 devDependencies 的原因。 - torvin

0

这个解决方案看起来很棒:

var packageJSON = require('./package.json');
var dependencies = Object.keys(packageJSON && packageJSON.dependencies || {});

gulp.task('vendor', function() {
   return browserify()
    .require(dependencies)
    .bundle()
    .pipe(source('vendor.bundle.js'))
    .pipe(gulp.dest(__dirname + '/public/scripts'));
});

0
我也遇到了这个问题。因为当所有供应商库在同一个文件中时,它是一个巨大的文件。所以浏览器总是卡在下载超过10MB的文件上。文件缩小也不是解决方案,因为编译需要更长的时间,对开发没有帮助。
我将vendor.jsapp.js分别放在不同的节点模块和应用程序脚本中。就像这样。
示例vendor.js(src/app/vendor.js)
/**
 * Node modules
 */
require('angular');
require('angular-cookies');
require('angular-ui-router');
require('angular-aria');
require('angular-animate');
....

示例 app.js(src/app/app.js)

/**
 * App Common Modules
 */
require('./modules/about/about.routing.js');
require('./modules/home/home.routing.js');

/**
 * Services
 */
require('./shared/services/order.js');
require('./shared/services/product.js');


/**
 * Directives
 */
require('./shared/directives/dropzone.js');
require('./shared/directives/tab-change.js');


angular
    .module('myApp', [
        //------------- Node modules ------------//
        'ui.router',
        'ngMaterial',


        //------------- App Common modules ------------//

        //About
        'cloudDecor.routing.about',
        'cloudDecor.controller.about',


        //Home
        'cloudDecor.routing.home',
        'cloudDecor.controller.home',


        //------------- Services --------------//

        'cloudDecor.service.order',


        //------------- Directives ------------//
        'cloudDecor.directive.dropzone',
        'cloudDecor.directive.tab-change'

    ]);

gulpfile.js

var gulp = require('gulp'),   
    browserify = require('browserify'),
    uglify = require('gulp-uglify'),
    buffer = require('vinyl-buffer');


//App js
gulp.task('app_js', function() {
    // Grabs the app.js file
    browserify({
            entries: ['./src/app/app.js'],
            debug: true
        })
        .bundle()
        .pipe(source('main.js'))
        .pipe(buffer())
        .pipe(gulp.dest('./build/'));
});

//Vendor js
gulp.task('vendor_js', function() {
    // Grabs the app.js file
    browserify({
        entries: ['./src/app/vendor.js']
    })
    .bundle()
    .pipe(source('vendor.min.js'))
    .pipe(buffer())
    .pipe(uglify({ mangle: false }))
    .pipe(gulp.dest('./build/'));
});

gulp.task('default', ['app_js', 'vendor_js']);

请确保在使用index.html中的main.js之前先引入vendor.js
<html>
<body>

<!--Vendor js, See src/vendor.js-->
<script type="text/javascript" src="vendor.min.js"></script>

<!--App scripts, See src/app.js-->
<script type="text/javascript" src="main.js"></script>
</body>
</html>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接