Webpack Externals

May 4, 2020

Webpack externals tell Webpack to exclude a certain import from the bundle. Often externals are used to exclude imports that will be loaded via CDN.

For example, suppose you are implementing server-side rendering with Vue and Express, but your client-side code imports Vue via a CDN. Suppose you have the below component.js file:

const Vue = require('vue');

module.exports = Vue.component('hello', {
  props: ['name'],
  template: '<h1>Hello, {{name}}</h1>'
});

The above component.js works perfectly in Node.js with server-side rendering. But what about using the above component with the below index.html file?

<html>
  <body>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>

    <div id="content"></div>
    <script src="dist/component.min.js"></script>
    <script>
      new Vue({ template: '<hello name="World" />' }).
        mount(document.querySelector('#content'));
    </script>
  </body>
</html>

The below webpack.config.js adds 'vue' as an external, meaning Webpack won't bundle Vue. Instead, when component.js calls require('vue'), Webpack will instead return global.Vue.

module.exports = {
  entry: {
    component: `${__dirname}/component.js`
  },
  output: {
    path: `${__dirname}/dist`,
    filename: '[name].min.js'
  },
  target: 'web',
  externals: {
    // Stubs out `require('vue')` so it returns `global.Vue`
    vue: 'Vue'
  }
};

Excluding Node.js Polyfills

Another use case for externals is browser APIs that require a polyfill in Node.js, like FormData. If you're testing code that requires FormData in Node.js, you need to use a polyfill like the form-data npm module.

const axios = require('axios');
const FormData = require('form-data');

const form = new FormData();
form.append('key', 'value');
const res = await axios.post('https://httpbin.org/post', form);
console.log(res.data);

Since FormData is a browser API, you don't need to bundle it when compiling the above code. So you can use the below Webpack config:

module.exports = {
  entry: {
    http: `${__dirname}/http.js`
  },
  output: {
    path: `${__dirname}/dist`,
    filename: '[name].min.js'
  },
  target: 'web',
  externals: {
    // Stubs out `require('form-data')` so it returns `global.FormData`
    'form-data': 'FormData'
  }
};

More Webpack Tutorials