Simple solution to share modules loaded via NPM across multiple Browserify or Webpack bundles

后端 未结 3 1110
Happy的楠姐
Happy的楠姐 2021-02-04 05:36

Pulling my hair out here looking for a simple solution to share code, required via NPM, across multiple Browserify or Webpack bundles. Thinking, is there such a thing

3条回答
  •  囚心锁ツ
    2021-02-04 06:06

    Listing all the vendor files/modules and using CommonChunkPlugin is indeed the recommended way. This gets pretty tedious though, and error prone.

    Consider these NPM modules: fastclick and mprogress. Since they have not adopted the CommonJS module format, you need to give webpack a hand, like this:

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

    Now assuming you would want both fastclick and mprogress in your vendor chunk, you would probably try this:

    module.exports = {
      entry: {
        app: "./app.js",
        vendor: ["fastclick", "mprogress", ...]
    

    Alas, it doesn't work. You need to match the calls to require():

    module.exports = {
      entry: {
        app: "./app.js",
        vendor: [
          "imports?define=>false!fastclick", 
          "mprogress/mprogress.min.css", 
          "mprogress/mprogress.min.js", 
          ...]
    

    It gets old, even with some resolve.alias trickery. Here is my workaround. CommonChunkPlugin lets you specify a callback that will return whether or not you want a module to be included in the vendor chunk. If your own source code is in a specific src directory, and the rest is in the node_modules directory, just reject the modules based on their path:

    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;
          }
        )
      ]
    };
    

    Where module.resource is the path to the module being considered. You could also do the opposite, and include only the module if it is inside node_modules_dir, i.e.:

           return module.resource && module.resource.indexOf(node_modules_dir) === 0;
    

    but in my situation, I'd rather say: "put everything that is not in my source source tree in a vendor chunk".

    Hope that helps.

提交回复
热议问题