From dee75945ddee1738ce1fbef1534f4a6cbea79b68 Mon Sep 17 00:00:00 2001 From: fi3ework Date: Mon, 5 Aug 2024 17:52:06 +0800 Subject: [PATCH 1/4] docs(externals): add `import` and `module-import` external type --- src/content/configuration/externals.mdx | 98 +++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/src/content/configuration/externals.mdx b/src/content/configuration/externals.mdx index 2e2e31b8df99..5e03cde36dda 100644 --- a/src/content/configuration/externals.mdx +++ b/src/content/configuration/externals.mdx @@ -19,6 +19,7 @@ contributors: - kinetifex - anshumanv - SaulSilver + - fi3ework --- The `externals` configuration option provides a way of excluding dependencies from the output bundles. Instead, the created bundle relies on that dependency to be present in the consumer's (any end-user application) environment. This feature is typically most useful to **library developers**, however there are a variety of applications for it. @@ -474,6 +475,103 @@ jq('.my-element').animate(/* ... */); Note that there will be an `import` statement in the output bundle. +### externalsType.import + +Specify the default type of externals as `'import'`. Webpack will generate code like `import('...')` for externals used in a module. + +#### Example + +```javascript +async function foo() { + const jq = await import('jQuery'); + jq('.my-element').animate(/* ... */); +} +``` + +**webpack.config.js** + +```js +module.exports = { + externalsType: 'import', + externals: { + jquery: 'jquery', + }, +}; +``` + +Will generate into something like + +```javascript +var __webpack_modules__ = { + jQuery: (module) => { + module.exports = import('jQuery'); + }, +}; + +// webpack runtime... + +async function foo() { + const jq = await Promise.resolve(/* import() */).then( + __webpack_require__.bind(__webpack_require__, 'jQuery') + ); + jq('.my-element').animate(/* ... */); +} +``` + +Note that there will be an `import()` statement in the output bundle. + +### externalsType['module-import'] + +Specify the default type of externals as `'module-import'`. This combines [`'module'`](#externalstypemodule) and [`'import'`](#externalstypeimport). Webpack will automatically detect the type of import syntax, setting it to `'module'` for static imports and `'import'` for dynamic imports. + +Make sure to enable [`experiments.outputModule`](/configuration/experiments/#experimentsoutputmodule) first if static imports exist, otherwise webpack will throw errors. + +#### Example + +```javascript +import { attempt } from 'lodash'; + +async function foo() { + const jq = await import('jQuery'); + attempt(() => jq('.my-element').animate(/* ... */)); +} +``` + +**webpack.config.js** + +```js +module.exports = { + externalsType: 'import', + externals: { + jquery: 'jquery', + }, +}; +``` + +Will generate into something like + +```javascript +import * as __WEBPACK_EXTERNAL_MODULE_lodash__ from 'lodash'; +const lodash = __WEBPACK_EXTERNAL_MODULE_jquery__; + +var __webpack_modules__ = { + jQuery: (module) => { + module.exports = import('jQuery'); + }, +}; + +// webpack runtime... + +async function foo() { + const jq = await Promise.resolve(/* import() */).then( + __webpack_require__.bind(__webpack_require__, 'jQuery') + ); + (0, lodash.attempt)(() => jq('.my-element').animate(/* ... */)); +} +``` + +Note that there will be an `import` or `import()` statement in the output bundle. + ### externalsType.node-commonjs Specify the default type of externals as `'node-commonjs'`. Webpack will import [`createRequire`](https://nodejs.org/api/module.html#module_module_createrequire_filename) from `'module'` to construct a require function for loading externals used in a module. From 4866c328909e7208d6608f6ae0a25ad1b4ea96f8 Mon Sep 17 00:00:00 2001 From: fi3ework Date: Thu, 15 Aug 2024 00:46:09 +0800 Subject: [PATCH 2/4] fix: update docs --- src/content/configuration/externals.mdx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/content/configuration/externals.mdx b/src/content/configuration/externals.mdx index 5e03cde36dda..74bfb2799957 100644 --- a/src/content/configuration/externals.mdx +++ b/src/content/configuration/externals.mdx @@ -354,6 +354,8 @@ Supported types: - `'import'` - uses `import()` to load a native EcmaScript module (async module) - `'jsonp'` - [`'module'`](#externalstypemodule) +- [`'import'`](#externalstypeimport) +- [`'module-import'`](#externalstypemodule-import) - [`'node-commonjs'`](#externalstypenode-commonjs) - [`'promise'`](#externalstypepromise) - same as `'var'` but awaits the result (async module) - [`'self'`](#externalstypeself) @@ -520,7 +522,7 @@ async function foo() { Note that there will be an `import()` statement in the output bundle. -### externalsType['module-import'] +### externalsType.module-import Specify the default type of externals as `'module-import'`. This combines [`'module'`](#externalstypemodule) and [`'import'`](#externalstypeimport). Webpack will automatically detect the type of import syntax, setting it to `'module'` for static imports and `'import'` for dynamic imports. @@ -572,6 +574,14 @@ async function foo() { Note that there will be an `import` or `import()` statement in the output bundle. +When a module is not imported via `import` or `import()`, webpack will determine which type of external to use as fallback based on the configuration of [`externalsPresets`](#externalspresets). When one of the previous `externalsPresets` type is enabled, the following `externalsPresets` type will no longer apply. The order is listed below. + +- When `externalsPresets.web` is `true`, use `module`. +- When `externalsPresets.webAsync` is `true`, use `import`. +- When node.js related (`electron`, `electronMain`, `electronPreload`, `electronRenderer`, `node`, `nwjs`) externalsPresets is true, use `node-commonjs`. + +When none of the above `externalsPresets` type is enabled or can be derived, webpack will use `commonjs` as the default type. + ### externalsType.node-commonjs Specify the default type of externals as `'node-commonjs'`. Webpack will import [`createRequire`](https://nodejs.org/api/module.html#module_module_createrequire_filename) from `'module'` to construct a require function for loading externals used in a module. From 71e643477a49f736308c76adc28f2fbc965a4707 Mon Sep 17 00:00:00 2001 From: fi3ework Date: Fri, 23 Aug 2024 02:24:16 +0800 Subject: [PATCH 3/4] fix: remove fallback --- src/content/configuration/externals.mdx | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/content/configuration/externals.mdx b/src/content/configuration/externals.mdx index 74bfb2799957..7b1a6da3d4c3 100644 --- a/src/content/configuration/externals.mdx +++ b/src/content/configuration/externals.mdx @@ -574,13 +574,23 @@ async function foo() { Note that there will be an `import` or `import()` statement in the output bundle. -When a module is not imported via `import` or `import()`, webpack will determine which type of external to use as fallback based on the configuration of [`externalsPresets`](#externalspresets). When one of the previous `externalsPresets` type is enabled, the following `externalsPresets` type will no longer apply. The order is listed below. +When a module is not imported via `import` or `import()`, webpack will use `"module"` externals type as fallback. If you want to use a different type of externals as fallback, you can specify it with a function in the `externals` option. For example: -- When `externalsPresets.web` is `true`, use `module`. -- When `externalsPresets.webAsync` is `true`, use `import`. -- When node.js related (`electron`, `electronMain`, `electronPreload`, `electronRenderer`, `node`, `nwjs`) externalsPresets is true, use `node-commonjs`. - -When none of the above `externalsPresets` type is enabled or can be derived, webpack will use `commonjs` as the default type. +```js +module.exports = { + externalsType: "module-import", + externals: [ + function ( + { request, dependencyType }, + callback + ) { + if (dependencyType === "commonjs") { + return callback(null, `node-commonjs ${request}`); + } + callback(); + }, + ] +``` ### externalsType.node-commonjs From 69d1f0ee60fe8131eb4d69c7d6955567048c5321 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Sat, 24 Aug 2024 16:40:04 +0530 Subject: [PATCH 4/4] docs: apply suggestions from code review --- src/content/configuration/externals.mdx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/content/configuration/externals.mdx b/src/content/configuration/externals.mdx index 7b1a6da3d4c3..6700150ed5d0 100644 --- a/src/content/configuration/externals.mdx +++ b/src/content/configuration/externals.mdx @@ -501,7 +501,7 @@ module.exports = { }; ``` -Will generate into something like +Will generate something like below: ```javascript var __webpack_modules__ = { @@ -520,13 +520,13 @@ async function foo() { } ``` -Note that there will be an `import()` statement in the output bundle. +Note that the output bundle will have an `import()` statement. ### externalsType.module-import Specify the default type of externals as `'module-import'`. This combines [`'module'`](#externalstypemodule) and [`'import'`](#externalstypeimport). Webpack will automatically detect the type of import syntax, setting it to `'module'` for static imports and `'import'` for dynamic imports. -Make sure to enable [`experiments.outputModule`](/configuration/experiments/#experimentsoutputmodule) first if static imports exist, otherwise webpack will throw errors. +Ensure to enable [`experiments.outputModule`](/configuration/experiments/#experimentsoutputmodule) first if static imports exist, otherwise, webpack will throw errors. #### Example @@ -550,7 +550,7 @@ module.exports = { }; ``` -Will generate into something like +Will generate something like below: ```javascript import * as __WEBPACK_EXTERNAL_MODULE_lodash__ from 'lodash'; @@ -572,9 +572,9 @@ async function foo() { } ``` -Note that there will be an `import` or `import()` statement in the output bundle. +Note that the output bundle will have an `import` or `import()` statement. -When a module is not imported via `import` or `import()`, webpack will use `"module"` externals type as fallback. If you want to use a different type of externals as fallback, you can specify it with a function in the `externals` option. For example: +When a module is not imported via `import` or `import()`, webpack will use the `"module"` externals type as a fallback. If you want to use a different kind of externals as a fallback, you can specify it with a function in the `externals` option. For example: ```js module.exports = {