Code Splitting - Using require.ensure

Edit this Page   

In this section, we will discuss how webpack splits code using require.ensure().

require.ensure is specific to webpack, see import() for a proposal for ECMAScript.

require.ensure()

webpack statically parses for require.ensure() in the code while building. Any module that is referenced as a dependency or require()d within the callback function, will be added to a new chunk. This new chunk is written to an async bundle that is loaded on demand by webpack through jsonp.

The syntax is as follows:

require.ensure(dependencies: String[], callback: function(require), chunkName: String)

dependencies

This is an array of strings where we can declare all the modules that need to be made available before all the code in the callback function can be executed.

callback

This is the callback function that webpack will execute once the dependencies are loaded. An implementation of the require function is sent as a parameter to this function. The function body can use this to further require() modules it needs for execution.

chunkName

The chunkName is a name given to the chunk created by this particular require.ensure(). By passing the same chunkName to various require.ensure() calls, we can combine their code into a single chunk, resulting in only one bundle that the browser must load.

Example

Let us consider the following file structure:

.
├── dist
├── js
│   ├── a.js
│   ├── b.js
│   ├── c.js
│   └── entry.js
└── webpack.config.js

entry.js

require('./a');
require.ensure(['./b'], function(require){
    require('./c');
    console.log('done!');
});

a.js

console.log('***** I AM a *****');

b.js

console.log('***** I AM b *****');

c.js

console.log('***** I AM c *****');

webpack.config.js

var path = require('path');

module.exports = function(env) {
    return {
        entry: './js/entry.js',
        output: {
            filename: 'bundle.js',
            path: path.resolve(__dirname, 'dist'),
            publicPath: 'https://cdn.example.com/assets/',
            // tell webpack where to load the on-demand bundles. 

            pathinfo: true,
            // show comments in bundles, just to beautify the output of this example.
            // should not be used for production.
        }
    }
}
output.publicPath is an important option when using code-splitting, it is used to tell webpack where to load your bundles on-demand, see the configuration documentation.

On running webpack on this project, we find that webpack has created two new bundles, bundle.js and 0.bundle.js.

entry.js and a.js are bundled in bundle.js.

bundle.js

/******/ (function(modules) { // webpackBootstrap
//webpack bootstrap code...

/******/     // __webpack_public_path__
/******/     __webpack_require__.p = "https://cdn.example.com/assets/";

// webpack bootstrap code...
/******/ })
/******/ ([
/* 0 */
/* unknown exports provided */
/* all exports used */
/*!*****************!*\
  !*** ./js/a.js ***!
  \*****************/
/***/ (function(module, exports) {

console.log('***** I AM a *****');


/***/ }),
/* 1 */,
/* 2 */,
/* 3 */
/* unknown exports provided */
/* all exports used */
/*!*********************!*\
  !*** ./js/entry.js ***!
  \*********************/
/***/ (function(module, exports, __webpack_require__) {

__webpack_require__(/*! ./a */ 0);
__webpack_require__.e/* require.ensure */(0).then((function(require){
    __webpack_require__(/*! ./c */ 2);
    console.log('done!');
}).bind(null, __webpack_require__)).catch(__webpack_require__.oe);


/***/ })
/******/ ]);
We can see the specified webpack public path on __webpack_require__.p in the bootstrap code, it corresponds to our output.publicPath configuration on above.

b.js and c.js are bundled in 0.bundle.js.

0.bundle.js

webpackJsonp([0],[
/* 0 */,
/* 1 */
/* unknown exports provided */
/* all exports used */
/*!*****************!*\
  !*** ./js/b.js ***!
  \*****************/
/***/ (function(module, exports) {

console.log('***** I AM b *****');


/***/ }),
/* 2 */
/* unknown exports provided */
/* all exports used */
/*!*****************!*\
  !*** ./js/c.js ***!
  \*****************/
/***/ (function(module, exports) {

console.log('***** I AM c *****');



/***/ })
]);

Now just add bundle.js in your HTML file and open it in your broswer, the 0.bundle.js will be loaded on demand (from https://cdn.example.com/assets/0.bundle.js) by webpack.

More examples

Promise polyfill

require.ensure relies on Promise internally. See this section for possible polyfills.

Gotchas for require.ensure()

Empty Array as Parameter

require.ensure([], function(require){
    require('./a.js');
});

The above code ensures that a split point is created and a.js is bundled separately by webpack.

Dependencies as Parameter

require.ensure(['./b.js'], function(require) {
    require('./c.js');
});

In the above code, b.js and c.js are bundled together and split from the main bundle. But only the contents of c.js are executed. The contents of b.js are only made available and not executed. To execute b.js, we will have to require it in a sync manner like require('./b.js') for the JavaScript to get executed.


Contributors