Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I build a webpack bundle that imports a module from another entry point bundle?

I'm trying to generate a second webpack bundle that's dependent on another bundle. Every page needs bundle-one, but only some pages need bundle-two.

For instance, let's say I have the following entry point scripts (these are trivial examples, just using them to get the point across):

bundle-one.js

import $ from 'jquery';
$(document).data('key', 'value');

bundle-two.js

import $ from 'jquery';
const value = $(document).data('key');

I know that I can use CommonsChunkPlugin to generate a commons.js file containing the WebPack loader and jQuery, but that would require loading both commons.js and bundle-one.js on every page, even when I don't need to load bundle-two.js.

So, basically: is there a way to build bundle-one.js as the "main" JavaScript bundle for all my pages, and then have bundle-two.js setup to load jQuery from bundle-one.js?

like image 902
dstaley Avatar asked Sep 15 '16 16:09

dstaley


People also ask

Can you have multiple entry points in a single webpack configuration file?

webpack.config.jsWe can also pass an array of file paths to the entry property which creates what is known as a "multi-main entry". This is useful when you would like to inject multiple dependent files together and graph their dependencies into one "chunk".

What is entry point webpack?

The entry object is where webpack looks to start building the bundle. The context is an absolute string to the directory that contains the entry files.

Does webpack build node_modules?

When you set target: 'node' in webpack config, webpack will not bundle the built-ins module of Node. js. path is a built-in module of Node. js, it doesn't come from the node_modules directory.


2 Answers

Option 1

Have two separate Webpack configs, one for each bundle. In your first bundle, expose jQuery as a global variable when you first require it using the expose-loader:

loaders: [
    { test: require.resolve('jquery'), loader: 'expose?jQuery!expose?$' }
]

Then, in your second bundle config, tell Webpack that jQuery is "external" and shouldn't be bundled in with the rest of the code:

{
    externals: {
        // require("jquery") is external and available
        //  on the global var jQuery
        "jquery": "jQuery"
    }
}

This way the first bundle exposes jQuery as a global variable, then the second bundle looks for that global variable instead of including the source.

Option 2

I'm not sure if this will work, but the CommonsChunkPlugin documentation says you can specify the name config option as an existing chunk. You try setting the name to your bundle1 entry point chunk name, and in theory jQuery (and other libs required across all chunks) will be built into bundle 1, and not bundle 2.

like image 89
Andy Ray Avatar answered Sep 21 '22 05:09

Andy Ray


You can do this in the following way using the provide plugin -

//webpack.config.js
module.exports = {
  entry: './index.js',
  output: { 
    filename: '[name].js' 
  },
  externals: {
    jquery: 'jQuery'
  },
  plugins: [
    new webpack.ProvidePlugin({
      $: 'jquery',
    })
  ]
};

This can be useful for refactoring legacy code with a lot of different files referencing $.

like image 27
Pritish Vaidya Avatar answered Sep 19 '22 05:09

Pritish Vaidya