diff --git a/declarations/WebpackOptions.d.ts b/declarations/WebpackOptions.d.ts index 29f6fd16a..8de86d72a 100644 --- a/declarations/WebpackOptions.d.ts +++ b/declarations/WebpackOptions.d.ts @@ -266,6 +266,30 @@ export type RuleSetLoaderOptions = | { [k: string]: any; }; +/** + * Redirect module requests. + */ +export type ResolveAlias = + | { + /** + * New request. + */ + alias: string[] | false | string; + /** + * Request to be redirected. + */ + name: string; + /** + * Redirect only exact matching request. + */ + onlyModule?: boolean; + }[] + | { + /** + * New request. + */ + [k: string]: string[] | false | string; + }; /** * A list of descriptions of loaders applied. */ @@ -1167,27 +1191,7 @@ export interface ResolveOptions { /** * Redirect module requests. */ - alias?: - | { - /** - * New request. - */ - alias: string[] | false | string; - /** - * Request to be redirected. - */ - name: string; - /** - * Redirect only exact matching request. - */ - onlyModule?: boolean; - }[] - | { - /** - * New request. - */ - [k: string]: string[] | false | string; - }; + alias?: ResolveAlias; /** * Fields in the description file (usually package.json) which are used to redirect requests inside the module. */ @@ -1235,6 +1239,10 @@ export interface ResolveOptions { * Extensions added to the request when trying to find the file. */ extensions?: string[]; + /** + * Redirect module requests when normal resolving fails. + */ + fallback?: ResolveAlias; /** * Filesystem for the resolver. */ @@ -1243,6 +1251,10 @@ export interface ResolveOptions { * Treats the request specified by the user as fully specified, meaning no extensions are added and the mainFiles in directories are not resolved (This doesn't affect requests from mainFields, aliasFields or aliases). */ fullySpecified?: boolean; + /** + * Field names from the description file (usually package.json) which are used to provide internal request of a package (requests starting with # are considered as internal). + */ + importsFields?: string[]; /** * Field names from the description file (package.json) which are used to find the default entry point. */ diff --git a/lib/ModuleNotFoundError.js b/lib/ModuleNotFoundError.js index 62274195d..a4dfde194 100644 --- a/lib/ModuleNotFoundError.js +++ b/lib/ModuleNotFoundError.js @@ -66,14 +66,14 @@ class ModuleNotFoundError extends WebpackError { if (request !== alias) { message += "If you want to include a polyfill, you need to:\n" + - `\t- add an alias 'resolve.alias: { "${request}": "${alias}" }'\n` + + `\t- add an fallback 'resolve.fallback: { "${request}": "${alias}" }'\n` + `\t- install '${dependency}'\n`; } else { message += `If you want to include a polyfill, you need to install '${dependency}'.\n`; } message += "If you don't want to include a polyfill, you can use an empty module like this:\n" + - `\tresolve.alias: { "${request}": false }`; + `\tresolve.fallback: { "${request}": false }`; } } diff --git a/package.json b/package.json index cb18ee887..3af0f3106 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "@webassemblyjs/wasm-parser": "1.9.0", "acorn": "^7.4.0", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "5.0.0-beta.10", + "enhanced-resolve": "5.0.0-beta.12", "eslint-scope": "^5.1.0", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", diff --git a/schemas/WebpackOptions.json b/schemas/WebpackOptions.json index 67037e099..46a6ef79e 100644 --- a/schemas/WebpackOptions.json +++ b/schemas/WebpackOptions.json @@ -2200,67 +2200,17 @@ } ] }, - "ResolveLoader": { - "description": "Options for the resolver when resolving loaders.", - "oneOf": [ + "ResolveAlias": { + "description": "Redirect module requests.", + "anyOf": [ { - "$ref": "#/definitions/ResolveOptions" - } - ] - }, - "ResolveOptions": { - "description": "Options object for resolving requests.", - "type": "object", - "additionalProperties": false, - "properties": { - "alias": { - "description": "Redirect module requests.", - "anyOf": [ - { - "type": "array", - "items": { - "description": "Alias configuration.", - "type": "object", - "additionalProperties": false, - "properties": { - "alias": { - "description": "New request.", - "anyOf": [ - { - "description": "Multiple alternative requests.", - "type": "array", - "items": { - "description": "One choice of request.", - "type": "string", - "minLength": 1 - } - }, - { - "description": "Ignore request (replace with empty module).", - "enum": [false] - }, - { - "description": "New request.", - "type": "string", - "minLength": 1 - } - ] - }, - "name": { - "description": "Request to be redirected.", - "type": "string" - }, - "onlyModule": { - "description": "Redirect only exact matching request.", - "type": "boolean" - } - }, - "required": ["alias", "name"] - } - }, - { - "type": "object", - "additionalProperties": { + "type": "array", + "items": { + "description": "Alias configuration.", + "type": "object", + "additionalProperties": false, + "properties": { + "alias": { "description": "New request.", "anyOf": [ { @@ -2282,9 +2232,62 @@ "minLength": 1 } ] + }, + "name": { + "description": "Request to be redirected.", + "type": "string" + }, + "onlyModule": { + "description": "Redirect only exact matching request.", + "type": "boolean" } - } - ] + }, + "required": ["alias", "name"] + } + }, + { + "type": "object", + "additionalProperties": { + "description": "New request.", + "anyOf": [ + { + "description": "Multiple alternative requests.", + "type": "array", + "items": { + "description": "One choice of request.", + "type": "string", + "minLength": 1 + } + }, + { + "description": "Ignore request (replace with empty module).", + "enum": [false] + }, + { + "description": "New request.", + "type": "string", + "minLength": 1 + } + ] + } + } + ] + }, + "ResolveLoader": { + "description": "Options for the resolver when resolving loaders.", + "oneOf": [ + { + "$ref": "#/definitions/ResolveOptions" + } + ] + }, + "ResolveOptions": { + "description": "Options object for resolving requests.", + "type": "object", + "additionalProperties": false, + "properties": { + "alias": { + "$ref": "#/definitions/ResolveAlias" }, "aliasFields": { "description": "Fields in the description file (usually package.json) which are used to redirect requests inside the module.", @@ -2370,6 +2373,14 @@ "minLength": 1 } }, + "fallback": { + "description": "Redirect module requests when normal resolving fails.", + "oneOf": [ + { + "$ref": "#/definitions/ResolveAlias" + } + ] + }, "fileSystem": { "description": "Filesystem for the resolver.", "tsType": "(import('../lib/util/fs').InputFileSystem)" @@ -2378,6 +2389,14 @@ "description": "Treats the request specified by the user as fully specified, meaning no extensions are added and the mainFiles in directories are not resolved (This doesn't affect requests from mainFields, aliasFields or aliases).", "type": "boolean" }, + "importsFields": { + "description": "Field names from the description file (usually package.json) which are used to provide internal request of a package (requests starting with # are considered as internal).", + "type": "array", + "items": { + "description": "Field name from the description file (usually package.json) which is used to provide internal request of a package (requests starting with # are considered as internal).", + "type": "string" + } + }, "mainFields": { "description": "Field names from the description file (package.json) which are used to find the default entry point.", "type": "array", diff --git a/test/__snapshots__/Cli.test.js.snap b/test/__snapshots__/Cli.test.js.snap index ea32aa56a..b810c36ce 100644 --- a/test/__snapshots__/Cli.test.js.snap +++ b/test/__snapshots__/Cli.test.js.snap @@ -3359,6 +3359,67 @@ Object { "multiple": false, "simpleType": "boolean", }, + "resolve-fallback-alias": Object { + "configs": Array [ + Object { + "description": "Ignore request (replace with empty module).", + "multiple": true, + "path": "resolve.fallback[].alias", + "type": "enum", + "values": Array [ + false, + ], + }, + Object { + "description": "New request.", + "multiple": true, + "path": "resolve.fallback[].alias", + "type": "string", + }, + ], + "description": "Ignore request (replace with empty module). New request.", + "multiple": true, + "simpleType": "string", + }, + "resolve-fallback-name": Object { + "configs": Array [ + Object { + "description": "Request to be redirected.", + "multiple": true, + "path": "resolve.fallback[].name", + "type": "string", + }, + ], + "description": "Request to be redirected.", + "multiple": true, + "simpleType": "string", + }, + "resolve-fallback-only-module": Object { + "configs": Array [ + Object { + "description": "Redirect only exact matching request.", + "multiple": true, + "path": "resolve.fallback[].onlyModule", + "type": "boolean", + }, + ], + "description": "Redirect only exact matching request.", + "multiple": true, + "simpleType": "boolean", + }, + "resolve-fallback-reset": Object { + "configs": Array [ + Object { + "description": "Clear all items provided in configuration. Redirect module requests.", + "multiple": false, + "path": "resolve.fallback", + "type": "reset", + }, + ], + "description": "Clear all items provided in configuration. Redirect module requests.", + "multiple": false, + "simpleType": "boolean", + }, "resolve-fully-specified": Object { "configs": Array [ Object { @@ -3372,6 +3433,32 @@ Object { "multiple": false, "simpleType": "boolean", }, + "resolve-imports-fields": Object { + "configs": Array [ + Object { + "description": "Field name from the description file (usually package.json) which is used to provide internal request of a package (requests starting with # are considered as internal).", + "multiple": true, + "path": "resolve.importsFields[]", + "type": "string", + }, + ], + "description": "Field name from the description file (usually package.json) which is used to provide internal request of a package (requests starting with # are considered as internal).", + "multiple": true, + "simpleType": "string", + }, + "resolve-imports-fields-reset": Object { + "configs": Array [ + Object { + "description": "Clear all items provided in configuration. Field names from the description file (usually package.json) which are used to provide internal request of a package (requests starting with # are considered as internal).", + "multiple": false, + "path": "resolve.importsFields", + "type": "reset", + }, + ], + "description": "Clear all items provided in configuration. Field names from the description file (usually package.json) which are used to provide internal request of a package (requests starting with # are considered as internal).", + "multiple": false, + "simpleType": "boolean", + }, "resolve-loader-alias-alias": Object { "configs": Array [ Object { @@ -3602,6 +3689,67 @@ Object { "multiple": false, "simpleType": "boolean", }, + "resolve-loader-fallback-alias": Object { + "configs": Array [ + Object { + "description": "Ignore request (replace with empty module).", + "multiple": true, + "path": "resolveLoader.fallback[].alias", + "type": "enum", + "values": Array [ + false, + ], + }, + Object { + "description": "New request.", + "multiple": true, + "path": "resolveLoader.fallback[].alias", + "type": "string", + }, + ], + "description": "Ignore request (replace with empty module). New request.", + "multiple": true, + "simpleType": "string", + }, + "resolve-loader-fallback-name": Object { + "configs": Array [ + Object { + "description": "Request to be redirected.", + "multiple": true, + "path": "resolveLoader.fallback[].name", + "type": "string", + }, + ], + "description": "Request to be redirected.", + "multiple": true, + "simpleType": "string", + }, + "resolve-loader-fallback-only-module": Object { + "configs": Array [ + Object { + "description": "Redirect only exact matching request.", + "multiple": true, + "path": "resolveLoader.fallback[].onlyModule", + "type": "boolean", + }, + ], + "description": "Redirect only exact matching request.", + "multiple": true, + "simpleType": "boolean", + }, + "resolve-loader-fallback-reset": Object { + "configs": Array [ + Object { + "description": "Clear all items provided in configuration. Redirect module requests.", + "multiple": false, + "path": "resolveLoader.fallback", + "type": "reset", + }, + ], + "description": "Clear all items provided in configuration. Redirect module requests.", + "multiple": false, + "simpleType": "boolean", + }, "resolve-loader-fully-specified": Object { "configs": Array [ Object { @@ -3615,6 +3763,32 @@ Object { "multiple": false, "simpleType": "boolean", }, + "resolve-loader-imports-fields": Object { + "configs": Array [ + Object { + "description": "Field name from the description file (usually package.json) which is used to provide internal request of a package (requests starting with # are considered as internal).", + "multiple": true, + "path": "resolveLoader.importsFields[]", + "type": "string", + }, + ], + "description": "Field name from the description file (usually package.json) which is used to provide internal request of a package (requests starting with # are considered as internal).", + "multiple": true, + "simpleType": "string", + }, + "resolve-loader-imports-fields-reset": Object { + "configs": Array [ + Object { + "description": "Clear all items provided in configuration. Field names from the description file (usually package.json) which are used to provide internal request of a package (requests starting with # are considered as internal).", + "multiple": false, + "path": "resolveLoader.importsFields", + "type": "reset", + }, + ], + "description": "Clear all items provided in configuration. Field names from the description file (usually package.json) which are used to provide internal request of a package (requests starting with # are considered as internal).", + "multiple": false, + "simpleType": "boolean", + }, "resolve-loader-main-fields": Object { "configs": Array [ Object { diff --git a/test/__snapshots__/StatsTestCases.test.js.snap b/test/__snapshots__/StatsTestCases.test.js.snap index 9af212173..5874bf5b4 100644 --- a/test/__snapshots__/StatsTestCases.test.js.snap +++ b/test/__snapshots__/StatsTestCases.test.js.snap @@ -1253,7 +1253,7 @@ This is no longer the case. Verify if you need this module and configure a polyf If you want to include a polyfill, you need to install 'buffer'. If you don't want to include a polyfill, you can use an empty module like this: - resolve.alias: { \\"buffer\\": false } + resolve.fallback: { \\"buffer\\": false } ERROR in ./index.js 2:0-13 Module not found: Error: Can't resolve 'os' in 'Xdir/module-not-found-error' @@ -1262,10 +1262,10 @@ BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules This is no longer the case. Verify if you need this module and configure a polyfill for it. If you want to include a polyfill, you need to: - - add an alias 'resolve.alias: { \\"os\\": \\"os-browserify/browser\\" }' + - add an fallback 'resolve.fallback: { \\"os\\": \\"os-browserify/browser\\" }' - install 'os-browserify' If you don't want to include a polyfill, you can use an empty module like this: - resolve.alias: { \\"os\\": false } + resolve.fallback: { \\"os\\": false } webpack compiled with 2 errors" `; diff --git a/types.d.ts b/types.d.ts index 4685c897b..9e5ff7b89 100644 --- a/types.d.ts +++ b/types.d.ts @@ -364,6 +364,15 @@ declare interface BannerPluginOptions { */ test?: Rules; } +declare interface BaseResolveRequest { + path: DevTool; + descriptionFilePath?: string; + descriptionFileRoot?: string; + descriptionFileData?: any; + relativePath?: string; + ignoreSymlinks?: boolean; + fullySpecified?: boolean; +} declare abstract class BasicEvaluatedExpression { type: number; range: [number, number]; @@ -6340,6 +6349,7 @@ declare interface ParsedIdentifier { directory: boolean; module: boolean; file: boolean; + internal: boolean; } declare class Parser { constructor(); @@ -6802,6 +6812,22 @@ declare abstract class RequestShortener { contextify: (arg0: string) => string; shorten(request: string): string; } +type ResolveAlias = + | { + /** + * New request. + */ + alias: string | false | string[]; + /** + * Request to be redirected. + */ + name: string; + /** + * Redirect only exact matching request. + */ + onlyModule?: boolean; + }[] + | { [index: string]: string | false | string[] }; declare interface ResolveBuildDependenciesResult { /** * list of files @@ -6899,6 +6925,20 @@ declare interface ResolveOptionsTypes { */ onlyModule?: boolean; }[]; + fallback: { + /** + * New request. + */ + alias: string | false | string[]; + /** + * Request to be redirected. + */ + name: string; + /** + * Redirect only exact matching request. + */ + onlyModule?: boolean; + }[]; aliasFields: Set; cachePredicate: (arg0: ResolveRequest) => boolean; cacheWithContext: boolean; @@ -6910,6 +6950,7 @@ declare interface ResolveOptionsTypes { descriptionFiles: string[]; enforceExtension: boolean; exportsFields: Set; + importsFields: Set; extensions: Set; fileSystem: FileSystem; unsafeCache: any; @@ -6936,22 +6977,7 @@ declare interface ResolveOptionsWebpackOptions { /** * Redirect module requests. */ - alias?: - | { - /** - * New request. - */ - alias: string | false | string[]; - /** - * Request to be redirected. - */ - name: string; - /** - * Redirect only exact matching request. - */ - onlyModule?: boolean; - }[] - | { [index: string]: string | false | string[] }; + alias?: ResolveAlias; /** * Fields in the description file (usually package.json) which are used to redirect requests inside the module. @@ -7003,6 +7029,11 @@ declare interface ResolveOptionsWebpackOptions { */ extensions?: string[]; + /** + * Redirect module requests when normal resolving fails. + */ + fallback?: ResolveAlias; + /** * Filesystem for the resolver. */ @@ -7013,6 +7044,11 @@ declare interface ResolveOptionsWebpackOptions { */ fullySpecified?: boolean; + /** + * Field names from the description file (usually package.json) which are used to provide internal request of a package (requests starting with # are considered as internal). + */ + importsFields?: string[]; + /** * Field names from the description file (package.json) which are used to find the default entry point. */ @@ -7075,20 +7111,7 @@ declare interface ResolvePluginInstance { */ apply: (resolver?: any) => void; } -declare interface ResolveRequest { - path: DevTool; - request?: string; - query?: string; - fragment?: string; - directory?: boolean; - module?: boolean; - descriptionFilePath?: string; - descriptionFileRoot?: string; - descriptionFileData?: any; - relativePath?: string; - ignoreSymlinks?: boolean; - fullySpecified?: boolean; -} +type ResolveRequest = BaseResolveRequest & Partial; declare abstract class Resolver { fileSystem: FileSystem; options: ResolveOptionsTypes; @@ -7134,6 +7157,7 @@ declare abstract class Resolver { ): any; parse(identifier: string): ParsedIdentifier; isModule(path?: any): boolean; + isPrivate(path?: any): boolean; isDirectory(path: string): boolean; join(path?: any, request?: any): string; normalize(path?: any): string; @@ -7151,22 +7175,7 @@ declare abstract class ResolverFactory { /** * Redirect module requests. */ - alias?: - | { - /** - * New request. - */ - alias: string | false | string[]; - /** - * Request to be redirected. - */ - name: string; - /** - * Redirect only exact matching request. - */ - onlyModule?: boolean; - }[] - | { [index: string]: string | false | string[] }; + alias?: ResolveAlias; /** * Fields in the description file (usually package.json) which are used to redirect requests inside the module. */ @@ -7207,6 +7216,10 @@ declare abstract class ResolverFactory { * Extensions added to the request when trying to find the file. */ extensions?: string[]; + /** + * Redirect module requests when normal resolving fails. + */ + fallback?: ResolveAlias; /** * Filesystem for the resolver. */ @@ -7215,6 +7228,10 @@ declare abstract class ResolverFactory { * Treats the request specified by the user as fully specified, meaning no extensions are added and the mainFiles in directories are not resolved (This doesn't affect requests from mainFields, aliasFields or aliases). */ fullySpecified?: boolean; + /** + * Field names from the description file (usually package.json) which are used to provide internal request of a package (requests starting with # are considered as internal). + */ + importsFields?: string[]; /** * Field names from the description file (package.json) which are used to find the default entry point. */ @@ -7270,22 +7287,7 @@ declare abstract class ResolverFactory { /** * Redirect module requests. */ - alias?: - | { - /** - * New request. - */ - alias: string | false | string[]; - /** - * Request to be redirected. - */ - name: string; - /** - * Redirect only exact matching request. - */ - onlyModule?: boolean; - }[] - | { [index: string]: string | false | string[] }; + alias?: ResolveAlias; /** * Fields in the description file (usually package.json) which are used to redirect requests inside the module. */ @@ -7326,6 +7328,10 @@ declare abstract class ResolverFactory { * Extensions added to the request when trying to find the file. */ extensions?: string[]; + /** + * Redirect module requests when normal resolving fails. + */ + fallback?: ResolveAlias; /** * Filesystem for the resolver. */ @@ -7334,6 +7340,10 @@ declare abstract class ResolverFactory { * Treats the request specified by the user as fully specified, meaning no extensions are added and the mainFiles in directories are not resolved (This doesn't affect requests from mainFields, aliasFields or aliases). */ fullySpecified?: boolean; + /** + * Field names from the description file (usually package.json) which are used to provide internal request of a package (requests starting with # are considered as internal). + */ + importsFields?: string[]; /** * Field names from the description file (package.json) which are used to find the default entry point. */ @@ -7389,22 +7399,7 @@ declare abstract class ResolverFactory { /** * Redirect module requests. */ - alias?: - | { - /** - * New request. - */ - alias: string | false | string[]; - /** - * Request to be redirected. - */ - name: string; - /** - * Redirect only exact matching request. - */ - onlyModule?: boolean; - }[] - | { [index: string]: string | false | string[] }; + alias?: ResolveAlias; /** * Fields in the description file (usually package.json) which are used to redirect requests inside the module. */ @@ -7445,6 +7440,10 @@ declare abstract class ResolverFactory { * Extensions added to the request when trying to find the file. */ extensions?: string[]; + /** + * Redirect module requests when normal resolving fails. + */ + fallback?: ResolveAlias; /** * Filesystem for the resolver. */ @@ -7453,6 +7452,10 @@ declare abstract class ResolverFactory { * Treats the request specified by the user as fully specified, meaning no extensions are added and the mainFiles in directories are not resolved (This doesn't affect requests from mainFields, aliasFields or aliases). */ fullySpecified?: boolean; + /** + * Field names from the description file (usually package.json) which are used to provide internal request of a package (requests starting with # are considered as internal). + */ + importsFields?: string[]; /** * Field names from the description file (package.json) which are used to find the default entry point. */ @@ -9097,6 +9100,26 @@ declare interface UserResolveOptions { onlyModule?: boolean; }[]; + /** + * A list of module alias configurations or an object which maps key to value, applied only after modules option + */ + fallback?: + | { [index: string]: string | false | string[] } + | { + /** + * New request. + */ + alias: string | false | string[]; + /** + * Request to be redirected. + */ + name: string; + /** + * Redirect only exact matching request. + */ + onlyModule?: boolean; + }[]; + /** * A list of alias fields in description files */ @@ -9132,6 +9155,11 @@ declare interface UserResolveOptions { */ exportsFields?: LibraryExport[]; + /** + * A list of imports fields in description files + */ + importsFields?: LibraryExport[]; + /** * A list of extensions which should be tried for files */ @@ -9580,22 +9608,7 @@ declare interface WithOptions { /** * Redirect module requests. */ - alias?: - | { - /** - * New request. - */ - alias: string | false | string[]; - /** - * Request to be redirected. - */ - name: string; - /** - * Redirect only exact matching request. - */ - onlyModule?: boolean; - }[] - | { [index: string]: string | false | string[] }; + alias?: ResolveAlias; /** * Fields in the description file (usually package.json) which are used to redirect requests inside the module. */ @@ -9636,6 +9649,10 @@ declare interface WithOptions { * Extensions added to the request when trying to find the file. */ extensions?: string[]; + /** + * Redirect module requests when normal resolving fails. + */ + fallback?: ResolveAlias; /** * Filesystem for the resolver. */ @@ -9644,6 +9661,10 @@ declare interface WithOptions { * Treats the request specified by the user as fully specified, meaning no extensions are added and the mainFiles in directories are not resolved (This doesn't affect requests from mainFields, aliasFields or aliases). */ fullySpecified?: boolean; + /** + * Field names from the description file (usually package.json) which are used to provide internal request of a package (requests starting with # are considered as internal). + */ + importsFields?: string[]; /** * Field names from the description file (package.json) which are used to find the default entry point. */ diff --git a/yarn.lock b/yarn.lock index 5b573cddd..4392a19ca 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2304,10 +2304,10 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enhanced-resolve@5.0.0-beta.10: - version "5.0.0-beta.10" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.0.0-beta.10.tgz#3907c034f8e59446dfa5a89a1fd73db29aa0f246" - integrity sha512-vEyxvHv3f8xl7i7QmTQ6BqKY32acSPQ4dTZo8WRMtcqTDYH9YyXnDxqXsQqBLvdRHUiwl9nVivESiM1RcrxbKQ== +enhanced-resolve@5.0.0-beta.12: + version "5.0.0-beta.12" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.0.0-beta.12.tgz#ddc2eab710a5f973e1350fd3c0f721df550ec59b" + integrity sha512-lEjGWKw3CAvoCZcXP2QBf74D7azAqSop2uOSN2nqOiqmy9h4F3Ci2OaGkxfifrnltv7MAtQApWycZOmzGwDovg== dependencies: graceful-fs "^4.2.0" tapable "^2.0.0-beta.10"