6

我正在尝试捆绑我自己的代码(A),该代码又使用 2 个第三方组件(B 和 C),其中 C 也需要 B。据我所知,所有内容都是使用 CommonJS 节点样式模块编写的。

捆绑时单独的 A 输出为 60K。

B 单独包含并假定为全局的,通过在我的构建步骤中进行一些肮脏的替换,将 require("B") 替换为 global.B,我可以正常工作

C 是什么导致了我的问题,它的大小意味着“只有 8K”,但是当我尝试将它与 A 捆绑在一起时,我的包会跳到 600K+,因为我认为它会吸引大量的依赖项?

这是不可接受的,但我不知道如何让它变得更小,因为我不知道它到底是什么(或更重要的是我可以排除什么以使其仍然有效)。我可以尝试使用排除法进行二元斩波,但我不知道这是否是一种安全的方式,甚至是明智的方式。

我怎样才能捆绑 C 并且只有我的捆绑包以 68.5K(两个代码块的总大小 60k + 8.5k)并且当然仍然可以工作?

我是 node 和 browserify 的新手,但我已经为此苦苦挣扎了一个多星期,所以公平地说,在举手之前我已经给了它一个很好的尝试。

附加信息(如果重要):

  • 它需要运行服务器端和客户端
  • B 实际上是 ReactJS
  • C 实际上是 React Router 组件
  • 通过 ReactJS.net 使用 windows 和 c#...嘿...等等...回来... tumbleweed
4

4 回答 4

5

如果您创建一个包含所有应用程序依赖项 (B + C) 的外部包,并在捆绑应用程序自己的代码 (A) 时将这些模块声明为外部模块,那么事情应该会按预期工作。

我不知道执行此操作的 grunt-browserify 配置咒语,但以下显示了如何在一些示例 gulp 任务中直接使用 browserify,因此包创建应该是可重用的:

var browserify = require('browserify')
var gulp = require('gulp')
var source = require('vinyl-source-stream')

gulp.task('js-deps', function() {
  var b = browserify()
  b.require('react')
  b.require('react-router-component')
  b.transform('envify')

  return b.bundle()
    .pipe(source('deps.js'))
    .pipe(gulp.dest('./build'))
})

gulp.task('bundle-js', function() {
  var b = browserify('./lib/app.js')
  b.external('react')
  b.external('react-router-component')

  return b.bundle()
    .pipe(source('app.js'))
    .pipe(gulp.dest('./build'))
})
于 2015-01-13T13:53:59.360 回答
2

其他人已经提到了应该是实际解决方案的外部选项。现在,也要考虑这些建议。您可能已经知道大部分(如果不是全部),但其中一些可能会有所帮助。这不会将 600k 文件变成 1k,但仍然可能很重要。

首先查看https://github.com/substack/node-browserify#usage中的高级选项,更具体地说是 --no-bundle-external 选项。如果 external 选项确实适用于 require('b') 但仍然包含外部库,这是你最好的选择;

还要查看有关全局变量的选项。当我开始使用 browserify 时,我将一个函数编译成一个巨大的库,因为它包含 NodeJS 本机模块的所有存根。上述选项是解决此问题的关键。它在 Grunt-task 中,但如果我没记错的话,它与 grunt-browserify 任务无关,它仍然可能是相关的。

如果您还没有这样做,请在运行 browserify:app 之前设置构建环境。有些库依赖于这些变量进行生产编译(我认为 React 就是其中之一)。

    grunt.loadNpmTasks('grunt-env');

    // initConfig task
    env: {
      dist: {
        NODE_ENV : 'production',
      },
      dev: {
        NODE_ENV: 'development',
      } 
    }

    grunt.registerTask("build_dist", ['env:dist', 'browserify:app']

尝试使用这些选项来运行 Uglify;

    // initConfig task options
    options: {
      compress:{
        dead_code     : true,  // discard unreachable code
        drop_debugger : true,  // discard “debugger” statements
        global_defs   : {      // global definitions
          "DEBUG": false,      // matters for some libraries
        },
      }
    }

您可以进行更多优化,但这应该可以帮助您入门。

B 单独包含并假定为全局的,通过在我的构建步骤中进行一些肮脏的替换,将 require("B") 替换为 global.B,我可以正常工作。

如果您在编译后切换到 global.B,那么您的包也将具有 require('b') 的所有依赖项。这个hack(可能)更好:

这是不可接受的,但我不知道如何让它更小,因为我不知道它到底是什么(或更重要的是我可以排除什么以使其仍然有效)

查看生成库的源代码,您应该能够识别不同的模块及其文件路径。

于 2015-01-13T20:16:08.683 回答
1

我已经整理了一个关于如何使用 Browserify 将代码拆分为多个包的工作示例:https ://github.com/aldendaniels/browserify-bundle-splitting

使用这种方法,您可以通过 Browserify 加载所有供应商代码(不需要全局填充),但仍然可以单独捆绑您自己的代码。

由于生成的包是真正独立的,您可以轻松地为生成的包设置不同的设置。例如,您可能希望禁用第 3 方代码的源映射,但对您自己的代码使用源映射。

于 2015-05-18T11:25:56.727 回答
0

您可以通过运行以下命令查看包中哪些文件占用了空间:browserify --list test/browser/browserify-test-uncompiled.js | xargs ls -la | sort

于 2016-09-12T12:05:07.160 回答