fix: ESM library generation (#19386)
Github Actions / lint (push) Waiting to run Details
Github Actions / basic (push) Waiting to run Details
Github Actions / validate-legacy-node (push) Waiting to run Details
Github Actions / unit (push) Waiting to run Details
Github Actions / integration (10.x, macos-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (10.x, macos-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (10.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (10.x, ubuntu-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (10.x, windows-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (10.x, windows-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (12.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (14.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (16.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (18.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (18.x, ubuntu-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (20.x, macos-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (20.x, macos-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (20.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (20.x, ubuntu-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (20.x, windows-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (20.x, windows-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (22.x, macos-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (22.x, macos-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (22.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (22.x, ubuntu-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (22.x, windows-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (22.x, windows-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (23.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (23.x, ubuntu-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (lts/*, ubuntu-latest, a, 1) (push) Blocked by required conditions Details
Github Actions / integration (lts/*, ubuntu-latest, b, 1) (push) Blocked by required conditions Details

This commit is contained in:
Alexander Akait 2025-04-06 17:53:09 +03:00 committed by GitHub
parent e0891eeea0
commit bba9874f0d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 545 additions and 231 deletions

View File

@ -346,6 +346,7 @@ const getNormalizedWebpackOptions = config => ({
importFunctionName: output.importFunctionName,
importMetaName: output.importMetaName,
scriptType: output.scriptType,
// TODO webpack6 remove `libraryTarget`/`auxiliaryComment`/`amdContainer`/etc in favor of the `library` option
library: libraryBase && {
type:
output.libraryTarget !== undefined

View File

@ -80,7 +80,8 @@ class EnableLibraryPlugin {
new ExportPropertyTemplatePlugin({
type,
nsObjectUsed: !["module", "modern-module"].includes(type),
runtimeExportsUsed: type !== "modern-module"
runtimeExportsUsed: !["module", "modern-module"].includes(type),
renderStartupUsed: !["module", "modern-module"].includes(type)
}).apply(compiler);
};
switch (type) {
@ -252,7 +253,8 @@ class EnableLibraryPlugin {
}).apply(compiler);
break;
}
case "module": {
case "module":
case "modern-module": {
enableExportProperty();
const ModuleLibraryPlugin = require("./ModuleLibraryPlugin");
new ModuleLibraryPlugin({
@ -260,14 +262,6 @@ class EnableLibraryPlugin {
}).apply(compiler);
break;
}
case "modern-module": {
enableExportProperty();
const ModernModuleLibraryPlugin = require("./ModernModuleLibraryPlugin");
new ModernModuleLibraryPlugin({
type
}).apply(compiler);
break;
}
default:
throw new Error(`Unsupported library type ${type}.
Plugins which provide custom library types must call EnableLibraryPlugin.setEnabled(compiler, type) to disable this error.`);

View File

@ -31,6 +31,7 @@ const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");
* @property {LibraryType} type
* @property {boolean} nsObjectUsed the namespace object is used
* @property {boolean} runtimeExportsUsed runtime exports are used
* @property {boolean} renderStartupUsed render startup is used
*/
/**
* @typedef {ExportPropertyLibraryPluginParsed} T
@ -40,13 +41,14 @@ class ExportPropertyLibraryPlugin extends AbstractLibraryPlugin {
/**
* @param {ExportPropertyLibraryPluginOptions} options options
*/
constructor({ type, nsObjectUsed, runtimeExportsUsed }) {
constructor({ type, nsObjectUsed, runtimeExportsUsed, renderStartupUsed }) {
super({
pluginName: "ExportPropertyLibraryPlugin",
type
});
this.nsObjectUsed = nsObjectUsed;
this.runtimeExportsUsed = runtimeExportsUsed;
this.renderStartupUsed = renderStartupUsed;
}
/**
@ -109,6 +111,7 @@ class ExportPropertyLibraryPlugin extends AbstractLibraryPlugin {
* @returns {Source} source with library export
*/
renderStartup(source, module, renderContext, { options }) {
if (!this.renderStartupUsed) return source;
if (!options.export) return source;
const postfix = `${RuntimeGlobals.exports} = ${
RuntimeGlobals.exports

View File

@ -1,157 +0,0 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const { ConcatSource } = require("webpack-sources");
const ConcatenatedModule = require("../optimize/ConcatenatedModule");
const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../../declarations/WebpackOptions").LibraryOptions} LibraryOptions */
/** @typedef {import("../../declarations/WebpackOptions").LibraryType} LibraryType */
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../Compilation").ChunkHashContext} ChunkHashContext */
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../Module").BuildMeta} BuildMeta */
/** @typedef {import("../javascript/JavascriptModulesPlugin").StartupRenderContext} StartupRenderContext */
/** @typedef {import("../util/Hash")} Hash */
/** @template T @typedef {import("./AbstractLibraryPlugin").LibraryContext<T>} LibraryContext<T> */
/**
* @typedef {object} ModernModuleLibraryPluginOptions
* @property {LibraryType} type
*/
/**
* @typedef {object} ModernModuleLibraryPluginParsed
* @property {string} name
*/
/**
* @typedef {ModernModuleLibraryPluginParsed} T
* @extends {AbstractLibraryPlugin<ModernModuleLibraryPluginParsed>}
*/
class ModernModuleLibraryPlugin extends AbstractLibraryPlugin {
/**
* Apply the plugin
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
super.apply(compiler);
compiler.hooks.compilation.tap("ModernModuleLibraryPlugin", compilation => {
const { exportsDefinitions } =
ConcatenatedModule.getCompilationHooks(compilation);
exportsDefinitions.tap("ModernModuleLibraryPlugin", () => true);
});
}
/**
* @param {ModernModuleLibraryPluginOptions} options the plugin options
*/
constructor(options) {
super({
pluginName: "ModernModuleLibraryPlugin",
type: options.type
});
}
/**
* @param {LibraryOptions} library normalized library option
* @returns {T | false} preprocess as needed by overriding
*/
parseOptions(library) {
const { name } = library;
if (name) {
throw new Error(
`Library name must be unset. ${AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE}`
);
}
const _name = /** @type {string} */ (name);
return {
name: _name
};
}
/**
* @param {Source} source source
* @param {Module} module module
* @param {StartupRenderContext} renderContext render context
* @param {LibraryContext<T>} libraryContext context
* @returns {Source} source with library export
*/
renderStartup(
source,
module,
{ moduleGraph, chunk },
{ options, compilation }
) {
const result = new ConcatSource(source);
const exportsInfo = moduleGraph.getExportsInfo(module);
const definitions =
/** @type {BuildMeta} */
(module.buildMeta).exportsFinalName;
const shortHandedExports = [];
const exports = [];
for (const exportInfo of exportsInfo.orderedExports) {
let shouldContinue = false;
const reexport = exportInfo.findTarget(moduleGraph, _m => true);
if (reexport) {
const exp = moduleGraph.getExportsInfo(reexport.module);
for (const reexportInfo of exp.orderedExports) {
if (
reexportInfo.provided === false &&
reexportInfo.name === /** @type {string[]} */ (reexport.export)[0]
) {
shouldContinue = true;
}
}
}
if (shouldContinue) continue;
const webpackExportsProperty = exportInfo.getUsedName(
exportInfo.name,
chunk.runtime
);
const finalName =
definitions &&
definitions[
/** @type {string} */
(webpackExportsProperty)
];
if (finalName && (finalName.includes(".") || finalName.includes("["))) {
exports.push([exportInfo.name, finalName]);
} else {
shortHandedExports.push(
finalName === exportInfo.name
? finalName
: `${finalName} as ${exportInfo.name}`
);
}
}
if (shortHandedExports.length > 0) {
result.add(`export { ${shortHandedExports.join(", ")} };\n`);
}
for (const [exportName, final] of exports) {
result.add(
`export ${compilation.outputOptions.environment.const ? "const" : "var"} ${exportName} = ${final};\n`
);
}
return result;
}
}
module.exports = ModernModuleLibraryPlugin;

View File

@ -8,6 +8,7 @@
const { ConcatSource } = require("webpack-sources");
const RuntimeGlobals = require("../RuntimeGlobals");
const Template = require("../Template");
const ConcatenatedModule = require("../optimize/ConcatenatedModule");
const propertyAccess = require("../util/propertyAccess");
const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");
@ -18,9 +19,14 @@ const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");
/** @typedef {import("../Compilation").ChunkHashContext} ChunkHashContext */
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../Module").BuildMeta} BuildMeta */
/** @typedef {import("../javascript/JavascriptModulesPlugin").StartupRenderContext} StartupRenderContext */
/** @typedef {import("../util/Hash")} Hash */
/** @template T @typedef {import("./AbstractLibraryPlugin").LibraryContext<T>} LibraryContext<T> */
/**
* @template T
* @typedef {import("./AbstractLibraryPlugin").LibraryContext<T>} LibraryContext<T>
*/
/**
* @typedef {object} ModuleLibraryPluginOptions
@ -30,6 +36,7 @@ const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");
/**
* @typedef {object} ModuleLibraryPluginParsed
* @property {string} name
* @property {string | string[]=} export
*/
/**
@ -47,6 +54,45 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
});
}
/**
* Apply the plugin
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
super.apply(compiler);
compiler.hooks.compilation.tap("ModernModuleLibraryPlugin", compilation => {
const { exportsDefinitions } =
ConcatenatedModule.getCompilationHooks(compilation);
exportsDefinitions.tap(
"ModernModuleLibraryPlugin",
(definitions, module) => {
// If we have connections not all modules were concatenated, so we need the wrapper
const connections =
compilation.moduleGraph.getIncomingConnections(module);
for (const connection of connections) {
if (connection.originModule) {
return false;
}
}
// Runtime and splitting chunks now requires the wrapper too
for (const chunk of compilation.chunkGraph.getModuleChunksIterable(
module
)) {
if (!chunk.hasRuntime()) {
return false;
}
}
return true;
}
);
});
}
/**
* @param {LibraryOptions} library normalized library option
* @returns {T | false} preprocess as needed by overriding
@ -60,7 +106,8 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
}
const _name = /** @type {string} */ (name);
return {
name: _name
name: _name,
export: library.export
};
}
@ -78,30 +125,89 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
{ options, compilation }
) {
const result = new ConcatSource(source);
const exportsInfo = moduleGraph.getExportsInfo(module);
const exportsInfos = options.export
? [
moduleGraph.getExportInfo(
module,
Array.isArray(options.export) ? options.export[0] : options.export
)
]
: moduleGraph.getExportsInfo(module).orderedExports;
const definitions =
/** @type {BuildMeta} */
(module.buildMeta).exportsFinalName || {};
const shortHandedExports = [];
const exports = [];
const isAsync = moduleGraph.isAsync(module);
if (isAsync) {
result.add(
`${RuntimeGlobals.exports} = await ${RuntimeGlobals.exports};\n`
);
}
for (const exportInfo of exportsInfo.orderedExports) {
for (const exportInfo of exportsInfos) {
if (!exportInfo.provided) continue;
const varName = `${RuntimeGlobals.exports}${Template.toIdentifier(
exportInfo.name
)}`;
let shouldContinue = false;
const reexport = exportInfo.findTarget(moduleGraph, _m => true);
if (reexport) {
const exp = moduleGraph.getExportsInfo(reexport.module);
for (const reexportInfo of exp.orderedExports) {
if (
reexportInfo.provided === false &&
reexportInfo.name === /** @type {string[]} */ (reexport.export)[0]
) {
shouldContinue = true;
}
}
}
if (shouldContinue) continue;
const webpackExportsProperty = exportInfo.getUsedName(
exportInfo.name,
chunk.runtime
);
const definition =
definitions[/** @type {string} */ (webpackExportsProperty)];
const finalName =
definition ||
`${RuntimeGlobals.exports}${Template.toIdentifier(exportInfo.name)}`;
if (!definition) {
result.add(
`var ${varName} = ${RuntimeGlobals.exports}${propertyAccess([
`var ${finalName} = ${RuntimeGlobals.exports}${propertyAccess([
/** @type {string} */
(exportInfo.getUsedName(exportInfo.name, chunk.runtime))
])};\n`
])}\n`
);
exports.push(`${varName} as ${exportInfo.name}`);
}
if (exports.length > 0) {
result.add(`export { ${exports.join(", ")} };\n`);
if (finalName && (finalName.includes(".") || finalName.includes("["))) {
exports.push([exportInfo.name, finalName]);
} else {
shortHandedExports.push(
definition && finalName === exportInfo.name
? finalName
: `${finalName} as ${exportInfo.name}`
);
}
}
if (shortHandedExports.length > 0) {
result.add(`export { ${shortHandedExports.join(", ")} };\n`);
}
for (const [exportName, final] of exports) {
result.add(
`export ${compilation.outputOptions.environment.const ? "const" : "var"} ${exportName} = ${final};\n`
);
}
return result;
}
}

View File

@ -603,7 +603,7 @@ const getFinalName = (
/**
* @typedef {object} ConcatenateModuleHooks
* @property {SyncBailHook<[Record<string, string>], boolean | void>} exportsDefinitions
* @property {SyncBailHook<[Record<string, string>, ConcatenatedModule], boolean | void>} exportsDefinitions
*/
/** @type {WeakMap<Compilation, ConcatenateModuleHooks>} */
@ -650,7 +650,7 @@ class ConcatenatedModule extends Module {
let hooks = compilationHooksMap.get(compilation);
if (hooks === undefined) {
hooks = {
exportsDefinitions: new SyncBailHook(["definitions"])
exportsDefinitions: new SyncBailHook(["definitions", "module"])
};
compilationHooksMap.set(compilation, hooks);
}
@ -1488,7 +1488,8 @@ class ConcatenatedModule extends Module {
// define exports
if (exportsMap.size > 0) {
const { exportsDefinitions } = ConcatenatedModule.getCompilationHooks(
/** @type {Compilation} */ (this.compilation)
/** @type {Compilation} */
(this.compilation)
);
const definitions = [];
@ -1499,8 +1500,11 @@ class ConcatenatedModule extends Module {
)}`
);
}
const shouldSkipRenderDefinitions =
exportsDefinitions.call(exportsFinalName);
const shouldSkipRenderDefinitions = exportsDefinitions.call(
exportsFinalName,
this
);
if (!shouldSkipRenderDefinitions) {
runtimeRequirements.add(RuntimeGlobals.exports);

View File

@ -0,0 +1,14 @@
export * from "./a";
export default "default-value";
export var b = "b";
export { default as external } from "external";
export * from "external-named";
const test = await 1;
var module = "should not conflict",
define = "should not conflict",
require = "should not conflict",
exports = "should not conflict",
globalName = "should not conflict";
console.log.bind(console, module, define, require, exports, globalName);

View File

@ -1,13 +1,16 @@
const path = require("path");
const webpack = require("../../../../");
const supportsAsync = require("../../../helpers/supportsAsync");
/** @type {(env: any, options: any) => import("../../../../").Configuration[]} */
module.exports = (env, { testPath }) => [
{
output: {
uniqueName: "esm",
filename: "esm.js",
libraryTarget: "module"
uniqueName: "modern-module",
filename: "modern-module.js",
library: {
type: "modern-module"
}
},
target: "node14",
resolve: {
@ -22,9 +25,11 @@ module.exports = (env, { testPath }) => [
},
{
output: {
uniqueName: "modern-module",
filename: "modern-module.js",
libraryTarget: "modern-module"
uniqueName: "esm",
filename: "esm.js",
library: {
type: "module"
}
},
target: "node14",
resolve: {
@ -37,11 +42,105 @@ module.exports = (env, { testPath }) => [
outputModule: true
}
},
{
output: {
uniqueName: "esm-export",
filename: "esm-export.js",
library: {
type: "module",
export: ["a"]
}
},
target: "node14",
resolve: {
alias: {
external: "./non-external",
"external-named": "./non-external-named"
}
},
experiments: {
outputModule: true
}
},
...(supportsAsync()
? [
{
entry: "./index-async.js",
output: {
uniqueName: "esm-async",
filename: "esm-async.js",
library: {
type: "module"
}
},
optimization: {
concatenateModules: true
},
target: "node14",
resolve: {
alias: {
external: "./non-external",
"external-named": "./non-external-named"
}
},
experiments: {
outputModule: true
}
},
{
entry: "./index-async.js",
output: {
uniqueName: "esm-async-no-concatenate-modules",
filename: "esm-async-no-concatenate-modules.js",
library: {
type: "module"
}
},
optimization: {
concatenateModules: false
},
resolve: {
alias: {
external: "./non-external",
"external-named": "./non-external-named"
}
},
experiments: {
outputModule: true
}
}
]
: []),
{
output: {
uniqueName: "esm-export-no-concatenate-modules",
filename: "esm-export-no-concatenate-modules.js",
library: {
type: "module",
export: ["a"]
}
},
target: "node14",
optimization: {
concatenateModules: false
},
resolve: {
alias: {
external: "./non-external",
"external-named": "./non-external-named"
}
},
experiments: {
outputModule: true
}
},
{
output: {
uniqueName: "esm-runtimeChunk",
filename: "esm-runtimeChunk/[name].js",
libraryTarget: "module"
library: {
type: "module"
}
},
target: "node14",
resolve: {
@ -57,11 +156,92 @@ module.exports = (env, { testPath }) => [
outputModule: true
}
},
{
output: {
uniqueName: "esm-runtimeChunk-concatenateModules",
filename: "esm-runtimeChunk-concatenateModules/[name].js",
library: {
type: "module"
}
},
target: "node14",
resolve: {
alias: {
external: "./non-external",
"external-named": "./non-external-named"
}
},
optimization: {
runtimeChunk: "single",
concatenateModules: true
},
experiments: {
outputModule: true
}
},
{
output: {
uniqueName: "esm-runtimeChunk-no-concatenateModules",
filename: "esm-runtimeChunk-no-concatenateModules/[name].js",
library: {
type: "module"
}
},
target: "node14",
resolve: {
alias: {
external: "./non-external",
"external-named": "./non-external-named"
}
},
optimization: {
runtimeChunk: "single",
concatenateModules: false
},
experiments: {
outputModule: true
}
},
{
output: {
uniqueName: "esm-runtimeChunk-concatenateModules-splitChunks",
filename: "esm-runtimeChunk-concatenateModules-splitChunks/[name].js",
library: {
type: "module"
}
},
target: "node14",
resolve: {
alias: {
external: "./non-external",
"external-named": "./non-external-named"
}
},
optimization: {
runtimeChunk: "single",
concatenateModules: true,
splitChunks: {
cacheGroups: {
module: {
test: /a\.js$/,
chunks: "all",
enforce: true,
reuseExistingChunk: true
}
}
}
},
experiments: {
outputModule: true
}
},
{
output: {
uniqueName: "commonjs",
filename: "commonjs.js",
libraryTarget: "commonjs",
library: {
type: "commonjs"
},
iife: false
},
resolve: {
@ -75,7 +255,9 @@ module.exports = (env, { testPath }) => [
output: {
uniqueName: "commonjs-iife",
filename: "commonjs-iife.js",
libraryTarget: "commonjs",
library: {
type: "commonjs"
},
iife: true
},
resolve: {
@ -89,7 +271,9 @@ module.exports = (env, { testPath }) => [
output: {
uniqueName: "amd",
filename: "amd.js",
libraryTarget: "amd",
library: {
type: "amd"
},
iife: false
},
resolve: {
@ -103,7 +287,9 @@ module.exports = (env, { testPath }) => [
output: {
uniqueName: "amd-iife",
filename: "amd-iife.js",
libraryTarget: "amd",
library: {
type: "amd"
},
iife: true
},
resolve: {
@ -117,7 +303,9 @@ module.exports = (env, { testPath }) => [
output: {
uniqueName: "amd-runtimeChunk",
filename: "amd-runtimeChunk/[name].js",
libraryTarget: "amd",
library: {
type: "amd"
},
globalObject: "global",
iife: false
},
@ -136,7 +324,9 @@ module.exports = (env, { testPath }) => [
output: {
uniqueName: "amd-iife-runtimeChunk",
filename: "amd-iife-runtimeChunk/[name].js",
libraryTarget: "amd",
library: {
type: "amd"
},
globalObject: "global",
iife: true
},
@ -155,7 +345,9 @@ module.exports = (env, { testPath }) => [
output: {
uniqueName: "umd",
filename: "umd.js",
libraryTarget: "umd"
library: {
type: "umd"
}
},
resolve: {
alias: {
@ -218,8 +410,10 @@ module.exports = (env, { testPath }) => [
output: {
uniqueName: "umd-default",
filename: "umd-default.js",
libraryTarget: "umd",
libraryExport: "default"
library: {
type: "umd",
export: "default"
}
},
resolve: {
alias: {
@ -232,7 +426,9 @@ module.exports = (env, { testPath }) => [
output: {
uniqueName: "this",
filename: "this.js",
libraryTarget: "this",
library: {
type: "this"
},
iife: false
},
resolve: {
@ -246,7 +442,9 @@ module.exports = (env, { testPath }) => [
output: {
uniqueName: "this-iife",
filename: "this-iife.js",
libraryTarget: "this",
library: {
type: "this"
},
iife: true
},
resolve: {
@ -301,8 +499,10 @@ module.exports = (env, { testPath }) => [
output: {
uniqueName: "commonjs-nested",
filename: "commonjs-nested.js",
libraryTarget: "commonjs",
libraryExport: "NS",
library: {
type: "commonjs",
export: "NS"
},
iife: false
},
resolve: {
@ -317,8 +517,10 @@ module.exports = (env, { testPath }) => [
output: {
uniqueName: "commonjs-nested-iife",
filename: "commonjs-nested-iife.js",
libraryTarget: "commonjs",
libraryExport: "NS",
library: {
type: "commonjs",
export: "NS"
},
iife: true
},
resolve: {
@ -332,7 +534,9 @@ module.exports = (env, { testPath }) => [
output: {
uniqueName: "commonjs2-external",
filename: "commonjs2-external.js",
libraryTarget: "commonjs2",
library: {
type: "commonjs2"
},
iife: false
},
externals: ["external", "external-named"]
@ -341,7 +545,9 @@ module.exports = (env, { testPath }) => [
output: {
uniqueName: "commonjs2-external-no-concat",
filename: "commonjs2-external-no-concat.js",
libraryTarget: "commonjs2",
library: {
type: "commonjs2"
},
iife: false
},
optimization: {
@ -353,7 +559,9 @@ module.exports = (env, { testPath }) => [
output: {
uniqueName: "commonjs2-iife-external",
filename: "commonjs2-iife-external.js",
libraryTarget: "commonjs2",
library: {
type: "commonjs2"
},
iife: true
},
externals: ["external", "external-named"]
@ -363,7 +571,9 @@ module.exports = (env, { testPath }) => [
output: {
uniqueName: "commonjs2-external-eval",
filename: "commonjs2-external-eval.js",
libraryTarget: "commonjs2"
library: {
type: "commonjs2"
}
},
externals: ["external", "external-named"]
},
@ -372,7 +582,9 @@ module.exports = (env, { testPath }) => [
output: {
uniqueName: "commonjs2-external-eval-source-map",
filename: "commonjs2-external-eval-source-map.js",
libraryTarget: "commonjs2"
library: {
type: "commonjs2"
}
},
devtool: "eval-source-map",
externals: ["external", "external-named"]
@ -381,7 +593,9 @@ module.exports = (env, { testPath }) => [
output: {
uniqueName: "commonjs-static-external",
filename: "commonjs-static-external.js",
libraryTarget: "commonjs-static",
library: {
type: "commonjs-static"
},
iife: false
},
externals: ["external", "external-named"]
@ -391,7 +605,9 @@ module.exports = (env, { testPath }) => [
uniqueName: "index",
filename: "index.js",
path: path.resolve(testPath, "commonjs2-split-chunks"),
libraryTarget: "commonjs2"
library: {
type: "commonjs2"
}
},
target: "node",
optimization: {
@ -417,7 +633,9 @@ module.exports = (env, { testPath }) => [
output: {
uniqueName: "commonjs2-runtimeChunk",
filename: "commonjs2-runtimeChunk/[name].js",
libraryTarget: "commonjs2",
library: {
type: "commonjs2"
},
iife: false
},
resolve: {
@ -434,7 +652,9 @@ module.exports = (env, { testPath }) => [
output: {
uniqueName: "commonjs2-iife-runtimeChunk",
filename: "commonjs2-iife-runtimeChunk/[name].js",
libraryTarget: "commonjs2",
library: {
type: "commonjs2"
},
iife: true
},
resolve: {

View File

@ -0,0 +1,5 @@
import * as mod from "library";
it("should tree-shake other exports from library (" + NAME + ") and export only 'a'", function() {
expect(mod).toMatchObject({ a: "a" });
});

View File

@ -3,21 +3,10 @@
const webpack = require("../../../../");
const path = require("path");
const supportsAsync = require("../../../helpers/supportsAsync");
/** @type {(env: any, options: any) => import("../../../../").Configuration[]} */
module.exports = (env, { testPath }) => [
{
resolve: {
alias: {
library: path.resolve(testPath, "../0-create-library/esm.js")
}
},
plugins: [
new webpack.DefinePlugin({
NAME: JSON.stringify("esm")
})
]
},
{
entry: "./default-test-modern-module.js",
optimization: {
@ -57,6 +46,81 @@ module.exports = (env, { testPath }) => [
}
]
},
{
resolve: {
alias: {
library: path.resolve(testPath, "../0-create-library/esm.js")
}
},
plugins: [
new webpack.DefinePlugin({
NAME: JSON.stringify("esm")
})
]
},
{
entry: "./module-export-test.js",
resolve: {
alias: {
library: path.resolve(testPath, "../0-create-library/esm-export.js")
}
},
plugins: [
new webpack.DefinePlugin({
NAME: JSON.stringify("esm-export")
})
]
},
{
entry: "./module-export-test.js",
resolve: {
alias: {
library: path.resolve(
testPath,
"../0-create-library/esm-export-no-concatenate-modules.js"
)
}
},
plugins: [
new webpack.DefinePlugin({
NAME: JSON.stringify("esm-export-no-concatenate-modules.js")
})
]
},
...(supportsAsync()
? [
{
resolve: {
alias: {
library: path.resolve(
testPath,
"../0-create-library/esm-async.js"
)
}
},
plugins: [
new webpack.DefinePlugin({
NAME: JSON.stringify("esm-async")
})
]
},
{
resolve: {
alias: {
library: path.resolve(
testPath,
"../0-create-library/esm-async-no-concatenate-modules.js"
)
}
},
plugins: [
new webpack.DefinePlugin({
NAME: JSON.stringify("esm-async-no-concatenate-modules")
})
]
}
]
: []),
{
resolve: {
alias: {
@ -72,6 +136,51 @@ module.exports = (env, { testPath }) => [
})
]
},
{
resolve: {
alias: {
library: path.resolve(
testPath,
"../0-create-library/esm-runtimeChunk-concatenateModules/main.js"
)
}
},
plugins: [
new webpack.DefinePlugin({
NAME: JSON.stringify("esm-runtimeChunk-concatenateModules")
})
]
},
{
resolve: {
alias: {
library: path.resolve(
testPath,
"../0-create-library/esm-runtimeChunk-no-concatenateModules/main.js"
)
}
},
plugins: [
new webpack.DefinePlugin({
NAME: JSON.stringify("esm-runtimeChunk-no-concatenateModules")
})
]
},
{
resolve: {
alias: {
library: path.resolve(
testPath,
"../0-create-library/esm-runtimeChunk-concatenateModules-splitChunks/main.js"
)
}
},
plugins: [
new webpack.DefinePlugin({
NAME: JSON.stringify("esm-runtimeChunk-concatenateModules-splitChunks")
})
]
},
{
resolve: {
alias: {

View File

@ -0,0 +1,15 @@
module.exports = function supportsAsync() {
// Node.js@10 has a bug with nested async/await
if (process.version.startsWith("v10.")) {
return false;
}
try {
eval("async () => {}");
return true;
} catch (_err) {
// Ignore
}
return false;
};