mirror of https://github.com/webpack/webpack.git
enable export mangling for system.js externals
add __esModule flag only when needed
This commit is contained in:
parent
3d3d20e353
commit
c94aea82cc
|
@ -44,6 +44,7 @@
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} ExportsSpec
|
* @typedef {Object} ExportsSpec
|
||||||
* @property {(string | ExportSpec)[] | true | null} exports exported names, true for unknown exports or null for no exports
|
* @property {(string | ExportSpec)[] | true | null} exports exported names, true for unknown exports or null for no exports
|
||||||
|
* @property {boolean=} canMangle can the export be renamed (defaults to true)
|
||||||
* @property {Module[]=} dependencies module on which the result depends on
|
* @property {Module[]=} dependencies module on which the result depends on
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ const { OriginalSource, RawSource } = require("webpack-sources");
|
||||||
const Module = require("./Module");
|
const Module = require("./Module");
|
||||||
const RuntimeGlobals = require("./RuntimeGlobals");
|
const RuntimeGlobals = require("./RuntimeGlobals");
|
||||||
const Template = require("./Template");
|
const Template = require("./Template");
|
||||||
|
const StaticExportsDependency = require("./dependencies/StaticExportsDependency");
|
||||||
const makeSerializable = require("./util/makeSerializable");
|
const makeSerializable = require("./util/makeSerializable");
|
||||||
const propertyAccess = require("./util/propertyAccess");
|
const propertyAccess = require("./util/propertyAccess");
|
||||||
|
|
||||||
|
@ -194,10 +195,17 @@ class ExternalModule extends Module {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
build(options, compilation, resolver, fs, callback) {
|
build(options, compilation, resolver, fs, callback) {
|
||||||
this.buildMeta = {};
|
this.buildMeta = {
|
||||||
|
exportsType: undefined
|
||||||
|
};
|
||||||
this.buildInfo = {
|
this.buildInfo = {
|
||||||
strict: true
|
strict: true
|
||||||
};
|
};
|
||||||
|
this.clearDependenciesAndBlocks();
|
||||||
|
if (this.externalType === "system") {
|
||||||
|
this.buildMeta.exportsType = "namespace";
|
||||||
|
this.addDependency(new StaticExportsDependency(true, true));
|
||||||
|
}
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,6 +298,13 @@ class ExternalModule extends Module {
|
||||||
hash.update(
|
hash.update(
|
||||||
JSON.stringify(Boolean(this.isOptional(chunkGraph.moduleGraph)))
|
JSON.stringify(Boolean(this.isOptional(chunkGraph.moduleGraph)))
|
||||||
);
|
);
|
||||||
|
if (this.externalType === "system") {
|
||||||
|
const exportsInfo = chunkGraph.moduleGraph.getExportsInfo(this);
|
||||||
|
for (const exportInfo of exportsInfo.orderedExports) {
|
||||||
|
hash.update(exportInfo.name);
|
||||||
|
hash.update(exportInfo.getUsedName() || "");
|
||||||
|
}
|
||||||
|
}
|
||||||
super.updateHash(hash, chunkGraph);
|
super.updateHash(hash, chunkGraph);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,10 +113,11 @@ class FlagDependencyExportsPlugin {
|
||||||
const exportDesc = dep.getExports(moduleGraph);
|
const exportDesc = dep.getExports(moduleGraph);
|
||||||
if (!exportDesc) return;
|
if (!exportDesc) return;
|
||||||
const exports = exportDesc.exports;
|
const exports = exportDesc.exports;
|
||||||
|
const canMangle = exportDesc.canMangle;
|
||||||
const exportDeps = exportDesc.dependencies;
|
const exportDeps = exportDesc.dependencies;
|
||||||
if (exports === true) {
|
if (exports === true) {
|
||||||
// unknown exports
|
// unknown exports
|
||||||
if (exportsInfo.setUnknownExportsProvided()) {
|
if (exportsInfo.setUnknownExportsProvided(canMangle)) {
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
} else if (Array.isArray(exports)) {
|
} else if (Array.isArray(exports)) {
|
||||||
|
@ -131,6 +132,13 @@ class FlagDependencyExportsPlugin {
|
||||||
exportInfo.provided = true;
|
exportInfo.provided = true;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
canMangle === false &&
|
||||||
|
exportInfo.canMangleProvide !== false
|
||||||
|
) {
|
||||||
|
exportInfo.canMangleProvide = false;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const exportInfo = exportsInfo.getExportInfo(
|
const exportInfo = exportsInfo.getExportInfo(
|
||||||
exportNameOrSpec.name
|
exportNameOrSpec.name
|
||||||
|
@ -139,11 +147,14 @@ class FlagDependencyExportsPlugin {
|
||||||
exportInfo.provided = true;
|
exportInfo.provided = true;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
if (exportNameOrSpec.canMangle === false) {
|
if (
|
||||||
if (exportInfo.canMangleProvide !== false) {
|
exportInfo.canMangleProvide !== false &&
|
||||||
exportInfo.canMangleProvide = false;
|
(exportNameOrSpec.canMangle === false ||
|
||||||
changed = true;
|
(canMangle === false &&
|
||||||
}
|
exportNameOrSpec.canMangle === undefined))
|
||||||
|
) {
|
||||||
|
exportInfo.canMangleProvide = false;
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
if (exportNameOrSpec.exports) {
|
if (exportNameOrSpec.exports) {
|
||||||
const nestedExportsInfo = exportInfo.createNestedExportsInfo();
|
const nestedExportsInfo = exportInfo.createNestedExportsInfo();
|
||||||
|
|
|
@ -70,10 +70,16 @@ class ExportsInfo {
|
||||||
this._redirectTo = undefined;
|
this._redirectTo = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {Iterable<ExportInfo>} all owned exports in any order
|
||||||
|
*/
|
||||||
get ownedExports() {
|
get ownedExports() {
|
||||||
return this._exports.values();
|
return this._exports.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {Iterable<ExportInfo>} all exports in any order
|
||||||
|
*/
|
||||||
get exports() {
|
get exports() {
|
||||||
if (this._redirectTo) {
|
if (this._redirectTo) {
|
||||||
const map = new Map(this._redirectTo._exports);
|
const map = new Map(this._redirectTo._exports);
|
||||||
|
@ -85,6 +91,9 @@ class ExportsInfo {
|
||||||
return this._exports.values();
|
return this._exports.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {Iterable<ExportInfo>} all exports in order
|
||||||
|
*/
|
||||||
get orderedExports() {
|
get orderedExports() {
|
||||||
if (!this._exportsAreOrdered) {
|
if (!this._exportsAreOrdered) {
|
||||||
this._sortExports();
|
this._sortExports();
|
||||||
|
@ -104,6 +113,9 @@ class ExportsInfo {
|
||||||
return this._exports.values();
|
return this._exports.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {ExportInfo} the export info of unlisted exports
|
||||||
|
*/
|
||||||
get otherExportsInfo() {
|
get otherExportsInfo() {
|
||||||
if (this._redirectTo) return this._redirectTo.otherExportsInfo;
|
if (this._redirectTo) return this._redirectTo.otherExportsInfo;
|
||||||
return this._otherExportsInfo;
|
return this._otherExportsInfo;
|
||||||
|
@ -223,16 +235,17 @@ class ExportsInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param {boolean=} canMangle true, if exports can still be mangled (defaults to false)
|
||||||
* @returns {boolean} true, if this call changed something
|
* @returns {boolean} true, if this call changed something
|
||||||
*/
|
*/
|
||||||
setUnknownExportsProvided() {
|
setUnknownExportsProvided(canMangle) {
|
||||||
let changed = false;
|
let changed = false;
|
||||||
for (const exportInfo of this._exports.values()) {
|
for (const exportInfo of this._exports.values()) {
|
||||||
if (exportInfo.provided !== true && exportInfo.provided !== null) {
|
if (exportInfo.provided !== true && exportInfo.provided !== null) {
|
||||||
exportInfo.provided = null;
|
exportInfo.provided = null;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
if (exportInfo.canMangleProvide !== false) {
|
if (!canMangle && exportInfo.canMangleProvide !== false) {
|
||||||
exportInfo.canMangleProvide = false;
|
exportInfo.canMangleProvide = false;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
@ -249,7 +262,7 @@ class ExportsInfo {
|
||||||
this._otherExportsInfo.provided = null;
|
this._otherExportsInfo.provided = null;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
if (this._otherExportsInfo.canMangleProvide !== false) {
|
if (!canMangle && this._otherExportsInfo.canMangleProvide !== false) {
|
||||||
this._otherExportsInfo.canMangleProvide = false;
|
this._otherExportsInfo.canMangleProvide = false;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -466,6 +466,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
|
||||||
case "dynamic-reexport":
|
case "dynamic-reexport":
|
||||||
return {
|
return {
|
||||||
exports: true,
|
exports: true,
|
||||||
|
canMangle: false,
|
||||||
// TODO: consider passing `ignored` from `dynamic-reexport`
|
// TODO: consider passing `ignored` from `dynamic-reexport`
|
||||||
dependencies: [moduleGraph.getModule(this)]
|
dependencies: [moduleGraph.getModule(this)]
|
||||||
};
|
};
|
||||||
|
|
|
@ -35,20 +35,11 @@ class StaticExportsDependency extends NullDependency {
|
||||||
* @returns {ExportsSpec | undefined} export names
|
* @returns {ExportsSpec | undefined} export names
|
||||||
*/
|
*/
|
||||||
getExports(moduleGraph) {
|
getExports(moduleGraph) {
|
||||||
if (!this.canMangle && this.exports !== true) {
|
return {
|
||||||
return {
|
exports: this.exports,
|
||||||
exports: this.exports.map(name => ({
|
canMangle: this.canMangle,
|
||||||
name,
|
dependencies: undefined
|
||||||
canMangle: false
|
};
|
||||||
})),
|
|
||||||
dependencies: undefined
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
exports: this.exports,
|
|
||||||
dependencies: undefined
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -7,7 +7,9 @@
|
||||||
|
|
||||||
const { ConcatSource } = require("webpack-sources");
|
const { ConcatSource } = require("webpack-sources");
|
||||||
const ExternalModule = require("../ExternalModule");
|
const ExternalModule = require("../ExternalModule");
|
||||||
|
const { UsageState } = require("../ModuleGraph");
|
||||||
const Template = require("../Template");
|
const Template = require("../Template");
|
||||||
|
const propertyAccess = require("../util/propertyAccess");
|
||||||
const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");
|
const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");
|
||||||
|
|
||||||
/** @typedef {import("webpack-sources").Source} Source */
|
/** @typedef {import("webpack-sources").Source} Source */
|
||||||
|
@ -67,7 +69,7 @@ class SystemLibraryPlugin extends AbstractLibraryPlugin {
|
||||||
* @param {LibraryContext<T>} libraryContext context
|
* @param {LibraryContext<T>} libraryContext context
|
||||||
* @returns {Source} source with library export
|
* @returns {Source} source with library export
|
||||||
*/
|
*/
|
||||||
render(source, { chunkGraph, chunk }, { options, compilation }) {
|
render(source, { chunkGraph, moduleGraph, chunk }, { options, compilation }) {
|
||||||
const modules = chunkGraph
|
const modules = chunkGraph
|
||||||
.getChunkModules(chunk)
|
.getChunkModules(chunk)
|
||||||
.filter(m => m instanceof ExternalModule);
|
.filter(m => m instanceof ExternalModule);
|
||||||
|
@ -99,10 +101,12 @@ class SystemLibraryPlugin extends AbstractLibraryPlugin {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Declaring variables for the internal variable names for the webpack externals
|
// Declaring variables for the internal variable names for the webpack externals
|
||||||
const externalVarDeclarations =
|
const externalVarDeclarations = externalWebpackNames
|
||||||
externalWebpackNames.length > 0
|
.map(name => `var ${name} = {};`)
|
||||||
? `var ${externalWebpackNames.join(", ")};`
|
.join("\n");
|
||||||
: "";
|
|
||||||
|
// Define __esModule flag on all internal variables and helpers
|
||||||
|
const externalVarInitialization = [];
|
||||||
|
|
||||||
// The system.register format requires an array of setter functions for externals.
|
// The system.register format requires an array of setter functions for externals.
|
||||||
const setters =
|
const setters =
|
||||||
|
@ -111,24 +115,65 @@ class SystemLibraryPlugin extends AbstractLibraryPlugin {
|
||||||
: Template.asString([
|
: Template.asString([
|
||||||
"setters: [",
|
"setters: [",
|
||||||
Template.indent(
|
Template.indent(
|
||||||
externalWebpackNames
|
externals
|
||||||
.map(external =>
|
.map((module, i) => {
|
||||||
Template.asString([
|
const external = externalWebpackNames[i];
|
||||||
|
const exportsInfo = moduleGraph.getExportsInfo(module);
|
||||||
|
const otherUnused =
|
||||||
|
exportsInfo.otherExportsInfo.used === UsageState.Unused;
|
||||||
|
const instructions = [];
|
||||||
|
const handledNames = [];
|
||||||
|
for (const exportInfo of exportsInfo.orderedExports) {
|
||||||
|
const used = exportInfo.getUsedName();
|
||||||
|
if (used) {
|
||||||
|
if (otherUnused || used !== exportInfo.name) {
|
||||||
|
instructions.push(
|
||||||
|
`${external}${propertyAccess([
|
||||||
|
used
|
||||||
|
])} = module${propertyAccess([exportInfo.name])};`
|
||||||
|
);
|
||||||
|
handledNames.push(exportInfo.name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
handledNames.push(exportInfo.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!otherUnused) {
|
||||||
|
externalVarInitialization.push(
|
||||||
|
`Object.defineProperty(${external}, "__esModule", { value: true });`
|
||||||
|
);
|
||||||
|
if (handledNames.length > 0) {
|
||||||
|
const name = `${external}handledNames`;
|
||||||
|
externalVarInitialization.push(
|
||||||
|
`var ${name} = ${JSON.stringify(handledNames)};`
|
||||||
|
);
|
||||||
|
instructions.push(
|
||||||
|
Template.asString([
|
||||||
|
"Object.keys(module).forEach(function(key) {",
|
||||||
|
Template.indent([
|
||||||
|
`if(${name}.indexOf(key) >= 0)`,
|
||||||
|
Template.indent(`${external}[key] = module[key];`)
|
||||||
|
]),
|
||||||
|
"});"
|
||||||
|
])
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
instructions.push(
|
||||||
|
Template.asString([
|
||||||
|
"Object.keys(module).forEach(function(key) {",
|
||||||
|
Template.indent([`${external}[key] = module[key];`]),
|
||||||
|
"});"
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (instructions.length === 0) return "undefined";
|
||||||
|
return Template.asString([
|
||||||
"function(module) {",
|
"function(module) {",
|
||||||
Template.indent(`${external} = {__esModule: true};`),
|
Template.indent(instructions),
|
||||||
Template.indent([
|
|
||||||
"for (var key in module) {",
|
|
||||||
Template.indent("defineGetter(key, module[key]);"),
|
|
||||||
"}",
|
|
||||||
"function defineGetter(key, value) {",
|
|
||||||
Template.indent([
|
|
||||||
`Object.defineProperty(${external}, key, {get: function() {return value;}, enumerable: true});`
|
|
||||||
]),
|
|
||||||
"}"
|
|
||||||
]),
|
|
||||||
"}"
|
"}"
|
||||||
])
|
]);
|
||||||
)
|
})
|
||||||
.join(",\n")
|
.join(",\n")
|
||||||
),
|
),
|
||||||
"],"
|
"],"
|
||||||
|
@ -139,23 +184,25 @@ class SystemLibraryPlugin extends AbstractLibraryPlugin {
|
||||||
`System.register(${name}${systemDependencies}, function(${dynamicExport}) {`,
|
`System.register(${name}${systemDependencies}, function(${dynamicExport}) {`,
|
||||||
Template.indent([
|
Template.indent([
|
||||||
externalVarDeclarations,
|
externalVarDeclarations,
|
||||||
|
Template.asString(externalVarInitialization),
|
||||||
"return {",
|
"return {",
|
||||||
Template.indent([
|
Template.indent([
|
||||||
setters,
|
setters,
|
||||||
"execute: function() {",
|
"execute: function() {",
|
||||||
Template.indent(`${dynamicExport}(`)
|
Template.indent(`${dynamicExport}(`)
|
||||||
])
|
])
|
||||||
])
|
]),
|
||||||
]) + "\n",
|
""
|
||||||
|
]),
|
||||||
source,
|
source,
|
||||||
"\n" +
|
Template.asString([
|
||||||
Template.asString([
|
"",
|
||||||
Template.indent([
|
Template.indent([
|
||||||
Template.indent([Template.indent([");"]), "}"]),
|
Template.indent([Template.indent([");"]), "}"]),
|
||||||
"};"
|
"};"
|
||||||
]),
|
]),
|
||||||
"})"
|
"})"
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -184,7 +184,7 @@ class WebAssemblyParser extends Parser {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
state.module.addDependency(new StaticExportsDependency(exports, true));
|
state.module.addDependency(new StaticExportsDependency(exports, false));
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import external3Default, { namedThing } from 'external3';
|
import external3Default, { namedThing } from "external3";
|
||||||
|
import "external4";
|
||||||
|
|
||||||
/* This test verifies that webpack externals are properly indicated as dependencies to System.
|
/* This test verifies that webpack externals are properly indicated as dependencies to System.
|
||||||
* Also that when System provides the external variables to webpack that the variables get plumbed
|
* Also that when System provides the external variables to webpack that the variables get plumbed
|
||||||
|
|
|
@ -4,14 +4,18 @@ module.exports = {
|
||||||
beforeExecute: () => {
|
beforeExecute: () => {
|
||||||
System.init({
|
System.init({
|
||||||
external1: {
|
external1: {
|
||||||
default: "the external1 value",
|
default: "the external1 value"
|
||||||
},
|
},
|
||||||
external2: {
|
external2: {
|
||||||
default: "the external2 value",
|
default: "the external2 value"
|
||||||
},
|
},
|
||||||
external3: {
|
external3: {
|
||||||
default: "the external3 default export",
|
default: "the external3 default export",
|
||||||
namedThing: "the external3 named export"
|
namedThing: "the external3 named export"
|
||||||
|
},
|
||||||
|
external4: {
|
||||||
|
default: "the external4 default export",
|
||||||
|
namedThing: "the external4 named export"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,6 +5,7 @@ module.exports = {
|
||||||
externals: {
|
externals: {
|
||||||
external1: "external1",
|
external1: "external1",
|
||||||
external2: "external2",
|
external2: "external2",
|
||||||
external3: "external3"
|
external3: "external3",
|
||||||
|
external4: "external4"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -69,8 +69,9 @@ const System = {
|
||||||
m.executed = true;
|
m.executed = true;
|
||||||
for (let i = 0; i < m.deps.length; i++) {
|
for (let i = 0; i < m.deps.length; i++) {
|
||||||
const dep = m.deps[i];
|
const dep = m.deps[i];
|
||||||
|
const setters = m.mod.setters[i];
|
||||||
System.ensureExecuted(dep);
|
System.ensureExecuted(dep);
|
||||||
m.mod.setters[i](System.registry[dep].exports);
|
if (setters) setters(System.registry[dep].exports);
|
||||||
}
|
}
|
||||||
m.mod.execute();
|
m.mod.execute();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue