Search code examples
webpackwebpack-2chunkscode-splitting

Webpack 2: vendor, common and specific bundles


With the CommonsChunkPlugin I currently have my code split up into:

vendors.js
common.js
page-1.js
page-2-authenticated.js
page-3-authenticated.js

So on page-1.html I load the following scripts:

<script src="vendors.js" />
<script src="common.js" />
<script src="page-1.js" />

It works fine and all the shared code in page-1.js, page-2-authenticated.js and page-3-authenticated.js are bundled into common.js.

As you can see, my application requires a user to be logged in for page-2-authenticated.html and page-3-authenticated.html. However, shared code in page-2-authenticated.js and page-3-authenticated.js is also bundled into common.js. But I don't want to bother users who are not logged in, with code that is only used when you are logged in.

So for page-2-authenticated.html I would like to have:

<script src="vendors.js" />
<script src="common.js" />
<script src="common-authenticated.js" /> // Shared code for authenticated users
<script src="page-2-authenticated.js" />

However, when I export a test variable in common-authenticated.js and import these into page-2-authenticated.js and page-3-authenticated.js, this shared code is still bundled into common.js. And common-authenticated.js is empty (just some webpackJsonp([12],[],[85]);).

I have the following webpack 2 config:

entry: {
  vendors: ['react'],
  common: 'index.js',
  'common-authenticated': 'common-authenticated.js',
  'page-1': 'page-1.js',
  'page-2-authenticated': 'page-2-authenticated.js',
  'page-3-authenticated': 'page-3-authenticated.js'
},
plugins: [
  new webpack.optimize.CommonsChunkPlugin({
    // The order of this array matters
    names: ['common', 'vendors'],
    minChunks: 2
  })
]

Question: How do I bundle specific code into common-authenticated.js? Any ideas?


Solution

  • I was able to solve it with the following configuration:

    entry: {
      // Same as in topic start
    },
    
    plugins: [
      /*
       * Check the files used for pages on which you need to be logged in
       * and bundle the shared code of these files in a chunk named
       * 'common-authenticated' (its output will be in 'common-authenticated.js')
       */
      new webpack.optimize.CommonsChunkPlugin({
        name: 'common-authenticated',
        chunks: [
          'page-2-authenticated',
          'page-3-authenticated'
        ],
        minChunks: 2
      }),
    
      /*
       * Now check for shared code in the bundle defined above plus the files for
       * pages on which you do not need to be logged in. Bundle this shared code into
       * 'common.js'
       */
      new webpack.optimize.CommonsChunkPlugin({
        name: 'common',
        chunks: [
          'common-authenticated', // Name of the chunk defined above
          'page-1'
        ],
        minChunks: 2
      }),
    
      /*
       * I don't really now how this works. But it works :).
       * It generates the 'vendors.js'
       */
      new webpack.optimize.CommonsChunkPlugin({
        name: 'vendors',
        chunks: ['common', 'vendors'],
        minChunks: 2
      })
    ]
    

    It gives me exactly what I want. The loading of scripts in page-1.html remains unchanged (I don't need common-authenticated.js there). And page-2-authenticated.html now has:

    <script src="vendors.js" />
    <script src="common.js" />
    <script src="common-authenticated.js" /> // Shared code for authenticated users
    <script src="page-2-authenticated.js" />