webpack打包懒加载

https://webpack.js.org/guides/lazy-loading/

懒加载 -- 按需加载。

Lazy, or "on demand", loading is a great way to optimize your site or application. This practice essentially involves splitting your code at logical breakpoints, and then loading it once the user has done something that requires, or will require, a new block of code. This speeds up the initial load of the application and lightens its overall weight as some blocks may never even be loaded.

webpack solution

https://webpack.js.org/migrate/3/#code-splitting-with-es2015

Code Splitting with ES2015

In webpack 1, you could use require.ensure() as a method to lazily-load chunks for your application:

require.ensure([], function(require) {
  var foo = require('./module');
});

The ES2015 Loader spec defines import() as method to load ES2015 Modules dynamically on runtime. webpack treats import() as a split-point and puts the requested module in a separate chunk. import() takes the module name as argument and returns a Promise.

function onClick() {
  import('./module').then(module => {
    return module.default;
  }).catch(err => {
    console.log('Chunk loading failed');
  });
}

Good news: Failure to load a chunk can now be handled because they are Promise

require.ensure

https://webpack.js.org/api/module-methods/#requireensure

require.ensure() is specific to webpack and superseded by import().

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

Split out the given dependencies to a separate bundle that that will be loaded asynchronously. When using CommonJS module syntax, this is the only way to dynamically load dependencies. Meaning, this code can be run within execution, only loading the dependencies if certain conditions are met.

This feature relies on Promise internally. If you use require.ensure with older browsers, remember to shim Promise using a polyfill such as es6-promise or promise-polyfill.

var a = require('normal-dep');

if ( module.hot ) {
  require.ensure(['b'], function(require) {
    var c = require('c');

    // Do something special...
  });
}

The following parameters are supported in the order specified above:

  • dependencies: An array of strings declaring all modules required for the code in the callback to execute.
  • callback: A 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.
  • errorCallback: A function that is executed when webpack fails to load the dependencies.
  • chunkName: 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.

Although the implementation of require is passed as an argument to the callback function, using an arbitrary name e.g. require.ensure([], function(request) { request('someModule'); }) isn't handled by webpack's static parser. Use require instead, e.g. require.ensure([], function(require) { require('someModule'); }).

import()

import('path/to/module') -> Promise

Dynamically load modules. Calls to import() are treated as split points, meaning the requested module and it's children are split out into a separate chunk.

The ES2015 Loader spec defines import() as method to load ES2015 modules dynamically on runtime.

if ( module.hot ) {
  import('lodash').then(_ => {
    // Do something with lodash (a.k.a '_')...
  });
}

This feature relies on Promise internally. If you use import() with older browsers, remember to shim Promise using a polyfill

require (amd-version)

https://webpack.js.org/api/module-methods/#require-amd-version

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

Similar to require.ensure, this will split the given dependencies into a separate bundle that will be loaded asynchronously. The callback will be called with the exports of each dependency in the dependencies array.

This feature relies on Promise internally. If you use AMD with older browsers (e.g. Internet Explorer 11), remember to shim Promise using a polyfill such as es6-promise or promise-polyfill.

require(['b'], function(b) {
  var c = require('c');
});

There is no option to provide a chunk name.

external NPM module -- bundle-loader

https://www.npmjs.com/package/bundle-loader

https://github.com/ruanyf/webpack-demos#demo08-html-webpack-plugin-and-open-browser-webpack-plugin-source

Another way of code splitting is using bundle-loader.

// main.js

// Now a.js is requested, it will be bundled into another file
var load = require('bundle-loader!./a.js');

// To wait until a.js is available (and get the exports)
//  you need to async wait for it.
load(function(file) {
  document.open();
  document.write('<h1>' + file + '</h1>');
  document.close();
});

require('bundle-loader!./a.js') tells Webpack to load a.js from another chunk.

Now Webpack will build main.js into bundle.js, and a.js into 0.bundle.js.

others lazy load

https://webpack.js.org/guides/lazy-loading/

Frameworks

Many frameworks and libraries have their own recommendations on how this should be accomplished within their methodologies. Here are a few examples:


Further Reading

reference:

https://github.com/amdjs/amdjs-api

https://github.com/yongningfu/webpa_ensure

https://github.com/yongningfu/webpack_package