From 28d9eef5b836d8d7ffae2f2e66664976068fcf7f Mon Sep 17 00:00:00 2001 From: Greg Venech Date: Sat, 24 Jun 2017 13:07:33 -0400 Subject: [PATCH] docs(guides): begin moving code-splitting-async content Much of this content is reference-like and fits more into the module-methods page. The rest is either being moved into code-splitting.md or lazy-loading.md. --- content/api/module-methods.md | 33 ++++++++++++++++++++++++++-- content/guides/code-splitting.md | 37 ++++++++++++++++++++++++++++++++ content/guides/lazy-loading.md | 3 +++ 3 files changed, 71 insertions(+), 2 deletions(-) diff --git a/content/api/module-methods.md b/content/api/module-methods.md index 369e82420d71..7d6846d72d8f 100644 --- a/content/api/module-methods.md +++ b/content/api/module-methods.md @@ -53,7 +53,11 @@ export default { ### `import()` -Dynamically load modules. +`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. + +T> The [ES2015 Loader spec](https://whatwg.github.io/loader/) defines `import()` as method to load ES2015 modules dynamically on runtime. ``` javascript if ( module.hot ) { @@ -63,8 +67,33 @@ if ( module.hot ) { } ``` -The compiler treats this as a split point and will split everything from `lodash` into a separate bundle. This returns a promise that will resolve to the module once the bundle has been loaded. See the [async code splitting guide](/guides/code-splitting-async) for more information. +W> This feature relies on [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) internally. If you use `import()` with older browsers, remember to shim `Promise` using a polyfill such as [es6-promise](https://github.com/stefanpenner/es6-promise) or [promise-polyfill](https://github.com/taylorhakes/promise-polyfill). See [Shimming](/guides/shimming) for more information. + +One problem with direct spec-based usage is that we have no control over the split chunk's name or other properties. Luckily webpack allows some special parameters via comments so as to not break the spec: + +``` js +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 chunk per request, meaning everything is lazy loaded. +- `"lazy-once"`: Generates a single chunk for all possible requests. The first call initiates a network request for all modules, and any following requests are already fulfilled. This is only available for when importing an expression. +- `"eager"`: Generates no chunk. All modules are included in the current chunk and no additional network requests are made. A `Promise` is still returned but is already resolved. In contrast to a static import, the module isn't executed until the request is made. + +T> 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. + +W> Fully dynamic statements, such as `import(foo)`, __will fail__ because webpack requires at least some file location information. This is because `foo` could potentially be any path to any file in your system or project. The `import()` 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. + +W> The entire module namespace is included. For example, ``import(`./locale/${language}.json`)`` will cause every `.json` file in the `./locale` directory to be bundled into the new chunk. At run time, when the variable `language` has been computed, any file like `english.json` or `german.json` will be available for consumption. +W> The use of `System.import` in webpack [did not fit the proposed spec](https://github.com/webpack/webpack/issues/2163), so it was deprecated in webpack [2.1.0-beta.28](https://github.com/webpack/webpack/releases/tag/v2.1.0-beta.28) in favor of `import()`. ## CommonJS diff --git a/content/guides/code-splitting.md b/content/guides/code-splitting.md index 52aba6b6212f..f1d57c5e5ab9 100644 --- a/content/guides/code-splitting.md +++ b/content/guides/code-splitting.md @@ -106,8 +106,45 @@ Here are some other useful plugins and loaders provide by the community for spli ## Dynamic Imports +Two similar techniques are supported by webpack when it comes to dynamic code splitting. The first and more preferable approach is use to the [`import()` syntax](/api/module-methods#import-) that conforms to the [ECMAScript proposal](https://github.com/tc39/proposal-dynamic-import) for dynamic imports. The legacy, webpack-specific approach is to use [`require.ensure`](/api/module-methods#require-ensure). Let's try using the first of these two approaches... + ... +?> Update the following example to match with _Getting Started_ + +__src/index.js__ + +```javascript +function determineDate() { + import('moment').then(function(moment) { + console.log(moment().format()); + }).catch(function(err) { + console.log('Failed to load moment', err); + }); +} + +determineDate(); +``` + +?> Note `async`/`await`... from code-splitting-async: + +> To use ES2017 [`async`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function)/[`await`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await) with `import()`: +> +> ```bash +> npm install --save-dev babel-plugin-transform-async-to-generator babel-plugin-transform-regenerator babel-plugin-transform-runtime babel-plugin-syntax-async-functions +> ``` +> +> __index-es2017.js__ +> +> ```javascript +> async function determineDate() { +> const moment = await import('moment'); +> return moment().format('LLLL'); +> } +> +> determineDate().then(str => console.log(str)); +> ``` + ## Next Steps diff --git a/content/guides/lazy-loading.md b/content/guides/lazy-loading.md index 17c7fa41e4f8..d64b0192a1b0 100644 --- a/content/guides/lazy-loading.md +++ b/content/guides/lazy-loading.md @@ -5,6 +5,9 @@ contributors: - iammerrick - chrisVillanueva - skipjack +related: + - title: Lazy Loading ES2015 Modules in the Browser + url: https://dzone.com/articles/lazy-loading-es2015-modules-in-the-browser --- T> This guide is a small follow-up to [Code Splitting](/guides/code-splitting). If you have not yet read through that guide, please do so now.