通过NPM跨多个Browserify或Webpack捆绑包共享模块的简单解决方案

cnp*_*cnp 16 javascript node.js npm browserify webpack

拉出我的头发寻找一个简单的解决方案,通过NPM,跨多个Browserify或Webpack捆绑包共享代码.思考,有文件"桥"这样的东西吗?

这不是因为编译时间(我知道watchify),而是希望提取出我所有供应商特定的库,vendor.js以便保持我的app.js文件大小并且不会使浏览器崩溃大量的源图.另外,如果需要查看已编译的js,我发现它更清晰.所以:

// vendor.js

require('react');
require('lodash');
require('other-npm-module');
require('another-npm-module');
Run Code Online (Sandbox Code Playgroud)

非常重要的是,代码从NPM加载而不是Bower,或者保存到某个"供应商"目录中,以便通过相对路径导入并通过垫片识别.除了我的实际应用程序源之外,我想通过NPM保留每个库引用.

在app.js我保留所有源代码,并通过externals数组,从编译中排除上面列出的供应商库:

// app.js 

var React = require('react');
var _     = require('lodash');

var Component = React.createClass()

// ...
Run Code Online (Sandbox Code Playgroud)

然后index.html,我需要两个文件

// index.html
<script src='vendor.js'></script>
<script src='app.js'></script>
Run Code Online (Sandbox Code Playgroud)

使用Browserify或Webpack,如何才能app.js"看到"通过npm加载的模块?我知道创建一个带有外部的包,然后node_modules通过别名引用直接文件(比方说),但我希望找到一个更自动且更少"Require.js"的解决方案.

基本上,我想知道是否可以桥接这两个,以便app.js可以查看内部vendor.js以解决依赖关系.这似乎是一个简单,直接的操作,但我似乎无法在这个广泛的网络上找到答案.

谢谢!

seb*_*n.b 26

列出所有供应商文件/模块并使用CommonChunkPlugin确实是推荐的方法.这变得相当繁琐,而且容易出错.

考虑这些NPM模块:fastclick和mprogress.由于他们没有采用CommonJS模块格式,你需要给webpack一个手,如下:

require('imports?define=>false!fastclick')(document.body);
require('mprogress/mprogress.min.css');
var Mprogress = require('mprogress/mprogress.min.js'),
Run Code Online (Sandbox Code Playgroud)

现在假设你想要两个 fastclick和mprogress你的供应商块,你可能会尝试这样:

module.exports = {
  entry: {
    app: "./app.js",
    vendor: ["fastclick", "mprogress", ...]
Run Code Online (Sandbox Code Playgroud)

唉,它不起作用.您需要匹配以下呼叫require():

module.exports = {
  entry: {
    app: "./app.js",
    vendor: [
      "imports?define=>false!fastclick", 
      "mprogress/mprogress.min.css", 
      "mprogress/mprogress.min.js", 
      ...]
Run Code Online (Sandbox Code Playgroud)

即使有些resolve.alias诡计,它也会变老.这是我的解决方法.CommonChunkPlugin允许您指定一个回调,无论您是否希望模块包含在供应商块中,该回调都将返回.如果您自己的源代码位于特定src目录中,而其余源代码位于node_modules目录中,则只需根据其路径拒绝这些模块:

var node_modules_dir = path.join(__dirname, 'node_modules'),
    app_dir          = path.join(__dirname, 'src');

module.exports = {
  entry: {
    app: "./app.js",
  },
  output: {
    filename: "bundle.js"
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin(
      /* chunkName= */"vendor",
      /* filename= */"vendor.bundle.js"
      function (module, count) {
       return module.resource && module.resource.indexOf(app_dir) === -1;
      }
    )
  ]
};
Run Code Online (Sandbox Code Playgroud)

module.resource正在考虑的模块的路径在哪里.你也可以做相反的事情,如果它在里面node_modules_dir,只包括模块,即:

       return module.resource && module.resource.indexOf(node_modules_dir) === 0;
Run Code Online (Sandbox Code Playgroud)

但在我的情况下,我宁愿说:" 把我源代码树中没有的东西放在供应商块中 ".

希望有所帮助.


Joh*_*ald 11

使用webpack,您将使用多个入口点和CommonChunkPlugin.

取自webpack文档:


要拆分您的应用程序为2个文件,说app.js和vendor.js,您可以要求在供应商的文件vendor.js.然后将此名称传递给CommonChunkPlugin,如下所示.

module.exports = {
  entry: {
    app: "./app.js",
    vendor: ["jquery", "underscore", ...],
  },
  output: {
    filename: "bundle.js"
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin(
        /* chunkName= */"vendor",
        /* filename= */"vendor.bundle.js"
    )
  ]
};
Run Code Online (Sandbox Code Playgroud)

这将从app chunk中删除供应商块中的所有模块.现在bundle.js将只包含您的应用程序代码,而不包含任何依赖项.这些都在vendor.bundle.js.

在您的HTML页面加载vendor.bundle.js之前bundle.js.

<script src="vendor.bundle.js"></script>
<script src="bundle.js"></script>
Run Code Online (Sandbox Code Playgroud)