Module API - Methods
This section covers all methods available in code compiled with webpack. When using webpack to bundle your application, you can pick from a variety of module syntax styles including ES6, CommonJS, and AMD.
While webpack supports multiple module syntaxes, we recommend following a single syntax for consistency and to avoid odd behaviors/bugs. Here's one example of mixing ES6 and CommonJS, however there are surely others.
ES6 (Recommended)
Version 2 of webpack supports ES6 module syntax natively, meaning you can use import and export without a tool like babel to handle this for you. Keep in mind that you will still probably need babel for other ES6+ features. The following methods are supported by webpack:
import
Statically import the exports of another module.
import MyModule from './my-module.js';
import { NamedExport } from './other-module.js';
The keyword here is statically. Normal
importstatement cannot be used dynamically within other logic or contain variables. See the spec for more information andimport()below for dynamic usage.
export
Export anything as a default or named export.
// Named exports
export var Count = 5;
export function Multiply(a, b) {
return a * b;
}
// Default export
export default {
// Some data...
}
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
Promiseinternally. If you useimport()with older browsers, remember to shimPromiseusing a polyfill such as es6-promise or promise-polyfill. See Shimming for more information.
The spec for import doesn't allow control over the chunk's name or other properties as "chunks" are only a concept within webpack. Luckily webpack allows some special parameters via comments so as to not break the spec:
import(
/* webpackChunkName: "my-chunk-name" */
/* webpackMode: "lazy" */
'module'
);
webpackChunkName: A name for the new chunk. Since webpack 2.6.0, the placeholders [index] and [request] are supported within the given string to an incremented number or the actual resolved filename respectively.
webpackMode: Since webpack 2.6.0, different modes for resolving dynamic imports can be specified. The following options are supported:
"lazy"(default): Generates a lazy-loadable chunk for eachimport()ed module."lazy-once": Generates a single lazy-loadable chunk that can satisfy all calls toimport(). The chunk will be fetched on the first call toimport(), and subsequent calls toimport()will use the same network response. Note that this only makes sense in the case of a partially dynamic statement, e.g.import(`./locales/${language}.json`), where there are multiple module paths that could potentially be requested."eager": Generates no extra chunk. All modules are included in the current chunk and no additional network requests are made. APromiseis still returned but is already resolved. In contrast to a static import, the module isn't executed until the call toimport()is made.
Note that both options can be combined like so
/* webpackMode: "lazy-once", webpackChunkName: "all-i18n-data" */. This is parsed as a JSON5 object without curly brackets.Fully dynamic statements, such as
import(foo), will fail because webpack requires at least some file location information. This is becausefoocould potentially be any path to any file in your system or project. Theimport()must contain at least some information about where the module is located, so bundling can be limited to a specific directory or set of files.Every module that could potentially be requested on an
import()call is included. For example,import(`./locale/${language}.json`)will cause every.jsonfile in the./localedirectory to be bundled into the new chunk. At run time, when the variablelanguagehas been computed, any file likeenglish.jsonorgerman.jsonwill be available for consumption.The use of
System.importin webpack did not fit the proposed spec, so it was deprecated in webpack 2.1.0-beta.28 in favor ofimport().
CommonJS
The goal of CommonJS is to specify an ecosystem for JavaScript outside the browser. The following CommonJS methods are supported by webpack:
require
require(dependency: String)
Synchronously retrieve the exports from another module. The compiler will ensure that the dependency is available in the output bundle.
var $ = require("jquery");
var myModule = require("my-module");
Using it asynchronously may not have the expected effect.
require.resolve
require.resolve(dependency: String)
Synchronously retrieve a module's ID. The compiler will ensure that the dependency is available in the output bundle. See module.id for more information.
var id = require.resolve("dependency");
typeof id === "number";
id === 0 // if dependency is the entry point
id > 0 // elsewise
Module ID is a number in webpack (in contrast to NodeJS where it is a string -- the filename).
require.cache
Multiple requires to the same module result in only one module execution and only one export. Therefore a cache in the runtime exists. Removing values from this cache cause new module execution and a new export.
This is only needed in rare cases for compatibility!
var d1 = require("dependency");
require("dependency") === d1
delete require.cache[require.resolve("dependency")];
require("dependency") !== d1
// in file.js
require.cache[module.id] === module
require("./file.js") === module.exports
delete require.cache[module.id];
require.cache[module.id] === undefined
require("./file.js") !== module.exports // in theory; in praxis this causes a stack overflow
require.cache[module.id] !== module
require.ensure
require.ensure()is specific to webpack and superseded byimport().
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.
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 thecallbackto execute.callback: A function that webpack will execute once the dependencies are loaded. An implementation of therequirefunction is sent as a parameter to this function. The function body can use this to furtherrequire()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 particularrequire.ensure(). By passing the samechunkNameto variousrequire.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
requireis passed as an argument to thecallbackfunction, using an arbitrary name e.g.require.ensure([], function(request) { request('someModule'); })isn't handled by webpack's static parser. Userequireinstead, e.g.require.ensure([], function(require) { require('someModule'); }).
AMD
Asynchronous Module Definition (AMD) is a JavaScript specification that defines an interface for writing and loading modules. The following AMD methods are supported by webpack:
define (with factory)
define([name: String], [dependencies: String[]], factoryMethod: function(...))
If dependencies are provided, factoryMethod will be called with the exports of each dependency (in the same order). If dependencies are not provided, factoryMethod is called with require, exports and module (for compatibility!). If this function returns a value, this value is exported by the module. The compiler ensures that each dependency is available.
Note that webpack ignores the
nameargument.
define(['jquery', 'my-module'], function($, myModule) {
// Do something with $ and myModule...
// Export a function
return function doSomething() {
// ...
};
});
This CANNOT be used in an asynchronous function.
define (with value)
define(value: !Function)
This will simply export the provided value. The value here can be anything except a function.
define({
answer: 42
});
This CANNOT be used in an async function.
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.
require(['b'], function(b) {
var c = require("c");
});
There is no option to provide a chunk name.
Labeled Modules
The internal LabeledModulesPlugin enables you to use the following methods for exporting and requiring within your modules:
export label
Export the given value. The label can occur before a function declaration or a variable declaration. The function name or variable name is the identifier under which the value is exported.
export: var answer = 42;
export: function method(value) {
// Do something...
};
Using it in an async function may not have the expected effect.
require label
Make all exports from the dependency available in the current scope. The require label can occur before a string. The dependency must export values with the export label. CommonJS or AMD modules cannot be consumed.
some-dependency.js
export: var answer = 42;
export: function method(value) {
// Do something...
};
require: 'some-dependency';
console.log(answer);
method(...);
Webpack
Aside from the module syntaxes described above, webpack also allows a few custom, webpack-specific methods:
require.context
require.context(directory:String, includeSubdirs:Boolean /* optional, default true */, filter:RegExp /* optional */)
Specify a whole group of dependencies using a path to the directory, an option to includeSubdirs, and a filter for more fine grained control of the mdoules included. These can then be easily resolved later on.
var context = require.context('components', true, /\.html$/);
var componentA = context.resolve('componentA');
require.include
require.include(dependency: String)
Include a dependency without executing it. This can be used for optimizing the position of a module in the output chunks.
require.include('a');
require.ensure(['a', 'b'], function(require) { /* ... */ });
require.ensure(['a', 'c'], function(require) { /* ... */ });
This will result in following output:
- entry chunk:
file.jsanda - anonymous chunk:
b - anonymous chunk:
c
Without require.include('a') it would be duplicated in both anonymous chunks.
require.resolveWeak
Similar to require.resolve, but this won't pull the module into the bundle. It's what is considered a "weak" dependency.
if(__webpack_modules__[require.resolveWeak('module')]) {
// Do something when module is available...
}
if(require.cache[require.resolveWeak('module')]) {
// Do something when module was loaded before...
}