magic-comments-loader
Advanced tools
Comparing version 1.2.0 to 1.3.0
@@ -14,3 +14,7 @@ "use strict"; | ||
active: { | ||
type: 'boolean' | ||
oneOf: [{ | ||
type: 'boolean' | ||
}, { | ||
instanceof: 'Function' | ||
}] | ||
} | ||
@@ -22,3 +26,3 @@ }, | ||
const getSchema = (commentSchema = defaultSchema) => ({ | ||
anyOf: [{ | ||
oneOf: [{ | ||
type: 'boolean' | ||
@@ -33,2 +37,4 @@ }, { | ||
}, { | ||
instanceof: 'Function' | ||
}, { | ||
type: 'object', | ||
@@ -46,5 +52,7 @@ properties: { | ||
const getConfig = (value, filepath, defaultConfig = { | ||
const getConfig = (value, match, filepath, importPath, defaultConfig = { | ||
active: true | ||
}) => { | ||
const path = match === 'import' ? importPath.replace(_util.importPrefix, '') : filepath; | ||
if (value === true) { | ||
@@ -56,6 +64,21 @@ return defaultConfig; | ||
return { ...defaultConfig, | ||
active: (0, _util.filepathIsMatch)(filepath, value) | ||
active: (0, _util.pathIsMatch)(path, value) | ||
}; | ||
} | ||
if (typeof value === 'function') { | ||
const configValue = value(filepath, importPath); | ||
if (configValue) { | ||
return { ...defaultConfig, | ||
active: true, | ||
dynamic: configValue | ||
}; | ||
} | ||
return { ...defaultConfig, | ||
active: false | ||
}; | ||
} | ||
let config = { ...defaultConfig, | ||
@@ -72,3 +95,3 @@ ...value.config | ||
for (let i = 0; i < length; i++) { | ||
if ((0, _util.filepathIsMatch)(filepath, overrides[i].files)) { | ||
if ((0, _util.pathIsMatch)(path, overrides[i].files)) { | ||
return { ...config, | ||
@@ -75,0 +98,0 @@ ...overrides[i].config |
@@ -10,6 +10,8 @@ "use strict"; | ||
const getCommenter = (filepath, options) => (match, capturedImportPath) => { | ||
const getCommenter = (filepath, options) => (rgxMatch, capturedImportPath) => { | ||
const importPath = capturedImportPath.trim(); | ||
const bareImportPath = importPath.replace(/['"`]/g, ''); | ||
const { | ||
verbose, | ||
match, | ||
...magicCommentOptions | ||
@@ -21,3 +23,3 @@ } = options; | ||
if (option) { | ||
return _strategy.commentFor[key](filepath, importPath, option); | ||
return _strategy.commentFor[key](filepath, bareImportPath, option, match); | ||
} | ||
@@ -27,3 +29,3 @@ | ||
}).filter(comment => comment); | ||
const magicImport = match.replace(capturedImportPath, `/* ${magicComment.join(', ')} */ ${importPath}`); | ||
const magicImport = rgxMatch.replace(capturedImportPath, magicComment.length > 0 ? `/* ${magicComment.join(', ')} */ ${importPath}` : `${importPath}`); | ||
@@ -30,0 +32,0 @@ if (verbose) { |
@@ -26,2 +26,3 @@ "use strict"; | ||
const magicComments = (0, _comment.getCommenter)(filepath.replace(/^\.\/?/, ''), optionKeys.length > 0 ? options : { | ||
match: 'module', | ||
webpackChunkName: true | ||
@@ -28,0 +29,0 @@ }); |
{ | ||
"name": "magic-comments-loader", | ||
"version": "1.2.0", | ||
"version": "1.3.0", | ||
"description": "Add webpack magic comments to your dynamic imports during build time", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -18,2 +18,4 @@ "use strict"; | ||
var _webpackExports = require("./webpackExports.js"); | ||
const schema = { | ||
@@ -25,2 +27,5 @@ type: 'object', | ||
}, | ||
match: { | ||
enum: ['module', 'import'] | ||
}, | ||
webpackChunkName: _webpackChunkName.schema, | ||
@@ -30,3 +35,4 @@ webpackMode: _webpackMode.schema, | ||
webpackPrefetch: _webpackPrefetch.schema, | ||
webpackPreload: _webpackPreload.schema | ||
webpackPreload: _webpackPreload.schema, | ||
webpackExports: _webpackExports.schema | ||
}, | ||
@@ -33,0 +39,0 @@ additionalProperties: false |
@@ -18,2 +18,4 @@ "use strict"; | ||
var _webpackExports = require("./webpackExports.js"); | ||
const commentFor = { | ||
@@ -24,4 +26,5 @@ webpackChunkName: _webpackChunkName.webpackChunkName, | ||
webpackPreload: _webpackPreload.webpackPreload, | ||
webpackPrefetch: _webpackPrefetch.webpackPrefetch | ||
webpackPrefetch: _webpackPrefetch.webpackPrefetch, | ||
webpackExports: _webpackExports.webpackExports | ||
}; | ||
exports.commentFor = commentFor; |
@@ -6,3 +6,3 @@ "use strict"; | ||
}); | ||
exports.filepathIsMatch = exports.getOverrideSchema = exports.getOverrideConfig = void 0; | ||
exports.importPrefix = exports.pathIsMatch = exports.getOverrideSchema = exports.getOverrideConfig = void 0; | ||
@@ -13,19 +13,3 @@ var _micromatch = _interopRequireDefault(require("micromatch")); | ||
const getOverrideConfig = (overrides, filepath, config) => { | ||
const length = overrides.length; | ||
for (let i = 0; i < length; i++) { | ||
if (filepathIsMatch(filepath, overrides[i].files)) { | ||
return { ...config, | ||
...overrides[i].config | ||
}; | ||
} | ||
} | ||
return config; | ||
}; | ||
exports.getOverrideConfig = getOverrideConfig; | ||
const filepathIsMatch = (filepath, files) => { | ||
const pathIsMatch = (path, files) => { | ||
const globs = []; | ||
@@ -45,6 +29,6 @@ const notglobs = []; | ||
}); | ||
return (globs.length === 0 || globs.some(glob => _micromatch.default.isMatch(filepath, glob))) && notglobs.every(notglob => _micromatch.default.isMatch(filepath, notglob)); | ||
return (globs.length === 0 || globs.some(glob => _micromatch.default.isMatch(path, glob))) && notglobs.every(notglob => _micromatch.default.isMatch(path, notglob)); | ||
}; | ||
exports.filepathIsMatch = filepathIsMatch; | ||
exports.pathIsMatch = pathIsMatch; | ||
@@ -72,2 +56,20 @@ const getOverrideSchema = commentSchema => ({ | ||
exports.getOverrideSchema = getOverrideSchema; | ||
exports.getOverrideSchema = getOverrideSchema; | ||
const getOverrideConfig = (overrides, filepath, config) => { | ||
const length = overrides.length; | ||
for (let i = 0; i < length; i++) { | ||
if (pathIsMatch(filepath, overrides[i].files)) { | ||
return { ...config, | ||
...overrides[i].config | ||
}; | ||
} | ||
} | ||
return config; | ||
}; | ||
exports.getOverrideConfig = getOverrideConfig; | ||
const importPrefix = /^(?:(\.{1,2}\/)+)|^\/|^.+:\/\/\/?[.-\w]+\//; | ||
exports.importPrefix = importPrefix; |
@@ -16,3 +16,7 @@ "use strict"; | ||
active: { | ||
type: 'boolean' | ||
oneOf: [{ | ||
type: 'boolean' | ||
}, { | ||
instanceof: 'Function' | ||
}] | ||
}, | ||
@@ -27,12 +31,17 @@ basename: { | ||
const webpackChunkName = (filepath, importPath, value) => { | ||
const config = (0, _booleanComment.getConfig)(value, filepath, { | ||
const webpackChunkName = (filepath, importPath, value, match) => { | ||
const config = (0, _booleanComment.getConfig)(value, match, filepath, importPath, { | ||
active: true, | ||
basename: false | ||
}); | ||
const isActive = typeof config.active === 'function' ? config.active(filepath, importPath) : config.active; | ||
if (!config.active) { | ||
if (!isActive) { | ||
return ''; | ||
} | ||
if (typeof config.dynamic === 'string') { | ||
return `webpackChunkName: "${config.dynamic}"`; | ||
} | ||
const { | ||
@@ -44,3 +53,3 @@ basename | ||
name | ||
} = (0, _path.parse)(importPath.replace(/['"`]/g, '')); | ||
} = (0, _path.parse)(importPath); | ||
const segments = `${dir}/${name}`.split('/').filter(segment => /\w/.test(segment)); | ||
@@ -47,0 +56,0 @@ const chunkName = basename ? name : segments.reduce((prev, curr) => { |
@@ -13,6 +13,7 @@ "use strict"; | ||
const webpackIgnore = (filepath, importPath, value) => { | ||
const config = (0, _booleanComment.getConfig)(value, filepath); | ||
const webpackIgnore = (filepath, importPath, value, match) => { | ||
const config = (0, _booleanComment.getConfig)(value, match, filepath, importPath); | ||
const isActive = typeof config.active === 'function' ? config.active(filepath, importPath) : config.active; | ||
if (!config.active) { | ||
if (!isActive) { | ||
return ''; | ||
@@ -19,0 +20,0 @@ } |
@@ -15,6 +15,10 @@ "use strict"; | ||
active: { | ||
type: 'boolean' | ||
oneOf: [{ | ||
type: 'boolean' | ||
}, { | ||
instanceof: 'Function' | ||
}] | ||
}, | ||
mode: { | ||
enum: validModes | ||
instanceof: 'Function' | ||
} | ||
@@ -25,9 +29,13 @@ }, | ||
const schema = { | ||
anyOf: [{ | ||
oneOf: [{ | ||
type: 'boolean' | ||
}, { | ||
type: 'string' | ||
}, { | ||
instanceof: 'Function' | ||
}, { | ||
type: 'object', | ||
properties: { | ||
config: configSchema, | ||
overrides: (0, _util.getOverrideSchema)(configSchema.properties) | ||
overrides: (0, _util.getOverrideSchema)(configSchema) | ||
}, | ||
@@ -41,9 +49,13 @@ required: ['config'], | ||
active: true, | ||
mode: 'lazy' | ||
mode: () => 'lazy' | ||
}; | ||
const getConfig = (value, filepath) => { | ||
if (value === true) { | ||
return defaultConfig; | ||
} | ||
if (typeof value === 'string') { | ||
return { ...defaultConfig, | ||
mode: value, | ||
mode: () => value, | ||
active: validModes.includes(value) | ||
@@ -53,2 +65,8 @@ }; | ||
if (typeof value === 'function') { | ||
return { ...defaultConfig, | ||
mode: value | ||
}; | ||
} | ||
let config = { ...defaultConfig, | ||
@@ -67,10 +85,17 @@ ...value.config | ||
const config = getConfig(value, filepath); | ||
const isActive = typeof config.active === 'function' ? config.active(filepath, importPath) : config.active; | ||
if (!config.active) { | ||
if (!isActive || typeof config.mode !== 'function') { | ||
return ''; | ||
} | ||
return `webpackMode: "${config.mode}"`; | ||
const configMode = config.mode(filepath, importPath); | ||
if (!validModes.includes(configMode)) { | ||
return ''; | ||
} | ||
return `webpackMode: "${configMode}"`; | ||
}; | ||
exports.webpackMode = webpackMode; |
@@ -13,6 +13,7 @@ "use strict"; | ||
const webpackPrefetch = (filepath, importPath, value) => { | ||
const config = (0, _booleanComment.getConfig)(value, filepath); | ||
const webpackPrefetch = (filepath, importPath, value, match) => { | ||
const config = (0, _booleanComment.getConfig)(value, match, filepath, importPath); | ||
const isActive = typeof config.active === 'function' ? config.active(filepath, importPath) : config.active; | ||
if (!config.active) { | ||
if (!isActive) { | ||
return ''; | ||
@@ -19,0 +20,0 @@ } |
@@ -13,6 +13,7 @@ "use strict"; | ||
const webpackPreload = (filepath, importPath, value) => { | ||
const config = (0, _booleanComment.getConfig)(value, filepath); | ||
const webpackPreload = (filepath, importPath, value, match) => { | ||
const config = (0, _booleanComment.getConfig)(value, match, filepath, importPath); | ||
const isActive = typeof config.active === 'function' ? config.active(filepath, importPath) : config.active; | ||
if (!config.active) { | ||
if (!isActive) { | ||
return ''; | ||
@@ -19,0 +20,0 @@ } |
{ | ||
"name": "magic-comments-loader", | ||
"version": "1.2.0", | ||
"version": "1.3.0", | ||
"description": "Add webpack magic comments to your dynamic imports during build time", | ||
@@ -5,0 +5,0 @@ "main": "dist", |
124
README.md
@@ -1,6 +0,6 @@ | ||
# magic-comments-loader | ||
# [`magic-comments-loader`](https://www.npmjs.com/package/magic-comments-loader) | ||
Adds [magic coments](https://webpack.js.org/api/module-methods/#magic-comments) to your dynamic import statements. | ||
Adds [magic coments](https://webpack.js.org/api/module-methods/#magic-comments) to your dynamic `import()` statements. | ||
**NOTE**: This loader ignores dynamic imports that already include comments of any kind. | ||
NOTE: **This loader ignores dynamic imports that already include comments of any kind**. | ||
@@ -11,4 +11,5 @@ Magic comments supported: | ||
* `webpackIgnore` | ||
* `webpackPreload` | ||
* `webpackPrefetch` | ||
* [`webpackPreload`](https://webpack.js.org/guides/code-splitting/#prefetchingpreloading-modules) | ||
* [`webpackPrefetch`](https://webpack.js.org/guides/code-splitting/#prefetchingpreloading-modules) | ||
* `webpackExports` | ||
@@ -26,2 +27,3 @@ ## Usage | ||
Adds `webpackChunkName` to all dynamic imports (same as `webpackChunkName: true` when using options). | ||
```js | ||
@@ -41,3 +43,3 @@ module: { | ||
When using the loaders `options` configure the magic comments by using their name as a key in the options object. You can provide a simple value to take on default behavior of the comment. | ||
The loader `options` is an object with keys corresponding to the names of supported magic comments. The following comments have a default behavior and do not require configuration beyond specifying where they should be applied (globally, or to certain files). | ||
@@ -55,3 +57,5 @@ ```js | ||
webpackMode: 'lazy', | ||
webpackPreload: 'src/preload/**/*.js' | ||
webpackIgnore: 'src/ignore/**/*.js', | ||
webpackPreload: ['src/preload/**/*.js', '!src/preload/skip/**/*.js'], | ||
webpackPrefetch: 'src/prefetch/**/*.js' | ||
} | ||
@@ -64,6 +68,10 @@ } | ||
For more control you can provide an object literal with futher configuration options specific | ||
to each comment type. All comment types have a configuration option of `active` which is a boolean to enable | ||
or disable the addition of the magic comment. When using an object literal the configuration must be passed under the `config` key. | ||
#### With `config` options | ||
For more control, all comments support a configuration object with two supported keys, `config` and `overrides`. The `config` key is an object used to specifiy [comment options](#options). The [`overrides`](#overrides) key is defined below. | ||
All comments support a `config.active` key: `Boolean` | `(modulePath, importPath) => Boolean`. This is used to enable or disable the comment. | ||
Here is an example of using `config` to customize comment behavior: | ||
```js | ||
@@ -79,9 +87,15 @@ module: { | ||
webpackChunkName: { | ||
basename: true | ||
config: { | ||
basename: true | ||
} | ||
}, | ||
webpackMode: { | ||
mode: 'lazy-once' | ||
config: { | ||
mode: 'lazy-once' | ||
} | ||
}, | ||
webpackIgnore: { | ||
active: false | ||
config: { | ||
active: false | ||
} | ||
} | ||
@@ -97,3 +111,3 @@ } | ||
You can also override the configuration passed in the `config` key by using `overrides`, which is an array of objects that look like: | ||
You can also override the configuration passed in the `config` key by using `overrides`. It is an array of objects that look like: | ||
@@ -103,7 +117,8 @@ ```js | ||
{ | ||
// Can be an array of strings too | ||
// Can be an array of globs too | ||
files: 'src/**/*.js', | ||
config: { | ||
active: false, | ||
// Possibly other configuration values | ||
active: true, | ||
exports: ['foo', 'bar'] | ||
// Etc. | ||
} | ||
@@ -114,2 +129,4 @@ } | ||
**The `config.match` in an override is ignored. You can only have one, top-level `config.match`**. | ||
Here's a more complete example using `config` and `overrides` to customize how comments are applied: | ||
@@ -146,2 +163,3 @@ | ||
}, | ||
webpackPrefetch: ['src/prefetch/**/*.js', '!src/prefetch/skip/**/*.js'], | ||
webpackMode: { | ||
@@ -176,3 +194,3 @@ config: { | ||
### Magic Comments | ||
## Magic Comments | ||
@@ -186,3 +204,4 @@ With loader options configured like | ||
webpackChunkName: true, | ||
webpackMode: 'lazy' | ||
webpackPrefetch: 'src/some/module.js', | ||
webpackMode: 'eager' | ||
} | ||
@@ -192,6 +211,6 @@ } | ||
an import statement like | ||
an import statement inside `src/some/module.js` like | ||
```js | ||
const dynamicModule = await import('./path/to/some/module') | ||
const dynamicModule = await import('./path/to/module.js') | ||
``` | ||
@@ -202,35 +221,46 @@ | ||
```js | ||
const dynamicModule = await import(/* webpackChunkName: "path-to-some-module", webpackMode: "lazy" */ './path/to/some/module') | ||
const dynamicModule = await import(/* webpackChunkName: "path-to-module", webpackPrefetch: true, webpackMode: "eager" */ './path/to/module.js') | ||
``` | ||
### Options | ||
## Options | ||
These are the options that can be configured under the loader `options`. All comments accept an [`overrides`](#overrides) key in addition to `config` when defined as an object. | ||
These are the options that can be configured under the loader `options`. When using comments with a [`config`](#with-config-options) key, you may also specify [`overrides`](#overrides)(`config.match` is ignored inside overrides). | ||
* `verbose`: Prints console statements of the updated `import()`s per module filepath during the webpack build. Useful for debugging your custom configurations. | ||
* `verbose`: Boolean. Prints console statements of the module filepath and updated `import()` during the webpack build. Useful for debugging your custom configurations. | ||
* `match`: `String(module|import)`. Sets how globs are matched, either the module file path or the `import()` path. Defaults to `'module'`. | ||
* `webpackChunkName` | ||
* `true`: Adds `webpackChunkName` comments to **all** dynamic imports using the full path to the imported module to construct the name, so `import('path/to/module')` becomes `import(/* webpackChunkName: "path-to-module" */ 'path/to/module')`. This is the default. | ||
* `true`: Adds `webpackChunkName` comments to **all** dynamic imports. This is the default. | ||
* `false`: Disables adding the `webpackChunkName` comment globally. | ||
* `some/glob/**/*.js`|`['/some/globs/**/*.js']`: Adds the comment with the default behavior of slugifying (hyphenating) the import path. | ||
* `config.active`: Boolean to enable/disable the comment. | ||
* `config.basename`: Boolean to use only the basename from the import path as the chunk name. Some relative path imports may end up with the same basename depsite importing different modules. Use in areas where you know the basenames are unique. | ||
* `webpackMode` | ||
* `true`: Adds `webpackMode` comments to **all** dynamic imports using `lazy`, so `import('path/to/module')` becomes `import(/* webpackMode: "lazy" */ 'path/to/module')`. | ||
* `false`: Disables adding the `webpackChunkName` comment globally. This is the default. | ||
* `config.active`: Boolean to enable/disable the comment. | ||
* `config.mode`: String to set the mode. `lazy`, `lazy-once`, `eager`, or `weak`. | ||
* `['/src/**/*.js']`: Adds the comment when the glob(s) match a path from a `match` path. | ||
* `Function`: `(modulePath, importPath) => String(<chunk name>)`. Returning `false` does not add the comment. | ||
* `config.active`: Boolean | `(modulePath, importPath) => Boolean`. Returning `false` does not add the comment. | ||
* `config.basename`: Boolean. Use only the basename from the import path as the chunk name. Relative imports may result in name collisions. Use in areas where you know the basenames are unique. | ||
* [`webpackPreload`](https://webpack.js.org/guides/code-splitting/#prefetchingpreloading-modules) | ||
* `true`: Adds `webpackPreload` comments to **all** dynamic imports. | ||
* `false`: Disables adding the `webpackPreload` comment globally. This is the default. | ||
* `['/src/**/*.js']`: Adds the comment with a value of `true` when the glob(s) match a path from a `match` path. | ||
* `Function`: `(modulePath, importPath) => Boolean`. Returning `false` does not add the comment. | ||
* `config.active`: Boolean | `(modulePath, importPath) => Boolean`. Returning `false` does not add the comment. | ||
* [`webpackPrefetch`](https://webpack.js.org/guides/code-splitting/#prefetchingpreloading-modules) | ||
* `true`: Adds `webpackPrefetch` comments to **all** dynamic imports. | ||
* `false`: Disables adding the `webpackPrefetch` comment globally. This is the default. | ||
* `['/src/**/*.js']`: Adds the comment with a value of `true` when the glob(s) match a path from a `match` path. | ||
* `Function`: `(modulePath, importPath) => Boolean`. Returning `false` does not add the comment. | ||
* `config.active`: Boolean | `(modulePath, importPath) => Boolean`. Returning `false` does not add the comment. | ||
* `webpackIgnore` | ||
* `true`: Adds `webpackIgnore` comments to **all** dynamic imports, so `import('path/to/module')` becomes `import(/* webpackIgnore: true */ 'path/to/module')`. | ||
* `true`: Adds `webpackIgnore` comments to **all** dynamic imports. **You don't want to do this**. | ||
* `false`: Disables adding the `webpackIgnore` comment globally. This is the default. | ||
* `some/glob/**/*.js`|`['/some/globs/**/*.js']`: Adds the comment with a value of `true` to all module filepaths that match the string or array of strings. | ||
* `config.active`: Boolean to enable/disable the comment. | ||
* `webpackPreload` | ||
* `true`: Adds `webpackPreload` comments to **all** dynamic imports, so `import('path/to/module')` becomes `import(/* webpackPreload: true */ 'path/to/module')`. | ||
* `false`: Disables adding the `webpackPreload` comment globally. This is the default. | ||
* `some/glob/**/*.js`|`['/some/globs/**/*.js']`: Adds the comment with a value of `true` to all module filepaths that match the string or array of strings. | ||
* `config.active`: Boolean to enable/disable the comment. | ||
* `webpackPrefetch` | ||
* `true`: Adds `webpackPrefetch` comments to **all** dynamic imports, so `import('path/to/module')` becomes `import(/* webpackPrefetch: true */ 'path/to/module')`. | ||
* `false`: Disables adding the `webpackPrefetch` comment globally. This is the default. | ||
* `some/glob/**/*.js`|`['/some/globs/**/*.js']`: Adds the comment with a value of `true` to all module filepaths that match the string or array of strings. | ||
* `config.active`: Boolean to enable/disable the comment. | ||
* `['/src/**/*.js']`: Adds the comment with a value of `true` when the glob(s) match a path from a `match` path. | ||
* `Function`: `(modulePath, importPath) => Boolean`. Returning `false` does not add the comment. | ||
* `config.active`: Boolean | `(modulePath, importPath) => Boolean`. Returning `false` does not add the comment. | ||
* `webpackMode` | ||
* `true`: Adds `webpackMode` comments to **all** dynamic imports using `lazy`. | ||
* `false`: Disables adding the comment globally. This is the default. | ||
* `String(lazy|lazy-once|eager|weak)`: Adds the comment to **all** dynamic imports using the provided value. | ||
* `Function`: `(modulePath, importPath) => String(lazy|lazy-once|eager|weak)`. Return falsy value to skip. | ||
* `config.active`: Boolean | `(modulePath, importPath) => Boolean`. Returning `false` does not add the comment. | ||
* `config.mode`: `(modulePath, importPath) => String(lazy|lazy-once|eager|weak)`. Return falsy value to skip. | ||
* `webpackExports` | ||
* `Function`: `(modulePath, importPath) => [String(<module names|default>)]`. Return falsy value to skip. | ||
* `config.active`: Boolean | `(modulePath, importPath) => Boolean`. Returning `false` does not add the comment. | ||
* `config.exports`: `(modulePath, importPath) => [String(<module names|default>)]`. Return falsy value to skip. |
27637
17
558
253