Merge pull request #6184 from webpack/feature/json-tree-shaking

Feature/json tree shaking
This commit is contained in:
Tobias Koppers 2017-12-23 09:24:25 +01:00 committed by GitHub
commit 6a49ce0631
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
77 changed files with 789 additions and 599 deletions

View File

@ -9,7 +9,6 @@ const Module = require("./Module");
const OriginalSource = require("webpack-sources").OriginalSource;
const RawSource = require("webpack-sources").RawSource;
const AsyncDependenciesBlock = require("./AsyncDependenciesBlock");
const DepBlockHelpers = require("./dependencies/DepBlockHelpers");
const Template = require("./Template");
class ContextModule extends Module {
@ -226,47 +225,63 @@ class ContextModule extends Module {
}
getFakeMap(dependencies) {
if(!this.options.namespaceObject) return false;
if(!this.options.namespaceObject) return 1;
// if we filter first we get a new array
// therefor we dont need to create a clone of dependencies explicitly
// therefore the order of this is !important!
let hasNonHarmony = false;
let hasHarmony = false;
let hasNamespace = false;
let hasNamed = false;
const fakeMap = dependencies
.filter(dependency => dependency.module)
.sort((a, b) => {
return b.module.id - a.module.id;
}).reduce((map, dep) => {
const harmonyModule = dep.module.buildMeta && dep.module.buildMeta.harmonyModule;
if(!harmonyModule) hasNonHarmony = true;
if(harmonyModule) hasHarmony = true;
map[dep.module.id] = harmonyModule ? 1 : 0;
const exportsType = dep.module.buildMeta && dep.module.buildMeta.exportsType;
if(!exportsType) hasNonHarmony = true;
if(exportsType === "namespace") hasNamespace = true;
if(exportsType === "named") hasNamed = true;
map[dep.module.id] = {
namespace: 1,
named: 2
}[exportsType] || 0;
return map;
}, Object.create(null));
if(hasHarmony && !hasNonHarmony) return false;
if(!hasHarmony && hasNonHarmony) return true;
if(!hasNamespace && hasNonHarmony && !hasNamed) return 0;
if(hasNamespace && !hasNonHarmony && !hasNamed) return 1;
if(!hasNamespace && !hasNonHarmony && hasNamed) return 2;
if(!hasNamespace && !hasNonHarmony && !hasNamed) return 1;
return fakeMap;
}
getModuleObjectSource(fakeMap, fakeMapDataExpression = "fakeMap[id]") {
getFakeMapInitStatement(fakeMap) {
return typeof fakeMap === "object" ? `var fakeMap = ${JSON.stringify(fakeMap, null, "\t")};` : "";
}
getReturnModuleObjectSource(fakeMap, fakeMapDataExpression = "fakeMap[id]") {
const strict = this.options.namespaceObject === "strict";
if(strict) {
if(fakeMap === true) return "/* fake namespace object */ { \"default\": module }";
if(fakeMap) return `${fakeMapDataExpression} ? module : /* fake namespace object */ { "default": module }`;
} else {
if(fakeMap === true) return "typeof module === \"object\" && module && module.__esModule ? module : /* fake namespace object */ { \"default\": module };";
if(fakeMap) return `${fakeMapDataExpression} || typeof module === "object" && module && module.__esModule ? module : /* fake namespace object */ { "default": module };`;
}
return "module";
const getReturn = type => {
if(type === 1) return "module";
if(type === 2) return "Object.assign({/* fake namespace object */}, module, { \"default\": module })";
if(type === 0) {
if(strict) {
return "/* fake namespace object */ { \"default\": module }";
} else {
return "(typeof module === \"object\" && module && module.__esModule ? module : /* fake namespace object */ { \"default\": module })";
}
}
};
if(typeof fakeMap === "number") return `return ${getReturn(fakeMap)};`;
return `return ${fakeMapDataExpression} === 1 ? ${getReturn(1)} : ${fakeMapDataExpression} ? ${getReturn(2)} : ${getReturn(0)};`;
}
getSyncSource(dependencies, id) {
const map = this.getUserRequestMap(dependencies);
const fakeMap = this.getFakeMap(dependencies);
const returnModuleObject = `return ${this.getModuleObjectSource(fakeMap)};`;
const returnModuleObject = `${this.getReturnModuleObjectSource(fakeMap)};`;
return `var map = ${JSON.stringify(map, null, "\t")};
${typeof fakeMap === "object" ? `var fakeMap = ${JSON.stringify(fakeMap, null, "\t")};` : ""}
${this.getFakeMapInitStatement(fakeMap)}
function webpackContext(req) {
var id = webpackContextResolve(req);
@ -275,8 +290,11 @@ function webpackContext(req) {
}
function webpackContextResolve(req) {
var id = map[req];
if(!(id + 1)) // check for number or string
throw new Error("Cannot find module '" + req + "'.");
if(!(id + 1)) { // check for number or string
var e = new Error('Cannot find module "' + req + '".');
e.code = 'MODULE_NOT_FOUND';
throw e;
}
return id;
}
webpackContext.keys = function webpackContextKeys() {
@ -290,22 +308,28 @@ webpackContext.id = ${JSON.stringify(id)};`;
getWeakSyncSource(dependencies, id) {
const map = this.getUserRequestMap(dependencies);
const fakeMap = this.getFakeMap(dependencies);
const returnModuleObject = `return ${this.getModuleObjectSource(fakeMap)};`;
const returnModuleObject = `${this.getReturnModuleObjectSource(fakeMap)};`;
return `var map = ${JSON.stringify(map, null, "\t")};
${typeof fakeMap === "object" ? `var fakeMap = ${JSON.stringify(fakeMap, null, "\t")};` : ""}
${this.getFakeMapInitStatement(fakeMap)}
function webpackContext(req) {
var id = webpackContextResolve(req);
if(!__webpack_require__.m[id])
throw new Error("Module '" + req + "' ('" + id + "') is not available (weak dependency)");
if(!__webpack_require__.m[id]) {
var e = new Error("Module '" + req + "' ('" + id + "') is not available (weak dependency)");
e.code = 'MODULE_NOT_FOUND';
throw e;
}
var module = __webpack_require__(id);
${returnModuleObject}
}
function webpackContextResolve(req) {
var id = map[req];
if(!(id + 1)) // check for number or string
throw new Error("Cannot find module '" + req + "'.");
if(!(id + 1)) { // check for number or string
var e = new Error('Cannot find module "' + req + '".');
e.code = 'MODULE_NOT_FOUND';
throw e;
}
return id;
}
webpackContext.keys = function webpackContextKeys() {
@ -319,15 +343,18 @@ module.exports = webpackContext;`;
getAsyncWeakSource(dependencies, id) {
const map = this.getUserRequestMap(dependencies);
const fakeMap = this.getFakeMap(dependencies);
const returnModuleObject = `return ${this.getModuleObjectSource(fakeMap)};`;
const returnModuleObject = `${this.getReturnModuleObjectSource(fakeMap)};`;
return `var map = ${JSON.stringify(map, null, "\t")};
${typeof fakeMap === "object" ? `var fakeMap = ${JSON.stringify(fakeMap, null, "\t")};` : ""}
${this.getFakeMapInitStatement(fakeMap)}
function webpackAsyncContext(req) {
return webpackAsyncContextResolve(req).then(function(id) {
if(!__webpack_require__.m[id])
throw new Error("Module '" + req + "' ('" + id + "') is not available (weak dependency)");
if(!__webpack_require__.m[id]) {
var e = new Error("Module '" + req + "' ('" + id + "') is not available (weak dependency)");
e.code = 'MODULE_NOT_FOUND';
throw e;
}
var module = __webpack_require__(id);
${returnModuleObject}
});
@ -337,8 +364,11 @@ function webpackAsyncContextResolve(req) {
// uncatched exception popping up in devtools
return Promise.resolve().then(function() {
var id = map[req];
if(!(id + 1)) // check for number or string
throw new Error("Cannot find module '" + req + "'.");
if(!(id + 1)) { // check for number or string
var e = new Error('Cannot find module "' + req + '".');
e.code = 'MODULE_NOT_FOUND';
throw e;
}
return id;
});
}
@ -353,14 +383,14 @@ module.exports = webpackAsyncContext;`;
getEagerSource(dependencies, id) {
const map = this.getUserRequestMap(dependencies);
const fakeMap = this.getFakeMap(dependencies);
const thenFunction = fakeMap ?
const thenFunction = fakeMap !== 1 ?
`function(id) {
var module = __webpack_require__(id);
return ${this.getModuleObjectSource(fakeMap)};
${this.getReturnModuleObjectSource(fakeMap)};
}` :
"__webpack_require__";
return `var map = ${JSON.stringify(map, null, "\t")};
${typeof fakeMap === "object" ? `var fakeMap = ${JSON.stringify(fakeMap, null, "\t")};` : ""}
${this.getFakeMapInitStatement(fakeMap)}
function webpackAsyncContext(req) {
return webpackAsyncContextResolve(req).then(${thenFunction});
@ -370,8 +400,11 @@ function webpackAsyncContextResolve(req) {
// uncatched exception popping up in devtools
return Promise.resolve().then(function() {
var id = map[req];
if(!(id + 1)) // check for number or string
throw new Error("Cannot find module '" + req + "'.");
if(!(id + 1)) { // check for number or string
var e = new Error('Cannot find module "' + req + '".');
e.code = 'MODULE_NOT_FOUND';
throw e;
}
return id;
});
}
@ -384,18 +417,21 @@ module.exports = webpackAsyncContext;`;
}
getLazyOnceSource(block, dependencies, id, runtimeTemplate) {
const promise = DepBlockHelpers.getDepBlockPromise(block, runtimeTemplate, "lazy-once context");
const promise = runtimeTemplate.blockPromise({
block,
message: "lazy-once context"
});
const map = this.getUserRequestMap(dependencies);
const fakeMap = this.getFakeMap(dependencies);
const thenFunction = fakeMap ?
const thenFunction = fakeMap !== 1 ?
`function(id) {
var module = __webpack_require__(id);
return ${this.getModuleObjectSource(fakeMap)};
${this.getReturnModuleObjectSource(fakeMap)};
}` :
"__webpack_require__";
return `var map = ${JSON.stringify(map, null, "\t")};
${typeof fakeMap === "object" ? `var fakeMap = ${JSON.stringify(fakeMap, null, "\t")};` : ""}
${this.getFakeMapInitStatement(fakeMap)}
function webpackAsyncContext(req) {
return webpackAsyncContextResolve(req).then(${thenFunction});
@ -403,8 +439,11 @@ function webpackAsyncContext(req) {
function webpackAsyncContextResolve(req) {
return ${promise}.then(function() {
var id = map[req];
if(!(id + 1)) // check for number or string
throw new Error("Cannot find module '" + req + "'.");
if(!(id + 1)) { // check for number or string
var e = new Error('Cannot find module "' + req + '".');
e.code = 'MODULE_NOT_FOUND';
throw e;
}
return id;
});
}
@ -446,13 +485,18 @@ module.exports = webpackAsyncContext;`;
const requestPrefix = hasMultipleOrNoChunks ?
`Promise.all(ids.slice(${chunksStartPosition}).map(__webpack_require__.e))` :
`__webpack_require__.e(ids[${chunksStartPosition}])`;
const returnModuleObject = `return ${this.getModuleObjectSource(fakeMap, "ids[1]")};`;
const returnModuleObject = `${this.getReturnModuleObjectSource(fakeMap, "ids[1]")};`;
return `var map = ${JSON.stringify(map, null, "\t")};
function webpackAsyncContext(req) {
var ids = map[req];
if(!ids)
return Promise.resolve().then(function() { throw new Error("Cannot find module '" + req + "'."); });
if(!ids) {
return Promise.resolve().then(function() {
var e = new Error('Cannot find module "' + req + '".');
e.code = 'MODULE_NOT_FOUND';
throw e;
});
}
return ${requestPrefix}.then(function() {
var module = __webpack_require__(ids[0]);
${returnModuleObject}
@ -467,7 +511,9 @@ module.exports = webpackAsyncContext;`;
getSourceForEmptyContext(id) {
return `function webpackEmptyContext(req) {
throw new Error("Cannot find module '" + req + "'.");
var e = new Error('Cannot find module "' + req + '".');
e.code = 'MODULE_NOT_FOUND';
throw e;
}
webpackEmptyContext.keys = function() { return []; };
webpackEmptyContext.resolve = webpackEmptyContext;
@ -480,7 +526,9 @@ webpackEmptyContext.id = ${JSON.stringify(id)};`;
// Here Promise.resolve().then() is used instead of new Promise() to prevent
// uncatched exception popping up in devtools
return Promise.resolve().then(function() {
throw new Error("Cannot find module '" + req + "'.");
var e = new Error('Cannot find module "' + req + '".');
e.code = 'MODULE_NOT_FOUND';
throw e;
});
}
webpackEmptyAsyncContext.keys = function() { return []; };

View File

@ -49,14 +49,18 @@ class DelegatedModule extends Module {
callback();
}
source() {
const sourceModule = this.dependencies[0].module;
source(depTemplates, runtime) {
const dep = this.dependencies[0];
const sourceModule = dep.module;
let str;
if(!sourceModule) {
str = WebpackMissingModule.moduleCode(this.sourceRequest);
} else {
str = `module.exports = (__webpack_require__(${JSON.stringify(sourceModule.id)}))`;
str = `module.exports = (${runtime.moduleExports({
module: sourceModule,
request: dep.request
})})`;
switch(this.type) {
case "require":

View File

@ -105,7 +105,7 @@ class FlagDependencyExportsPlugin {
module = queue.dequeue();
if(module.buildMeta.providedExports !== true) {
moduleWithExports = module.buildMeta && module.buildMeta.harmonyModule;
moduleWithExports = module.buildMeta && module.buildMeta.exportsType;
moduleProvidedExports = Array.isArray(module.buildMeta.providedExports) ? new Set(module.buildMeta.providedExports) : new Set();
processDependenciesBlock(module);
if(!moduleWithExports) {

View File

@ -7,6 +7,9 @@
const JsonParser = require("./JsonParser");
const ConcatSource = require("webpack-sources").ConcatSource;
const stringifySafe = data => JSON.stringify(data)
.replace(/\u2028|\u2029/g, str => str === "\u2029" ? "\\u2029" : "\\u2028"); // invalid in JavaScript but valid JSON
class JsonModulesPlugin {
apply(compiler) {
compiler.hooks.compilation.tap("JsonModulesPlugin", (compilation, {
@ -18,8 +21,22 @@ class JsonModulesPlugin {
compilation.moduleTemplates.javascript.hooks.content.tap("JsonModulesPlugin", (moduleSource, module) => {
if(module.type && module.type.startsWith("json")) {
const source = new ConcatSource();
source.add(`${module.moduleArgument}.exports = `);
source.add(moduleSource);
const data = module.buildInfo.jsonData;
if(Array.isArray(module.buildMeta.providedExports) && !module.isUsed("default")) {
// Only some exports are used: We can optimize here, by only generating a part of the JSON
const reducedJson = {};
for(const exportName of module.buildMeta.providedExports) {
if(exportName === "default")
continue;
const used = module.isUsed(exportName);
if(used) {
reducedJson[used] = data[exportName];
}
}
source.add(`${module.moduleArgument}.exports = ${stringifySafe(reducedJson)};`);
} else {
source.add(`${module.moduleArgument}.exports = ${stringifySafe(data)};`);
}
return source;
} else {
return moduleSource;

View File

@ -4,7 +4,7 @@
*/
"use strict";
const ConstDependency = require("./dependencies/ConstDependency");
const JsonExportsDependency = require("./dependencies/JsonExportsDependency");
class JsonParser {
constructor(options) {
@ -12,14 +12,12 @@ class JsonParser {
}
parse(source, state) {
const regExp = /\u2028|\u2029/g; // invalid in JavaScript but valid JSON
let match = regExp.exec(source);
while(match) {
const escaped = match[0] === "\u2028" ? "\\u2028" : "\\u2029";
const dep = new ConstDependency(escaped, [match.index, match.index]);
state.module.addDependency(dep);
match = regExp.exec(source);
}
const data = JSON.parse(source);
state.module.buildInfo.jsonData = data;
state.module.buildMeta.exportsType = "named";
if(typeof data === "object" && data)
state.module.addDependency(new JsonExportsDependency(Object.keys(data)));
state.module.addDependency(new JsonExportsDependency(["default"]));
return state;
}
}

View File

@ -248,8 +248,14 @@ class Module extends DependenciesBlock {
if(this.usedExports === true) return exportName;
let idx = this.usedExports.indexOf(exportName);
if(idx < 0) return false;
if(this.isProvided(exportName))
return Template.numberToIdentifer(idx);
// Mangle export name if possible
if(this.isProvided(exportName)) {
if(this.buildMeta.exportsType === "namespace")
return Template.numberToIdentifer(idx);
else if(this.buildMeta.exportsType === "named" && this.usedExports.indexOf("default") < 0)
return Template.numberToIdentifer(idx);
}
return exportName;
}

View File

@ -77,14 +77,14 @@ class NodeStuffPlugin {
});
parser.hooks.expression.for("module.exports").tap("NodeStuffPlugin", () => {
const module = parser.state.module;
const isHarmony = module.buildMeta && module.buildMeta.harmonyModule;
const isHarmony = module.buildMeta && module.buildMeta.exportsType;
if(!isHarmony)
return true;
});
parser.hooks.evaluateIdentifier.for("module.hot").tap("NodeStuffPlugin", ParserHelpers.evaluateToIdentifier("module.hot", false));
parser.hooks.expression.for("module").tap("NodeStuffPlugin", () => {
const module = parser.state.module;
const isHarmony = module.buildMeta && module.buildMeta.harmonyModule;
const isHarmony = module.buildMeta && module.buildMeta.exportsType;
let moduleJsPath = path.join(__dirname, "..", "buildin", isHarmony ? "harmony-module.js" : "module.js");
if(module.context) {
moduleJsPath = path.relative(parser.state.module.context, moduleJsPath);

View File

@ -4,9 +4,286 @@
*/
"use strict";
const Template = require("./Template");
module.exports = class RuntimeTemplate {
constructor(outputOptions, requestShortener) {
this.outputOptions = outputOptions || {};
this.requestShortener = requestShortener;
}
comment({
request,
chunkName,
chunkReason,
message,
exportName
}) {
let content;
if(this.outputOptions.pathinfo) {
content = [message, request, chunkName, chunkReason].filter(Boolean).map(item => this.requestShortener.shorten(item)).join(" | ");
} else {
content = [message, chunkName, chunkReason].filter(Boolean).map(item => this.requestShortener.shorten(item)).join(" | ");
}
if(!content) return "";
if(this.outputOptions.pathinfo) {
return Template.toComment(content) + " ";
} else {
return Template.toNormalComment(content) + " ";
}
}
throwMissingModuleErrorFunction({
request
}) {
const err = `Cannot find module "${request}"`;
return `function webpackMissingModule() { var e = new Error(${JSON.stringify(err)}); e.code = 'MODULE_NOT_FOUND'; throw e; }`;
}
missingModule({
request
}) {
return `!(${this.throwMissingModuleErrorFunction({ request })}())`;
}
missingModuleStatement({
request
}) {
return `${this.missingModule({ request })};\n`;
}
missingModulePromise({
request
}) {
return `Promise.resolve().then(${this.throwMissingModuleErrorFunction({ request })})`;
}
moduleId({
module,
request
}) {
if(!module) return this.missingModule({
request
});
return `${this.comment({ request })}${JSON.stringify(module.id)}`;
}
moduleRaw({
module,
request
}) {
if(!module) return this.missingModule({
request
});
return `__webpack_require__(${this.moduleId({ module, request })})`;
}
moduleExports({
module,
request
}) {
return this.moduleRaw({
module,
request
});
}
moduleNamespace({
module,
request,
strict
}) {
const rawModule = this.moduleRaw({
module,
request
});
const exportsType = module.buildMeta && module.buildMeta.exportsType;
if(exportsType === "namespace") {
return rawModule;
} else if(exportsType === "named") {
return `Object.assign({/* fake namespace object */}, ${rawModule}, { "default": ${rawModule} })`;
} else if(strict) {
return `Object({ /* fake namespace object */ "default": ${rawModule} })`;
} else {
return `Object(function() { var module = ${rawModule}; return typeof module === "object" && module && module.__esModule ? module : { /* fake namespace object */ "default": module }; }())`;
}
}
moduleNamespacePromise({
block,
module,
request,
message,
strict,
weak
}) {
if(!module) return this.missingModulePromise({
request
});
const promise = this.blockPromise({
block,
message
});
let getModuleFunction;
let idExpr = JSON.stringify(module.id);
const comment = this.comment({
request
});
let header = "";
if(weak) {
if(idExpr.length > 8) { // 'var x="nnnnnn";x,"+x+",x' vs '"nnnnnn",nnnnnn,"nnnnnn"'
header += `var id = ${idExpr}; `;
idExpr = "id";
}
header += `if(!__webpack_require__.m[${idExpr}]) { var e = new Error("Module '" + ${idExpr} + "' is not available (weak dependency)"); e.code = 'MODULE_NOT_FOUND'; throw e; } `;
}
const rawModule = this.moduleRaw({
module,
request
});
const exportsType = module.buildMeta && module.buildMeta.exportsType;
if(exportsType === "namespace") {
if(header) {
getModuleFunction = `function() { ${header}return ${rawModule}; }`;
} else {
getModuleFunction = `__webpack_require__.bind(null, ${comment}${idExpr})`;
}
} else if(exportsType === "named") {
getModuleFunction = `function() { ${header}var module = ${rawModule}; return Object.assign({/* fake namespace object */}, module, { "default": module }); }`;
} else if(strict) {
getModuleFunction = `function() { ${header}return { /* fake namespace object */ "default": ${rawModule} }; }`;
} else {
getModuleFunction = `function() { ${header}var module = ${rawModule}; return typeof module === "object" && module && module.__esModule ? module : { /* fake namespace object */ "default": module }; }`;
}
return `${promise || "Promise.resolve()"}.then(${getModuleFunction})`;
}
importStatement({
update,
module,
request,
importVar,
originModule
}) {
if(!module) return this.missingModuleStatement({
request
});
const comment = this.comment({
request
});
const optDeclaration = update ? "" : "var ";
const exportsType = module.buildMeta && module.buildMeta.exportsType;
let content = `/* harmony import */ ${optDeclaration}${importVar} = __webpack_require__(${comment}${JSON.stringify(module.id)});\n`;
if(!exportsType && !originModule.buildMeta.strictHarmonyModule) {
content += `/* harmony import */ ${optDeclaration}${importVar}_default = /*#__PURE__*/__webpack_require__.n(${importVar});\n`;
}
if(exportsType === "named") {
if(Array.isArray(module.buildMeta.providedExports))
content += `${optDeclaration}${importVar}_namespace = /*#__PURE__*/Object.assign({}, ${importVar}, {"default": ${importVar}});\n`;
else
content += `${optDeclaration}${importVar}_namespace = /*#__PURE__*/{ /* fake namespace object */ "default": ${importVar} };\n`;
}
return content;
}
exportFromImport({
module,
exportName,
originModule,
asiSafe,
isCall,
callContext,
importVar
}) {
const exportsType = module.buildMeta && module.buildMeta.exportsType;
if(!exportsType) {
if(exportName === "default") {
if(!originModule.buildMeta.strictHarmonyModule) {
if(isCall)
return `${importVar}_default()`;
else if(asiSafe)
return `(${importVar}_default())`;
else
return `${importVar}_default.a`;
} else {
return importVar;
}
} else if(originModule.buildMeta.strictHarmonyModule) {
if(exportName) {
return "/* non-default import from non-esm module */undefined";
} else if(!exportName) {
if(asiSafe) {
return `/*#__PURE__*/{ /* fake namespace object */ "default": ${importVar} }`;
} else {
return `/*#__PURE__*/Object({ /* fake namespace object */ "default": ${importVar} })`;
}
}
}
}
if(exportsType === "named") {
if(exportName === "default") {
return importVar;
} else if(!exportName) {
return `${importVar}_namespace`;
}
}
if(exportName) {
const used = module.isUsed(exportName);
const comment = used !== exportName ? Template.toNormalComment(exportName) + " " : "";
const access = `${importVar}[${comment}${JSON.stringify(used)}]`;
if(isCall) {
if(callContext === false && asiSafe)
return `(0,${access})`;
else if(callContext === false)
return `Object(${access})`;
}
return access;
} else {
return importVar;
}
}
blockPromise({
block,
message
}) {
if(!block || !block.chunks) {
const comment = this.comment({
message
});
return `Promise.resolve(${comment.trim()})`;
}
const chunks = block.chunks.filter(chunk => !chunk.hasRuntime() && chunk.id !== null);
const comment = this.comment({
message,
chunkName: block.chunkName,
chunkReason: block.chunkReason
});
if(chunks.length === 1) {
const chunkId = JSON.stringify(chunks[0].id);
return `__webpack_require__.e(${comment}${chunkId})`;
} else if(chunks.length > 0) {
const requireChunkId = chunk => `__webpack_require__.e(${JSON.stringify(chunk.id)})`;
return `Promise.all(${comment.trim()}[${chunks.map(requireChunkId).join(", ")}])`;
} else {
return `Promise.resolve(${comment.trim()})`;
}
}
onError() {
return "__webpack_require__.oe";
}
defineEsModuleFlagStatement({
exportsArgument
}) {
return `__webpack_require__.r(${exportsArgument});\n`;
}
};

View File

@ -22,7 +22,7 @@ class WebAssemblyParser extends Tapable {
// TODO extract imports
// flag it as ESM
state.module.buildMeta.harmonyModule = true;
state.module.buildMeta.exportsType = "namespace";
// extract exports
// TODO find more efficient way doing it

View File

@ -4,8 +4,6 @@
*/
"use strict";
const Dependency = require("../Dependency");
const Template = require("../Template");
const webpackMissingModuleModule = require("./WebpackMissingModule").module;
class AMDRequireArrayDependency extends Dependency {
constructor(depsArray, range) {
@ -27,25 +25,24 @@ AMDRequireArrayDependency.Template = class AMDRequireArrayDependencyTemplate {
getContent(dep, runtime) {
const requires = dep.depsArray.map((dependency) => {
const optionalComment = runtime.outputOptions.pathinfo ? Template.toComment(runtime.requestShortener.shorten(dependency.request)) : "";
return this.contentForDependency(dependency, optionalComment);
return this.contentForDependency(dependency, runtime);
});
return `[${requires.join(", ")}]`;
}
contentForDependency(dep, comment) {
contentForDependency(dep, runtime) {
if(typeof dep === "string") {
return dep;
}
if(dep.module) {
const stringifiedId = JSON.stringify(dep.module.id);
return `__webpack_require__(${comment}${stringifiedId})`;
} else if(dep.localModule) {
if(dep.localModule) {
return dep.localModule.variableName();
} else {
return runtime.moduleExports({
module: dep.module,
request: dep.request
});
}
return webpackMissingModuleModule(dep.request);
}
};

View File

@ -4,7 +4,6 @@
*/
"use strict";
const NullDependency = require("./NullDependency");
const DepBlockHelpers = require("./DepBlockHelpers");
class AMDRequireDependency extends NullDependency {
constructor(block) {
@ -16,12 +15,15 @@ class AMDRequireDependency extends NullDependency {
AMDRequireDependency.Template = class AMDRequireDependencyTemplate {
apply(dep, source, runtime) {
const depBlock = dep.block;
const wrapper = DepBlockHelpers.getLoadDepBlockWrapper(depBlock, runtime, "require");
const promise = runtime.blockPromise({
block: depBlock,
message: "AMD require"
});
// has array range but no function range
if(depBlock.arrayRange && !depBlock.functionRange) {
const startBlock = wrapper[0] + "function() {";
const endBlock = `;}${wrapper[1]}__webpack_require__.oe${wrapper[2]}`;
const startBlock = `${promise}.then(function() {`;
const endBlock = `;}).catch(${runtime.onError()})`;
source.replace(depBlock.outerRange[0], depBlock.arrayRange[0] - 1, startBlock);
source.replace(depBlock.arrayRange[1], depBlock.outerRange[1] - 1, endBlock);
return;
@ -29,8 +31,8 @@ AMDRequireDependency.Template = class AMDRequireDependencyTemplate {
// has function range but no array range
if(depBlock.functionRange && !depBlock.arrayRange) {
const startBlock = wrapper[0] + "function() {(";
const endBlock = `.call(exports, __webpack_require__, exports, module));}${wrapper[1]}__webpack_require__.oe${wrapper[2]}`;
const startBlock = `${promise}.then((`;
const endBlock = `).bind(exports, __webpack_require__, exports, module)).catch(${runtime.onError()})`;
source.replace(depBlock.outerRange[0], depBlock.functionRange[0] - 1, startBlock);
source.replace(depBlock.functionRange[1], depBlock.outerRange[1] - 1, endBlock);
return;
@ -38,14 +40,14 @@ AMDRequireDependency.Template = class AMDRequireDependencyTemplate {
// has array range, function range, and errorCallbackRange
if(depBlock.arrayRange && depBlock.functionRange && depBlock.errorCallbackRange) {
const startBlock = wrapper[0] + "function() { ";
const errorRangeBlock = `}${depBlock.functionBindThis ? ".bind(this)" : ""}${wrapper[1]}`;
const endBlock = `${depBlock.errorCallbackBindThis ? ".bind(this)" : ""}${wrapper[2]}`;
const startBlock = `${promise}.then(function() { `;
const errorRangeBlock = `}${depBlock.functionBindThis ? ".bind(this)" : ""}).catch(`;
const endBlock = `${depBlock.errorCallbackBindThis ? ".bind(this)" : ""})`;
source.replace(depBlock.outerRange[0], depBlock.arrayRange[0] - 1, startBlock);
source.insert(depBlock.arrayRange[0] + 0.9, "var __WEBPACK_AMD_REQUIRE_ARRAY__ = ");
source.replace(depBlock.arrayRange[1], depBlock.functionRange[0] - 1, "; ((");
source.insert(depBlock.functionRange[1], ").apply(null, __WEBPACK_AMD_REQUIRE_ARRAY__));");
source.replace(depBlock.arrayRange[1], depBlock.functionRange[0] - 1, "; (");
source.insert(depBlock.functionRange[1], ").apply(null, __WEBPACK_AMD_REQUIRE_ARRAY__);");
source.replace(depBlock.functionRange[1], depBlock.errorCallbackRange[0] - 1, errorRangeBlock);
source.replace(depBlock.errorCallbackRange[1], depBlock.outerRange[1] - 1, endBlock);
return;
@ -53,12 +55,12 @@ AMDRequireDependency.Template = class AMDRequireDependencyTemplate {
// has array range, function range, but no errorCallbackRange
if(depBlock.arrayRange && depBlock.functionRange) {
const startBlock = wrapper[0] + "function() { ";
const endBlock = `}${depBlock.functionBindThis ? ".bind(this)" : ""}${wrapper[1]}__webpack_require__.oe${wrapper[2]}`;
const startBlock = `${promise}.then(function() { `;
const endBlock = `}${depBlock.functionBindThis ? ".bind(this)" : ""}).catch(${runtime.onError()})`;
source.replace(depBlock.outerRange[0], depBlock.arrayRange[0] - 1, startBlock);
source.insert(depBlock.arrayRange[0] + 0.9, "var __WEBPACK_AMD_REQUIRE_ARRAY__ = ");
source.replace(depBlock.arrayRange[1], depBlock.functionRange[0] - 1, "; ((");
source.insert(depBlock.functionRange[1], ").apply(null, __WEBPACK_AMD_REQUIRE_ARRAY__));");
source.replace(depBlock.arrayRange[1], depBlock.functionRange[0] - 1, "; (");
source.insert(depBlock.functionRange[1], ").apply(null, __WEBPACK_AMD_REQUIRE_ARRAY__);");
source.replace(depBlock.functionRange[1], depBlock.outerRange[1] - 1, endBlock);
}
}

View File

@ -4,14 +4,15 @@
*/
"use strict";
const Template = require("../Template");
class ContextDependencyTemplateAsId {
apply(dep, source, runtime) {
const comment = runtime.outputOptions.pathinfo ? Template.toComment(runtime.requestShortener.shorten(dep.request)) + " " : "";
const moduleExports = runtime.moduleExports({
module: dep.module,
request: dep.request
});
if(dep.module && dep.module.dependencies && dep.module.dependencies.length > 0) {
if(dep.module) {
if(dep.valueRange) {
if(Array.isArray(dep.replaces)) {
for(let i = 0; i < dep.replaces.length; i++) {
@ -20,13 +21,12 @@ class ContextDependencyTemplateAsId {
}
}
source.replace(dep.valueRange[1], dep.range[1] - 1, ")");
source.replace(dep.range[0], dep.valueRange[0] - 1, "__webpack_require__(" + comment + JSON.stringify(dep.module.id) + ").resolve(" + (typeof dep.prepend === "string" ? JSON.stringify(dep.prepend) : "") + "");
source.replace(dep.range[0], dep.valueRange[0] - 1, `${moduleExports}.resolve(${typeof dep.prepend === "string" ? JSON.stringify(dep.prepend) : ""}`);
} else {
source.replace(dep.range[0], dep.range[1] - 1, "__webpack_require__(" + comment + JSON.stringify(dep.module.id) + ").resolve");
source.replace(dep.range[0], dep.range[1] - 1, `${moduleExports}.resolve`);
}
} else {
const content = require("./WebpackMissingModule").module(dep.request);
source.replace(dep.range[0], dep.range[1] - 1, content);
source.replace(dep.range[0], dep.range[1] - 1, moduleExports);
}
}
}

View File

@ -4,16 +4,15 @@
*/
"use strict";
const Template = require("../Template");
class ContextDependencyTemplateAsRequireCall {
apply(dep, source, runtime) {
const comment = runtime.outputOptions.pathinfo ? Template.toComment(runtime.requestShortener.shorten(dep.options.request)) + " " : "";
const moduleExports = runtime.moduleExports({
module: dep.module,
request: dep.request
});
const containsDeps = dep.module && dep.module.dependencies && dep.module.dependencies.length > 0;
const isAsync = dep.options.mode !== "sync" && dep.options.mode !== "weak";
if(dep.module && (isAsync || containsDeps)) {
if(dep.module) {
if(dep.valueRange) {
if(Array.isArray(dep.replaces)) {
for(let i = 0; i < dep.replaces.length; i++) {
@ -22,13 +21,12 @@ class ContextDependencyTemplateAsRequireCall {
}
}
source.replace(dep.valueRange[1], dep.range[1] - 1, ")");
source.replace(dep.range[0], dep.valueRange[0] - 1, "__webpack_require__(" + comment + JSON.stringify(dep.module.id) + ")(" + (typeof dep.prepend === "string" ? JSON.stringify(dep.prepend) : "") + "");
source.replace(dep.range[0], dep.valueRange[0] - 1, `${moduleExports}(${typeof dep.prepend === "string" ? JSON.stringify(dep.prepend) : ""}`);
} else {
source.replace(dep.range[0], dep.range[1] - 1, "__webpack_require__(" + comment + JSON.stringify(dep.module.id) + ")");
source.replace(dep.range[0], dep.range[1] - 1, moduleExports);
}
} else {
const content = require("./WebpackMissingModule").module(dep.request);
source.replace(dep.range[0], dep.range[1] - 1, content);
source.replace(dep.range[0], dep.range[1] - 1, moduleExports);
}
}
}

View File

@ -1,36 +0,0 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const Template = require("../Template");
const DepBlockHelpers = exports;
DepBlockHelpers.getLoadDepBlockWrapper = (depBlock, runtimeTemplate, name) => {
const promiseCode = DepBlockHelpers.getDepBlockPromise(depBlock, runtimeTemplate, name);
return [
promiseCode + ".then(",
").catch(",
")"
];
};
DepBlockHelpers.getDepBlockPromise = (depBlock, runtimeTemplate, name) => {
if(depBlock.chunks) {
const chunks = depBlock.chunks.filter(chunk => !chunk.hasRuntime() && chunk.id !== null);
const pathChunkCheck = runtimeTemplate.outputOptions.pathinfo && depBlock.chunkName;
const shortChunkName = runtimeTemplate.requestShortener.shorten(depBlock.chunkName);
const chunkReason = Template.toNormalComment(depBlock.chunkReason);
const requireChunkId = chunk => "__webpack_require__.e(" + JSON.stringify(chunk.id) + ")";
name = Template.toNormalComment(name);
if(chunks.length === 1) {
const chunkId = JSON.stringify(chunks[0].id);
return `__webpack_require__.e${name}(${chunkId}${pathChunkCheck ? Template.toComment(shortChunkName) : ""}${chunkReason})`;
} else if(chunks.length > 0) {
return `Promise.all${name}(${pathChunkCheck ? Template.toComment(shortChunkName) : ""}[${chunks.map(requireChunkId).join(", ")}])`;
}
}
return "Promise.resolve()";
};

View File

@ -24,7 +24,7 @@ HarmonyAcceptDependency.Template = class HarmonyAcceptDependencyTemplate {
apply(dep, source, runtime) {
const content = dep.dependencies
.filter(dependency => HarmonyImportDependency.Template.isImportEmitted(dependency, source))
.map(dependency => dependency.getImportStatement(false, runtime))
.map(dependency => dependency.getImportStatement(true, runtime))
.join("");
if(dep.hasCallback) {

View File

@ -17,11 +17,12 @@ class HarmonyCompatibilityDependency extends NullDependency {
}
HarmonyCompatibilityDependency.Template = class HarmonyExportDependencyTemplate {
apply(dep, source) {
apply(dep, source, runtime) {
const usedExports = dep.originModule.usedExports;
if(usedExports !== false && !Array.isArray(usedExports)) {
const exportName = dep.originModule.exportsArgument;
const content = `__webpack_require__.r(${exportName});\n`;
const content = runtime.defineEsModuleFlagStatement({
exportsArgument: dep.originModule.exportsArgument
});
source.insert(-10, content);
}
}

View File

@ -43,7 +43,7 @@ module.exports = class HarmonyDetectionParserPlugin {
};
module.addDependency(initDep);
parser.state.harmonyParserScope = parser.state.harmonyParserScope || {};
module.buildMeta.harmonyModule = true;
module.buildMeta.exportsType = "namespace";
module.buildInfo.strict = true;
module.buildInfo.exportsArgument = "__webpack_exports__";
if(isStrictHarmony) {
@ -55,13 +55,13 @@ module.exports = class HarmonyDetectionParserPlugin {
const skipInHarmony = () => {
const module = parser.state.module;
if(module && module.buildMeta && module.buildMeta.harmonyModule)
if(module && module.buildMeta && module.buildMeta.exportsType)
return true;
};
const nullInHarmony = () => {
const module = parser.state.module;
if(module && module.buildMeta && module.buildMeta.harmonyModule)
if(module && module.buildMeta && module.buildMeta.exportsType)
return null;
};

View File

@ -40,7 +40,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
};
}
const isNotAHarmonyModule = importedModule.buildMeta && !importedModule.buildMeta.harmonyModule;
const isNotAHarmonyModule = importedModule.buildMeta && !importedModule.buildMeta.exportsType;
const strictHarmonyModule = this.originModule.buildMeta.strictHarmonyModule;
if(name && id === "default" && isNotAHarmonyModule) {
if(strictHarmonyModule) {
@ -288,7 +288,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
return;
}
if(!importedModule.buildMeta || !importedModule.buildMeta.harmonyModule) {
if(!importedModule.buildMeta || !importedModule.buildMeta.exportsType) {
// It's not an harmony module
if(this.originModule.buildMeta.strictHarmonyModule && this.id !== "default") {
// In strict harmony modules we only support the default export
@ -339,8 +339,7 @@ module.exports = HarmonyExportImportedSpecifierDependency;
HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedSpecifierDependencyTemplate extends HarmonyImportDependency.Template {
harmonyInit(dep, source, runtime, dependencyTemplates) {
super.harmonyInit(dep, source, runtime, dependencyTemplates);
const importVar = dep.getImportVar();
const content = this.getContent(dep, importVar);
const content = this.getContent(dep);
source.insert(-1, content);
}
@ -380,7 +379,7 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
return super.getHarmonyInitOrder(dep);
}
getContent(dep, name) {
getContent(dep) {
const mode = dep.getMode();
const module = dep.originModule;
const importedModule = dep.module;
@ -433,7 +432,7 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
else
content += "if(__WEBPACK_IMPORT_KEY__ !== 'default') ";
const exportsName = dep.originModule.exportsArgument;
return content + `(function(key) { __webpack_require__.d(${exportsName}, key, function() { return ${name}[key]; }) }(__WEBPACK_IMPORT_KEY__));\n`;
return content + `(function(key) { __webpack_require__.d(${exportsName}, key, function() { return ${importVar}[key]; }) }(__WEBPACK_IMPORT_KEY__));\n`;
}
default:

View File

@ -34,35 +34,20 @@ class HarmonyImportDependency extends ModuleDependency {
return importVar;
}
getImportStatement(declare, runtime) {
const module = this.module;
const comment = runtime.outputOptions.pathinfo ? Template.toComment(runtime.requestShortener.shorten(this.request)) : "";
const optDeclaration = declare ? "var " : "";
const optNewline = declare ? "\n" : " ";
if(!module) {
const stringifiedError = JSON.stringify(`Cannot find module "${this.request}"`);
return `throw new Error(${stringifiedError});${optNewline}`;
}
const importVar = this.getImportVar();
if(importVar) {
const isHarmonyModule = module.buildMeta && module.buildMeta.harmonyModule;
const content = `/* harmony import */ ${optDeclaration}${importVar} = __webpack_require__(${comment}${JSON.stringify(module.id)});${optNewline}`;
if(isHarmonyModule || this.originModule.buildMeta.strictHarmonyModule) {
return content;
}
return `${content}/* harmony import */ ${optDeclaration}${importVar}_default = /*#__PURE__*/__webpack_require__.n(${importVar});${optNewline}`;
}
return "";
getImportStatement(update, runtime) {
return runtime.importStatement({
update,
module: this.module,
importVar: this.getImportVar(),
request: this.request,
originModule: this.originModule
});
}
updateHash(hash) {
super.updateHash(hash);
const importedModule = this.module;
hash.update((importedModule && (!importedModule.buildMeta || importedModule.buildMeta.harmonyModule)) + "");
hash.update((importedModule && (!importedModule.buildMeta || importedModule.buildMeta.exportsType)) + "");
hash.update((importedModule && importedModule.id) + "");
}
}
@ -95,7 +80,7 @@ HarmonyImportDependency.Template = class HarmonyImportDependencyTemplate {
const key = dep.module || dep.request;
if(key && sourceInfo.emittedImports.get(key)) return;
sourceInfo.emittedImports.set(key, true);
const content = dep.getImportStatement(true, runtime);
const content = dep.getImportStatement(false, runtime);
source.insert(-1, content);
}
};

View File

@ -8,7 +8,7 @@ const HarmonyImportDependency = require("./HarmonyImportDependency");
class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
constructor(request, originModule, sourceOrder, parserScope, id, name, range, strictExportPresence) {
super(request, originModule, sourceOrder, parserScope);
this.id = id;
this.id = id === null ? null : `${id}`;
this.name = name;
this.range = range;
this.strictExportPresence = strictExportPresence;
@ -50,7 +50,7 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
return;
}
if(!importedModule.buildMeta || !importedModule.buildMeta.harmonyModule) {
if(!importedModule.buildMeta || !importedModule.buildMeta.exportsType) {
// It's not an harmony module
if(this.originModule.buildMeta.strictHarmonyModule && this.id !== "default") {
// In strict harmony modules we only support the default export
@ -89,7 +89,7 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
const importedModule = this.module;
hash.update((importedModule && this.id) + "");
hash.update((importedModule && this.id && importedModule.isUsed(this.id)) + "");
hash.update((importedModule && (!importedModule.buildMeta || importedModule.buildMeta.harmonyModule)) + "");
hash.update((importedModule && (!importedModule.buildMeta || importedModule.buildMeta.exportsType)) + "");
hash.update((importedModule && (importedModule.used + JSON.stringify(importedModule.usedExports))) + "");
}
}
@ -97,60 +97,21 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
HarmonyImportSpecifierDependency.Template = class HarmonyImportSpecifierDependencyTemplate extends HarmonyImportDependency.Template {
apply(dep, source, runtime) {
super.apply(dep, source, runtime);
const importedVar = dep.getImportVar();
const content = this.getContent(dep, importedVar);
const content = this.getContent(dep, runtime);
source.replace(dep.range[0], dep.range[1] - 1, content);
}
getContent(dep, importedVar) {
const importedModule = dep.module;
const nonHarmonyImport = !(importedModule && (!importedModule.buildMeta || importedModule.buildMeta.harmonyModule));
const importedVarSuffix = this.getImportVarSuffix(dep.id, importedModule);
const shortHandPrefix = dep.shorthand ? `${dep.name}: ` : "";
// Note: dep.call and dep.shorthand are exclusive
if(nonHarmonyImport) {
const defaultExport = dep.id === "default";
if(dep.originModule.buildMeta.strictHarmonyModule) {
if(defaultExport) {
return `${shortHandPrefix}${importedVar}`;
}
if(!dep.id) {
if(shortHandPrefix)
return `${shortHandPrefix}/* fake namespace object for non-esm import */ { default: ${importedVar} }`;
else
return `Object(/* fake namespace object for non-esm import */{ "default": ${importedVar} })`;
}
return `${shortHandPrefix}/* non-default import from non-esm module */undefined`;
} else {
if(dep.call && defaultExport) {
return `${shortHandPrefix}${importedVar}_default()`;
}
if(defaultExport) {
return `${shortHandPrefix}${importedVar}_default.a`;
}
}
}
if(dep.call && dep.id && dep.directImport) {
return `Object(${importedVar}${importedVarSuffix})`;
}
return `${shortHandPrefix}${importedVar}${importedVarSuffix}`;
}
getImportVarSuffix(id, importedModule) {
if(id) {
const used = importedModule ? importedModule.isUsed(id) : id;
const optionalComment = id !== used ? " /* " + id + " */" : "";
return `[${JSON.stringify(used)}${optionalComment}]`;
}
return "";
getContent(dep, runtime) {
const exportExpr = runtime.exportFromImport({
module: dep.module,
exportName: dep.id,
originModule: dep.originModule,
asiSafe: dep.shorthand,
isCall: dep.call,
callContext: !dep.directImport,
importVar: dep.getImportVar()
});
return dep.shorthand ? `${dep.name}: ${exportExpr}` : exportExpr;
}
};

View File

@ -4,9 +4,6 @@
*/
"use strict";
const ModuleDependency = require("./ModuleDependency");
const Template = require("../Template");
const DepBlockHelpers = require("./DepBlockHelpers");
const webpackMissingPromiseModule = require("./WebpackMissingModule").promise;
class ImportDependency extends ModuleDependency {
constructor(request, originModule, block) {
@ -22,31 +19,15 @@ class ImportDependency extends ModuleDependency {
ImportDependency.Template = class ImportDependencyTemplate {
apply(dep, source, runtime) {
const depBlock = dep.block;
const promise = DepBlockHelpers.getDepBlockPromise(depBlock, runtime, "import()");
const comment = runtime.outputOptions.pathinfo ? Template.toComment(runtime.requestShortener.shorten(dep.request)) : "";
const content = runtime.moduleNamespacePromise({
block: dep.block,
module: dep.module,
request: dep.request,
strict: dep.originModule.buildMeta.strictHarmonyModule,
message: "import()"
});
const content = this.getContent(promise, dep, comment);
source.replace(depBlock.range[0], depBlock.range[1] - 1, content);
}
getContent(promise, dep, comment) {
let getModuleFunction;
if(dep.module) {
const stringifiedId = JSON.stringify(dep.module.id);
if(dep.module.buildMeta && dep.module.buildMeta.harmonyModule) {
getModuleFunction = `__webpack_require__.bind(null, ${comment}${stringifiedId})`;
} else if(dep.originModule.buildMeta.strictHarmonyModule) {
getModuleFunction = `function() { return /* fake namespace object */ { "default": __webpack_require__(${comment}${stringifiedId}) }; }`;
} else {
getModuleFunction = `function() { var module = __webpack_require__(${comment}${stringifiedId}); return typeof module === "object" && module && module.__esModule ? module : /* fake namespace object */ { "default": module }; }`;
}
return `${promise || "Promise.resolve()"}.then(${getModuleFunction})`;
}
return webpackMissingPromiseModule(dep.request);
source.replace(dep.block.range[0], dep.block.range[1] - 1, content);
}
};

View File

@ -4,36 +4,29 @@
*/
"use strict";
const ModuleDependency = require("./ModuleDependency");
const Template = require("../Template");
const webpackMissingPromiseModule = require("./WebpackMissingModule").promise;
class ImportEagerDependency extends ModuleDependency {
constructor(request, range) {
constructor(request, originModule, range) {
super(request);
this.originModule = originModule;
this.range = range;
}
get type() {
return "import()";
return "import() eager";
}
}
ImportEagerDependency.Template = class ImportEagerDependencyTemplate {
apply(dep, source, runtime) {
const comment = runtime.outputOptions.pathinfo ? Template.toComment(runtime.requestShortener.shorten(dep.request)) : "";
const content = this.getContent(dep, comment);
const content = runtime.moduleNamespacePromise({
module: dep.module,
request: dep.request,
strict: dep.originModule.buildMeta.strictHarmonyModule,
message: "import() eager"
});
source.replace(dep.range[0], dep.range[1] - 1, content);
}
getContent(dep, comment) {
if(dep.module) {
const stringifiedId = JSON.stringify(dep.module.id);
return `new Promise(function(resolve) { resolve(__webpack_require__(${comment}${stringifiedId})); })`;
}
return webpackMissingPromiseModule(dep.request);
}
};
module.exports = ImportEagerDependency;

View File

@ -65,10 +65,10 @@ class ImportParserPlugin {
}
if(mode === "eager") {
const dep = new ImportEagerDependency(param.string, expr.range);
const dep = new ImportEagerDependency(param.string, parser.state.module, expr.range);
parser.state.current.addDependency(dep);
} else if(mode === "weak") {
const dep = new ImportWeakDependency(param.string, expr.range);
const dep = new ImportWeakDependency(param.string, parser.state.module, expr.range);
parser.state.current.addDependency(dep);
} else {
const depBlock = new ImportDependenciesBlock(param.string, expr.range, chunkName, parser.state.module, expr.loc, parser.state.module);

View File

@ -4,12 +4,11 @@
*/
"use strict";
const ModuleDependency = require("./ModuleDependency");
const Template = require("../Template");
const webpackMissingPromiseModule = require("./WebpackMissingModule").promise;
class ImportWeakDependency extends ModuleDependency {
constructor(request, range) {
constructor(request, originModule, range) {
super(request);
this.originModule = originModule;
this.range = range;
this.weak = true;
}
@ -21,20 +20,15 @@ class ImportWeakDependency extends ModuleDependency {
ImportWeakDependency.Template = class ImportDependencyTemplate {
apply(dep, source, runtime) {
const comment = runtime.outputOptions.pathinfo ? Template.toComment(runtime.requestShortener.shorten(dep.request)) : "";
const content = this.getContent(dep, comment);
const content = runtime.moduleNamespacePromise({
module: dep.module,
request: dep.request,
strict: dep.originModule.buildMeta.strictHarmonyModule,
message: "import() weak",
weak: true
});
source.replace(dep.range[0], dep.range[1] - 1, content);
}
getContent(dep, comment) {
if(dep.module) {
const stringifiedId = JSON.stringify(dep.module.id);
return `Promise.resolve(${comment}${stringifiedId}).then(function(id) { if(!__webpack_require__.m[id]) throw new Error("Module '" + id + "' is not available (weak dependency)"); return __webpack_require__(id); })`;
}
return webpackMissingPromiseModule(dep.request);
}
};
module.exports = ImportWeakDependency;

View File

@ -0,0 +1,25 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const NullDependency = require("./NullDependency");
class JsonExportsDependency extends NullDependency {
constructor(exports) {
super();
this.exports = exports;
}
get type() {
return "json exports";
}
getExports() {
return {
exports: this.exports
};
}
}
module.exports = JsonExportsDependency;

View File

@ -4,19 +4,14 @@
*/
"use strict";
const Template = require("../Template");
class ModuleDependencyTemplateAsId {
apply(dep, source, runtime) {
if(!dep.range) return;
const comment = runtime.outputOptions.pathinfo ?
Template.toComment(runtime.requestShortener.shorten(dep.request)) + " " : "";
let content;
if(dep.module)
content = comment + JSON.stringify(dep.module.id);
else
content = require("./WebpackMissingModule").module(dep.request);
const content = runtime.moduleId({
module: dep.module,
request: dep.request
});
source.replace(dep.range[0], dep.range[1] - 1, content);
}
}

View File

@ -4,19 +4,14 @@
*/
"use strict";
const Template = require("../Template");
class ModuleDependencyTemplateAsRequireId {
apply(dep, source, runtime) {
if(!dep.range) return;
const comment = runtime.outputOptions.pathinfo ?
Template.toComment(runtime.requestShortener.shorten(dep.request)) + " " : "";
let content;
if(dep.module)
content = `__webpack_require__(${comment}${JSON.stringify(dep.module.id)})`;
else
content = require("./WebpackMissingModule").module(dep.request);
const content = runtime.moduleExports({
module: dep.module,
request: dep.request
});
source.replace(dep.range[0], dep.range[1] - 1, content);
}
}

View File

@ -4,7 +4,6 @@
*/
"use strict";
const NullDependency = require("./NullDependency");
const DepBlockHelpers = require("./DepBlockHelpers");
class RequireEnsureDependency extends NullDependency {
constructor(block) {
@ -20,15 +19,18 @@ class RequireEnsureDependency extends NullDependency {
RequireEnsureDependency.Template = class RequireEnsureDependencyTemplate {
apply(dep, source, runtime) {
const depBlock = dep.block;
const wrapper = DepBlockHelpers.getLoadDepBlockWrapper(depBlock, runtime, "require.ensure");
const promise = runtime.blockPromise({
block: depBlock,
message: "require.ensure"
});
const errorCallbackExists = depBlock.expr.arguments.length === 4 || (!depBlock.chunkName && depBlock.expr.arguments.length === 3);
const startBlock = wrapper[0] + "(";
const middleBlock = `).bind(null, __webpack_require__)${wrapper[1]}`;
const endBlock = `${middleBlock}__webpack_require__.oe${wrapper[2]}`;
const startBlock = `${promise}.then((`;
const middleBlock = ").bind(null, __webpack_require__)).catch(";
const endBlock = `).bind(null, __webpack_require__)).catch(${runtime.onError()})`;
source.replace(depBlock.expr.range[0], depBlock.expr.arguments[1].range[0] - 1, startBlock);
if(errorCallbackExists) {
source.replace(depBlock.expr.arguments[1].range[1], depBlock.expr.arguments[2].range[0] - 1, middleBlock);
source.replace(depBlock.expr.arguments[2].range[1], depBlock.expr.range[1] - 1, wrapper[2]);
source.replace(depBlock.expr.arguments[2].range[1], depBlock.expr.range[1] - 1, ")");
} else {
source.replace(depBlock.expr.arguments[1].range[1], depBlock.expr.range[1] - 1, endBlock);
}

View File

@ -579,7 +579,7 @@ class ConcatenatedModule extends Module {
}
case "external":
{
info.interop = info.module.buildMeta && !info.module.buildMeta.harmonyModule;
info.interop = info.module.buildMeta && !info.module.buildMeta.exportsType;
const externalName = this.findNewName("", allUsedNames, null, info.module.readableIdentifier(requestShortener));
allUsedNames.add(externalName);
info.name = externalName;
@ -624,7 +624,9 @@ class ConcatenatedModule extends Module {
// add harmony compatibility flag (must be first because of possible circular dependencies)
const usedExports = this.rootModule.usedExports;
if(usedExports === true) {
result.add(`__webpack_require__.r(${this.exportsArgument});\n`);
result.add(runtimeTemplate.defineEsModuleFlagStatement({
exportsArgument: this.exportsArgument
}));
}
// define required namespace objects (must be before evaluation modules)

View File

@ -54,7 +54,7 @@ class ModuleConcatenationPlugin {
const possibleInners = new Set();
for(const module of modules) {
// Only harmony modules are valid for optimization
if(!module.buildMeta || !module.buildMeta.harmonyModule || !module.dependencies.some(d => d instanceof HarmonyCompatibilityDependency)) {
if(!module.buildMeta || module.buildMeta.exportsType !== "namespace" || !module.dependencies.some(d => d instanceof HarmonyCompatibilityDependency)) {
setBailoutReason(module, "Module is not an ECMAScript module");
continue;
}

View File

@ -1,135 +0,0 @@
"use strict";
const _ = require("lodash");
require("should");
const sinon = require("sinon");
const ContextDependencyTemplateAsId = require("../lib/dependencies/ContextDependencyTemplateAsId");
describe("ContextDependencyTemplateAsId", () => {
let env;
beforeEach(() => {
env = {
source: {
replace: sinon.stub()
},
runtimeTemplate: {
outputOptions: {
pathinfo: true
},
requestShortener: {
shorten: (request) => `shortened ${request}`
}
},
module: {
id: "123",
dependencies: [
"myModuleDependency"
]
},
baseDependency: {
range: [1, 25],
request: "myModule"
}
};
});
it("has apply function", () => {
(new ContextDependencyTemplateAsId()).apply.should.be.a.Function();
});
describe("when applied", () => {
describe("with module missing depedencies", () => {
beforeEach(() => {
new ContextDependencyTemplateAsId().apply(env.baseDependency, env.source, env.runtimeTemplate);
});
it("replaces source with missing module error", () => {
env.source.replace.callCount.should.be.exactly(1);
sinon.assert.calledWith(env.source.replace, 1, 24, "!(function webpackMissingModule() { var e = new Error(\"Cannot find module \\\"myModule\\\"\"); e.code = 'MODULE_NOT_FOUND'; throw e; }())");
});
});
describe("with module which does not have a value range", () => {
beforeEach(() => {
env.dependency = _.extend(env.baseDependency, {
prepend: "prepend value",
module: env.module
});
});
describe("and path info true", function() {
beforeEach(function() {
env.runtimeTemplate.outputOptions.pathinfo = true;
new ContextDependencyTemplateAsId().apply(env.dependency, env.source, env.runtimeTemplate);
});
it("replaces source with webpack require with comment", () => {
env.source.replace.callCount.should.be.exactly(1);
sinon.assert.calledWith(env.source.replace, 1, 24, "__webpack_require__(/*! shortened myModule */ \"123\").resolve");
});
});
describe("and path info false", function() {
beforeEach(function() {
env.runtimeTemplate.outputOptions.pathinfo = false;
new ContextDependencyTemplateAsId().apply(env.dependency, env.source, env.runtimeTemplate);
});
it("replaces source with webpack require without comment", () => {
env.source.replace.callCount.should.be.exactly(1);
sinon.assert.calledWith(env.source.replace, 1, 24, "__webpack_require__(\"123\").resolve");
});
});
});
describe("with module which has a value range", () => {
describe("with no replacements", () => {
beforeEach(() => {
const dependency = _.extend(env.baseDependency, {
valueRange: [8, 18],
prepend: "prepend value",
module: env.module
});
new ContextDependencyTemplateAsId().apply(dependency, env.source, env.runtimeTemplate);
});
it("replaces source with webpack require and wraps value", () => {
env.source.replace.callCount.should.be.exactly(2);
sinon.assert.calledWith(env.source.replace, 18, 24, ")");
sinon.assert.calledWith(env.source.replace, 1, 7, "__webpack_require__(/*! shortened myModule */ \"123\").resolve(\"prepend value\"");
});
});
describe("with replacements", () => {
beforeEach(() => {
const dependency = _.extend(env.baseDependency, {
valueRange: [8, 18],
replaces: [{
value: "foo",
range: [9, 11]
},
{
value: "bar",
range: [13, 15]
}
],
prepend: "prepend value",
module: env.module
});
new ContextDependencyTemplateAsId().apply(dependency, env.source, env.runtimeTemplate);
});
it("replaces source with webpack require, wraps value and make replacements", () => {
env.source.replace.callCount.should.be.exactly(4);
sinon.assert.calledWith(env.source.replace, 9, 10, "foo");
sinon.assert.calledWith(env.source.replace, 13, 14, "bar");
sinon.assert.calledWith(env.source.replace, 18, 24, ")");
sinon.assert.calledWith(env.source.replace, 1, 7, "__webpack_require__(/*! shortened myModule */ \"123\").resolve(\"prepend value\"");
});
});
});
});
});

View File

@ -0,0 +1,11 @@
module.exports = function() {
let str = "";
let sum = ["1"];
const query = +this.query.substr(1);
for(let i = 0; i < query; i++) {
str += `import b${i} from "./b?${Math.floor(i/2)}!";\n`;
sum.push(`b${i}`);
}
str += "export default " + sum.join(" + ");
return str;
}

View File

@ -1,46 +1,46 @@
it("should be able to use eager mode", function(done) {
it("should be able to use eager mode", function() {
function load(name) {
return import(/* webpackMode: "eager" */ "./dir1/" + name);
}
testChunkLoading(load, true, true, done);
return testChunkLoading(load, true, true);
});
it("should be able to use lazy-once mode", function(done) {
it("should be able to use lazy-once mode", function() {
function load(name) {
return import(/* webpackMode: "lazy-once" */ "./dir2/" + name);
}
testChunkLoading(load, false, true, done);
return testChunkLoading(load, false, true);
});
it("should be able to use lazy-once mode with name", function(done) {
it("should be able to use lazy-once mode with name", function() {
function load(name) {
return import(/* webpackMode: "lazy-once", webpackChunkName: "name-lazy-once" */ "./dir3/" + name);
}
testChunkLoading(load, false, true, done);
return testChunkLoading(load, false, true);
});
it("should be able to use lazy mode", function(done) {
it("should be able to use lazy mode", function() {
function load(name) {
return import(/* webpackMode: "lazy" */ "./dir4/" + name);
}
testChunkLoading(load, false, false, done);
return testChunkLoading(load, false, false);
});
it("should be able to use lazy mode with name", function(done) {
it("should be able to use lazy mode with name", function() {
function load(name) {
return import(/* webpackMode: "lazy", webpackChunkName: "name-lazy" */ "./dir5/" + name);
}
testChunkLoading(load, false, false, done);
return testChunkLoading(load, false, false);
});
it("should be able to use lazy mode with name and placeholder", function(done) {
it("should be able to use lazy mode with name and placeholder", function() {
function load(name) {
return import(/* webpackMode: "lazy", webpackChunkName: "name-lazy-[request]" */ "./dir6/" + name);
}
testChunkLoading(load, false, false, done);
return testChunkLoading(load, false, false);
});
it("should be able to combine chunks by name", function(done) {
it("should be able to combine chunks by name", function() {
function load(name) {
switch(name) {
case "a":
@ -55,20 +55,20 @@ it("should be able to combine chunks by name", function(done) {
throw new Error("Unexcepted test data");
}
}
testChunkLoading(load, false, true, done);
return testChunkLoading(load, false, true);
});
it("should be able to use weak mode", function(done) {
it("should be able to use weak mode", function() {
function load(name) {
return import(/* webpackMode: "weak" */ "./dir8/" + name);
}
require("./dir8/a") // chunks served manually by the user
require("./dir8/b")
require("./dir8/c")
testChunkLoading(load, true, true, done);
return testChunkLoading(load, true, true);
});
it("should be able to use weak mode (without context)", function(done) {
it("should be able to use weak mode (without context)", function() {
function load(name) {
switch(name) {
case "a":
@ -84,33 +84,31 @@ it("should be able to use weak mode (without context)", function(done) {
require("./dir9/a") // chunks served manually by the user
require("./dir9/b")
require("./dir9/c")
testChunkLoading(load, true, true, done);
return testChunkLoading(load, true, true);
});
it("should not find module when mode is weak and chunk not served elsewhere", function(done) {
it("should not find module when mode is weak and chunk not served elsewhere", function() {
var name = "a";
import(/* webpackMode: "weak" */ "./dir10/" + name)
return import(/* webpackMode: "weak" */ "./dir10/" + name)
.catch(function(e) {
e.should.match(/not available/);
done();
e.should.match({ message: /not available/, code: /MODULE_NOT_FOUND/ });
})
});
it("should not find module when mode is weak and chunk not served elsewhere (without context)", function(done) {
import(/* webpackMode: "weak" */ "./dir11/a")
it("should not find module when mode is weak and chunk not served elsewhere (without context)", function() {
return import(/* webpackMode: "weak" */ "./dir11/a")
.catch(function(e) {
e.should.match(/not available/);
done();
e.should.match({ message: /not available/, code: /MODULE_NOT_FOUND/ });
})
});
function testChunkLoading(load, expectedSyncInitial, expectedSyncRequested, done) {
function testChunkLoading(load, expectedSyncInitial, expectedSyncRequested) {
var sync = false;
var syncInitial = true;
Promise.all([load("a"), load("b")]).then(function() {
var p = Promise.all([load("a"), load("b")]).then(function() {
syncInitial.should.be.eql(expectedSyncInitial);
sync = true;
Promise.all([
var p = Promise.all([
load("a").then(function(a) {
a.should.be.eql({ default: "a" });
sync.should.be.eql(true);
@ -119,12 +117,14 @@ function testChunkLoading(load, expectedSyncInitial, expectedSyncRequested, done
c.should.be.eql({ default: "c" });
sync.should.be.eql(expectedSyncRequested);
})
]).then(function() { done(); }, done);
]);
Promise.resolve().then(function(){}).then(function(){}).then(function(){}).then(function(){
sync = false;
});
}).catch(done);
return p;
});
Promise.resolve().then(function(){}).then(function(){}).then(function(){}).then(function(){
syncInitial = false;
});
return p;
}

View File

@ -0,0 +1 @@
null

View File

@ -0,0 +1 @@
123

View File

@ -0,0 +1 @@
[1, 2, 3, 4]

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,5 @@
{
"1": "x",
"bb": 2,
"aa": 1
}

View File

@ -0,0 +1,5 @@
{
"named": "named",
"default": "default",
"__esModule": true
}

View File

@ -0,0 +1,3 @@
{
"named": {}
}

View File

@ -0,0 +1,10 @@
it("should require json via require", function() {
({ data: require("./a.json") }).should.be.eql({ data: null });
({ data: require("./b.json") }).should.be.eql({ data: 123 });
({ data: require("./c.json") }).should.be.eql({ data: [1, 2, 3, 4] });
({ data: require("./e.json") }).should.be.eql({ data: {
"aa": 1,
"bb": 2,
"1": "x"
} });
});

View File

@ -0,0 +1,21 @@
import * as c from "../data/c.json";
import * as d from "../data/d.json";
import { bb, aa } from "../data/e.json";
import f, { named } from "../data/f.json";
import g, { named as gnamed } from "../data/g.json";
it("should be possible to import json data", function() {
c[2].should.be.eql(3);
Object.keys(d).should.be.eql(["default"]);
aa.should.be.eql(1);
bb.should.be.eql(2);
named.should.be.eql("named");
({ f }).should.be.eql({
f: {
__esModule: true,
default: "default",
named: "named"
}
});
g.named.should.be.equal(gnamed);
});

View File

@ -0,0 +1,23 @@
import a from "../data/a.json";
import b from "../data/b.json";
import c from "../data/c.json";
import d from "../data/d.json";
import e from "../data/e.json";
import f from "../data/f.json";
it("should be possible to import json data", function() {
({a}).should.be.eql({a: null});
b.should.be.eql(123);
c.should.be.eql([1, 2, 3, 4]);
d.should.be.eql({});
e.should.be.eql({
aa: 1,
bb: 2,
"1": "x"
});
f.should.be.eql({
named: "named",
"default": "default",
__esModule: true
});
});

View File

@ -1,3 +1,3 @@
it("should be able to use loadModule multiple times within a loader, on files in different directories", function() {
require('!./loader/index.js!./a.json').should.have.properties(['a', 'b', 'c']);
require('!./loader/index.js!./a.data').should.have.properties(['a', 'b', 'c']);
});

View File

@ -11,15 +11,3 @@ it("should also work when the json extension is omitted", function() {
someJson.should.have.property("it", "works");
someJson.should.have.property("number", 42);
});
it("should still be possible to manually apply the json-loader for compatibility reasons", function() {
var someJson = require("json-loader!./some.json");
someJson.should.have.property("it", "works");
someJson.should.have.property("number", 42);
});
it("should still be possible to use a custom loader", function() {
var someJson = JSON.parse(require("raw-loader!./some.json"));
someJson.should.have.property("it", "works");
someJson.should.have.property("number", 42);
});

View File

@ -34,10 +34,10 @@ it("should be able to use renaming combined with a context", function() {
});
it("should compile an empty context", function() {
var x = "";
var x = "xxx";
(function() {
require("./templates/notExisting" + x);
}).toString().should.not.match(/require/);
}).should.throw(/xxx/);
});
it("should execute an empty context", function() {

View File

@ -1,33 +1,43 @@
it("should require existing module with supplied error callback", function(done) {
require(['./file'], function(file){
file.should.be.eql("file");
done();
}, function(error) {});
try {
file.should.be.eql("file");
done();
} catch(e) { done(e); }
}, function(error) { done(error); });
});
it("should call error callback on missing module", function(done) {
require(['./file', './missingModule'], function(file){}, function(error) {
error.should.be.instanceOf(Error);
error.message.should.be.eql('Cannot find module "./missingModule"');
done();
try {
error.should.be.instanceOf(Error);
error.message.should.be.eql('Cannot find module "./missingModule"');
done();
} catch(e) {
done(e);
}
});
});
it("should call error callback on missing module in context", function(done) {
(function(module) {
require(['./' + module], function(file){}, function(error) {
error.should.be.instanceOf(Error);
error.message.should.be.eql("Cannot find module './missingModule'.");
done();
try {
error.should.be.instanceOf(Error);
error.message.should.be.eql("Cannot find module \"./missingModule\".");
done();
} catch(e) { done(e); }
});
})('missingModule');
});
it("should call error callback on exception thrown in loading module", function(done) {
require(['./throwing'], function(){}, function(error) {
error.should.be.instanceOf(Error);
error.message.should.be.eql('message');
done();
try {
error.should.be.instanceOf(Error);
error.message.should.be.eql('message');
done();
} catch(e) { done(e); }
});
});
@ -35,8 +45,10 @@ it("should not call error callback on exception thrown in require callback", fun
require(['./throwing'], function() {
throw new Error('message');
}, function(error) {
error.should.be.instanceOf(Error);
error.message.should.be.eql('message');
done();
try {
error.should.be.instanceOf(Error);
error.message.should.be.eql('message');
done();
} catch(e) { done(e); }
});
});

View File

@ -1,8 +1,10 @@
it("should require existing module with supplied error callback", function(done) {
require.ensure(['./file'], function(){
var file = require('./file');
file.should.be.eql("file");
done();
try {
var file = require('./file');
file.should.be.eql("file");
done();
} catch(e) { done(e); }
}, function(error) {});
});
@ -22,7 +24,7 @@ it("should call error callback on missing module in context", function(done) {
require('./' + module);
}, function(error) {
error.should.be.instanceOf(Error);
error.message.should.be.eql("Cannot find module './missingModule'.");
error.message.should.be.eql("Cannot find module \"./missingModule\".");
done();
});
})('missingModule');
@ -40,7 +42,6 @@ it("should call error callback on exception thrown in loading module", function(
it("should not call error callback on exception thrown in require callback", function(done) {
require.ensure(['./throwing'], function() {
require('./throwing');
throw new Error('message');
}, function(error) {
error.should.be.instanceOf(Error);
@ -51,9 +52,11 @@ it("should not call error callback on exception thrown in require callback", fun
it("should call error callback when there is an error loading the chunk", function(done) {
var temp = __webpack_require__.e;
__webpack_require__.e = function() { return Promise.reject('fake chunk load error'); };
__webpack_require__.e = function() { return Promise.resolve().then(function() { throw 'fake chunk load error'; }); };
require.ensure(['./file'], function(){
var file = require('./file');
try {
var file = require('./file');
} catch(e) { done(e); }
}, function(error) {
error.should.be.eql('fake chunk load error');
done();

View File

@ -10,11 +10,11 @@ it("should not exclude paths not matching the exclusion pattern", function() {
it("should exclude paths/files matching the exclusion pattern", function() {
(() => requireInContext("dont")).
should.throw(/Cannot find module '.\/dont'/);
should.throw(/Cannot find module ".\/dont"/);
(() => requireInContext("dont-check-here/file")).
should.throw(/Cannot find module '.\/dont-check-here\/file'/);
should.throw(/Cannot find module ".\/dont-check-here\/file"/);
(() => requireInContext("check-here/dont-check-here/file")).
should.throw(/Cannot find module '.\/check-here\/dont-check-here\/file'/);
should.throw(/Cannot find module ".\/check-here\/dont-check-here\/file"/);
});

View File

@ -8,7 +8,7 @@ module.exports = {
"./module": {
id: 1,
buildMeta: {
harmonyModule: true,
exportsType: "namespace",
providedExports: ["default"]
},
}

View File

@ -3,11 +3,6 @@ module.exports = {
performance: {
hints: false
},
module: {
rules: [
{ test: /\.json$/, loader: "json-loader" }
]
},
node: {
__dirname: false,
__filename: false

View File

@ -8,7 +8,7 @@ d3cbd72ce65d74600a43.js 1.94 KiB 1 [emitted]
be4832811033692f578c.js 1.94 KiB 4 [emitted]
ac227ea2bbc85cb2741c.js 1 KiB 5 [emitted]
97965c2451ecb81665d7.js 1.01 KiB 6 [emitted]
9436edacbc90d1f598aa.js 8.28 KiB 7 [emitted] main
9436edacbc90d1f598aa.js 8.36 KiB 7 [emitted] main
Entrypoint main = 9436edacbc90d1f598aa.js
chunk {0} 678a72d82e420b28b031.js 1.76 KiB {7} [recorded]
> aggressive-splitted duplicate [11] ./index.js 4:0-51

View File

@ -1,10 +1,10 @@
Hash: 8f74408892465f3dc6d5
Time: Xms
Asset Size Chunks Chunk Names
0.bundle.js 528 bytes 0 [emitted]
0.bundle.js 530 bytes 0 [emitted]
1.bundle.js 394 bytes 1 [emitted]
2.bundle.js 782 bytes 2 [emitted]
bundle.js 7.54 KiB main [emitted] main
bundle.js 7.55 KiB main [emitted] main
chunk {main} bundle.js (main) 73 bytes [entry] [rendered]
> main [./index.js] ./index.js
[./a.js] 22 bytes {main} [built]

View File

@ -2,9 +2,9 @@ Hash: ee41f06ebdd1a9a95e6a
Time: Xms
Asset Size Chunks Chunk Names
0.bundle.js 152 bytes 0 [emitted]
1.bundle.js 288 bytes 1 [emitted]
1.bundle.js 289 bytes 1 [emitted]
2.bundle.js 227 bytes 2 [emitted]
bundle.js 6.96 KiB 3 [emitted] main
bundle.js 6.97 KiB 3 [emitted] main
chunk {0} 0.bundle.js 22 bytes {3} [rendered]
> [4] ./index.js 2:0-16
[2] ./b.js 22 bytes {0} [built]

View File

@ -4,9 +4,9 @@ Child normal:
1.bundle.js 815 bytes 1 [emitted] x2
2.bundle.js 1.07 KiB 2 [emitted] x3
3.bundle.js 1.33 KiB 3 [emitted] x4
4.bundle.js 858 bytes 4 [emitted] x5
4.bundle.js 865 bytes 4 [emitted] x5
5.bundle.js 1.04 KiB 5 [emitted] xx5
bundle.js 7.03 KiB 6 [emitted] main
bundle.js 7.06 KiB 6 [emitted] main
chunk {0} 0.bundle.js (x1) 14 bytes {6} [rendered]
> x1 [11] ./index.js 1:0-42
[0] ./a.js 0 bytes {0} {1} {2} {3} {4} [built]
@ -49,9 +49,9 @@ Child children:
1.bundle.js 661 bytes 1 [emitted] x2
2.bundle.js 939 bytes 2 [emitted] x3
3.bundle.js 1.19 KiB 3 [emitted] x4
4.bundle.js 742 bytes 4 [emitted] x5
4.bundle.js 749 bytes 4 [emitted] x5
5.bundle.js 1.04 KiB 5 [emitted] xx5
bundle.js 7.14 KiB 6 [emitted] main
bundle.js 7.17 KiB 6 [emitted] main
chunk {0} 0.bundle.js (x1) 14 bytes {6} [rendered]
> x1 [11] ./index.js 1:0-42
[6] ./x1.js 14 bytes {0} [built]
@ -88,9 +88,9 @@ Child async:
2.bundle.js 661 bytes 2 [emitted] x2
3.bundle.js 939 bytes 3 [emitted] x3
4.bundle.js 1.19 KiB 4 [emitted] x4
5.bundle.js 742 bytes 5 [emitted] x5
5.bundle.js 749 bytes 5 [emitted] x5
6.bundle.js 1.04 KiB 6 [emitted] xx5
bundle.js 7.23 KiB 7 [emitted] main
bundle.js 7.25 KiB 7 [emitted] main
chunk {0} 0.bundle.js 0 bytes {7} [rendered]
> async commons x1 [11] ./index.js 1:0-42
> async commons x2 [11] ./index.js 2:0-42
@ -132,9 +132,9 @@ Child deep-children:
1.bundle.js 661 bytes 1 [emitted] x2
2.bundle.js 881 bytes 2 [emitted] x3
3.bundle.js 1.13 KiB 3 [emitted] x4
4.bundle.js 742 bytes 4 [emitted] x5
4.bundle.js 749 bytes 4 [emitted] x5
5.bundle.js 1020 bytes 5 [emitted] xx5
bundle.js 7.26 KiB 6 [emitted] main
bundle.js 7.29 KiB 6 [emitted] main
chunk {0} 0.bundle.js (x1) 14 bytes {6} [rendered]
> x1 [11] ./index.js 1:0-42
[6] ./x1.js 14 bytes {0} [built]
@ -169,9 +169,9 @@ Child deep-async:
2.bundle.js 661 bytes 2 [emitted] x2
3.bundle.js 881 bytes 3 [emitted] x3
4.bundle.js 1.13 KiB 4 [emitted] x4
5.bundle.js 783 bytes 5 [emitted] x5
5.bundle.js 789 bytes 5 [emitted] x5
6.bundle.js 1020 bytes 6 [emitted] xx5
bundle.js 7.23 KiB 7 [emitted] main
bundle.js 7.25 KiB 7 [emitted] main
chunk {0} 0.bundle.js 0 bytes {7} [rendered]
> async commons x1 [11] ./index.js 1:0-42
> async commons x2 [11] ./index.js 2:0-42

View File

@ -1,10 +1,10 @@
Hash: a6418d72fd6bad27d7e001bd4246a474bfd828f8
Hash: 33e68a38df1cd17df82bf09d6254865163caaf3a
Child
Hash: a6418d72fd6bad27d7e0
Hash: 33e68a38df1cd17df82b
Time: Xms
Asset Size Chunks Chunk Names
app.js 656 bytes 0 [emitted] app
vendor.054b9142e1966b5880c5.js 619 bytes 1 [emitted] vendor
vendor.9de225d5f0ac36b2596b.js 619 bytes 1 [emitted] vendor
runtime.js 7.03 KiB 2 [emitted] runtime
[./constants.js] 87 bytes {1} [built]
[./entry-1.js] ./entry-1.js + 2 modules 190 bytes {0} [built]
@ -12,11 +12,11 @@ Child
| ./submodule-a.js 59 bytes [built]
| ./submodule-b.js 59 bytes [built]
Child
Hash: 01bd4246a474bfd828f8
Hash: f09d6254865163caaf3a
Time: Xms
Asset Size Chunks Chunk Names
app.js 673 bytes 0 [emitted] app
vendor.054b9142e1966b5880c5.js 619 bytes 1 [emitted] vendor
vendor.9de225d5f0ac36b2596b.js 619 bytes 1 [emitted] vendor
runtime.js 7.03 KiB 2 [emitted] runtime
[./constants.js] 87 bytes {1} [built]
[./entry-2.js] ./entry-2.js + 2 modules 197 bytes {0} [built]

View File

@ -1,7 +1,7 @@
Hash: 0c78424b0f03182d4365
Hash: 23b0e2e89d599733386c
Time: Xms
Asset Size Chunks Chunk Names
bundle.js 3.03 KiB 0 [emitted] main
bundle.js 3.04 KiB 0 [emitted] main
+ 1 hidden asset
[0] ./index.js 77 bytes {0} [built]
[1] ./a.txt 43 bytes {0} [built]

View File

@ -19,7 +19,8 @@ module.exports = {
loader: "raw-loader"
}, {
test: /\.json/,
loader: "file-loader"
loader: "file-loader",
type: "javascript/auto"
}]
}
};

View File

@ -1,10 +1,10 @@
Hash: d93ce02dc3d831c9f9d8
Hash: f44ab9a84588885bef81
Time: Xms
Asset Size Chunks Chunk Names
0.js 305 bytes 0 [emitted]
1.js 314 bytes 1 [emitted]
2.js 308 bytes 2 [emitted]
entry.js 7.7 KiB 3 [emitted] entry
entry.js 7.75 KiB 3 [emitted] entry
[0] ./templates/bar.js 38 bytes {0} [optional] [built]
[1] ./templates/baz.js 38 bytes {1} [optional] [built]
[2] ./templates/foo.js 38 bytes {2} [optional] [built]

View File

@ -2,7 +2,7 @@ Hash: 76f3311214153561286d
Time: Xms
Asset Size Chunks Chunk Names
0.js 149 bytes 0 [emitted]
entry.js 7.21 KiB 1 [emitted] entry
entry.js 7.58 KiB 1 [emitted] entry
[0] ./modules/b.js 22 bytes {0} [built]
[1] ./entry.js 120 bytes {1} [built]
[2] ./modules/a.js 37 bytes [built]

View File

@ -3,7 +3,7 @@ Child
Hash: 0bcb77c121105f5554b0
Time: Xms
Asset Size Chunks Chunk Names
bundle.js 3.79 KiB 0 [emitted] main
bundle.js 3.91 KiB 0 [emitted] main
chunk {0} bundle.js (main) 191 bytes [entry] [rendered]
[0] ./index.js 73 bytes {0} [built]
[1] ./a.js 22 bytes {0} [built]
@ -15,7 +15,7 @@ Child
Hash: f4bf5583ae34c4fb7657
Time: Xms
Asset Size Chunks Chunk Names
0.bundle.js 932 bytes 0 [emitted]
0.bundle.js 928 bytes 0 [emitted]
bundle.js 7.12 KiB 1 [emitted] main
chunk {0} 0.bundle.js 118 bytes {1} [rendered]
[0] ./d.js 22 bytes {0} [built]
@ -29,7 +29,7 @@ Child
Hash: 31d10387e7bad2352849
Time: Xms
Asset Size Chunks Chunk Names
0.bundle.js 794 bytes 0 [emitted]
0.bundle.js 790 bytes 0 [emitted]
1.bundle.js 245 bytes 1 [emitted]
bundle.js 7.12 KiB 2 [emitted] main
chunk {0} 0.bundle.js 74 bytes {2} [rendered]
@ -47,7 +47,7 @@ Child
Asset Size Chunks Chunk Names
0.bundle.js 236 bytes 0 [emitted]
1.bundle.js 245 bytes 1 [emitted]
2.bundle.js 623 bytes 2 [emitted]
2.bundle.js 619 bytes 2 [emitted]
bundle.js 7.11 KiB 3 [emitted] main
chunk {0} 0.bundle.js 44 bytes {2} {3} [rendered]
[0] ./d.js 22 bytes {0} [built]

View File

@ -1,10 +1,10 @@
Asset Size Chunks Chunk Names
0.js 808 bytes 0 [emitted] async3
1.js 808 bytes 1 [emitted] async1
2.js 808 bytes 2 [emitted] async2
e1.js 7.93 KiB 3 [emitted] e1
e2.js 7.95 KiB 4 [emitted] e2
e3.js 7.97 KiB 5 [emitted] e3
0.js 818 bytes 0 [emitted] async3
1.js 818 bytes 1 [emitted] async1
2.js 818 bytes 2 [emitted] async2
e1.js 7.94 KiB 3 [emitted] e1
e2.js 7.96 KiB 4 [emitted] e2
e3.js 7.98 KiB 5 [emitted] e3
chunk {0} 0.js (async3) 89 bytes {2} {5} [rendered]
[4] ./h.js 9 bytes {0} {5} [built]
[7] ./async3.js 80 bytes {0} [built]

View File

@ -1,7 +1,7 @@
Hash: 9ba7ce8e004fc375bd9e
Time: Xms
Asset Size Chunks Chunk Names
chunk-containing-__a_js.js 467 bytes chunk-containing-__a_js [emitted]
chunk-containing-__a_js.js 465 bytes chunk-containing-__a_js [emitted]
chunk-containing-__b_js.js 173 bytes chunk-containing-__b_js [emitted]
entry.js 7.13 KiB entry [emitted] entry
[0] ./modules/b.js 22 bytes {chunk-containing-__b_js} [built]

View File

@ -1,14 +1,14 @@
Hash: 9e791589c2c0542190c6
Time: Xms
Asset Size Chunks Chunk Names
0.js 281 bytes 0 [emitted] cir1
0.js 299 bytes 0 [emitted] cir1
1.js 183 bytes 1 [emitted] ab
2.js 277 bytes 2, 1 [emitted] abd
3.js 296 bytes 3 [emitted] cir2
3.js 311 bytes 3 [emitted] cir2
4.js 190 bytes 4, 6 [emitted] chunk
5.js 356 bytes 5, 3 [emitted] cir2 from cir1
5.js 371 bytes 5, 3 [emitted] cir2 from cir1
6.js 130 bytes 6 [emitted] ac in ab
main.js 7.62 KiB 7 [emitted] main
main.js 7.68 KiB 7 [emitted] main
chunk {0} 0.js (cir1) 81 bytes {3} {7} [rendered]
> duplicate cir1 from cir2 [3] ./circular2.js 1:0-79
> duplicate cir1 [8] ./index.js 13:0-54

View File

@ -1,7 +1,7 @@
Time: <CLR=BOLD>X</CLR>ms
<CLR=BOLD>Asset</CLR> <CLR=BOLD>Size</CLR> <CLR=BOLD>Chunks</CLR> <CLR=39,BOLD><CLR=22> <CLR=39,BOLD><CLR=22><CLR=BOLD>Chunk Names</CLR>
<CLR=32,BOLD>0.js</CLR> 152 bytes <CLR=BOLD>0</CLR> <CLR=32,BOLD>[emitted]</CLR>
<CLR=32,BOLD>1.js</CLR> 288 bytes <CLR=BOLD>1</CLR> <CLR=32,BOLD>[emitted]</CLR>
<CLR=32,BOLD>1.js</CLR> 289 bytes <CLR=BOLD>1</CLR> <CLR=32,BOLD>[emitted]</CLR>
<CLR=32,BOLD>2.js</CLR> 227 bytes <CLR=BOLD>2</CLR> <CLR=32,BOLD>[emitted]</CLR>
<CLR=32,BOLD>main.js</CLR> 300 KiB <CLR=BOLD>3</CLR> <CLR=32,BOLD>[emitted]</CLR> main
Entrypoint <CLR=BOLD>main</CLR> = <CLR=32,BOLD>main.js</CLR>

View File

@ -1,7 +1,7 @@
Time: <CLR=BOLD>X</CLR>ms
<CLR=BOLD>Asset</CLR> <CLR=BOLD>Size</CLR> <CLR=BOLD>Chunks</CLR> <CLR=39,BOLD><CLR=22> <CLR=39,BOLD><CLR=22> <CLR=BOLD>Chunk Names</CLR>
<CLR=32,BOLD>0.js</CLR> 152 bytes <CLR=BOLD>0</CLR> <CLR=32,BOLD>[emitted]</CLR>
<CLR=32,BOLD>1.js</CLR> 288 bytes <CLR=BOLD>1</CLR> <CLR=32,BOLD>[emitted]</CLR>
<CLR=32,BOLD>1.js</CLR> 289 bytes <CLR=BOLD>1</CLR> <CLR=32,BOLD>[emitted]</CLR>
<CLR=32,BOLD>2.js</CLR> 227 bytes <CLR=BOLD>2</CLR> <CLR=32,BOLD>[emitted]</CLR>
<CLR=33,BOLD>main.js</CLR> <CLR=33,BOLD>300 KiB</CLR> <CLR=BOLD>3</CLR> <CLR=32,BOLD>[emitted]</CLR> <CLR=33,BOLD>[big]</CLR> main
Entrypoint <CLR=BOLD>main</CLR> <CLR=33,BOLD>[big]</CLR> = <CLR=32,BOLD>main.js</CLR>

View File

@ -1,7 +1,7 @@
Time: <CLR=BOLD>X</CLR>ms
<CLR=BOLD>Asset</CLR> <CLR=BOLD>Size</CLR> <CLR=BOLD>Chunks</CLR> <CLR=39,BOLD><CLR=22> <CLR=39,BOLD><CLR=22> <CLR=BOLD>Chunk Names</CLR>
<CLR=32,BOLD>0.js</CLR> 152 bytes <CLR=BOLD>0</CLR> <CLR=32,BOLD>[emitted]</CLR>
<CLR=32,BOLD>1.js</CLR> 288 bytes <CLR=BOLD>1</CLR> <CLR=32,BOLD>[emitted]</CLR>
<CLR=32,BOLD>1.js</CLR> 289 bytes <CLR=BOLD>1</CLR> <CLR=32,BOLD>[emitted]</CLR>
<CLR=32,BOLD>2.js</CLR> 227 bytes <CLR=BOLD>2</CLR> <CLR=32,BOLD>[emitted]</CLR>
<CLR=33,BOLD>main.js</CLR> <CLR=33,BOLD>300 KiB</CLR> <CLR=BOLD>3</CLR> <CLR=32,BOLD>[emitted]</CLR> <CLR=33,BOLD>[big]</CLR> main
Entrypoint <CLR=BOLD>main</CLR> <CLR=33,BOLD>[big]</CLR> = <CLR=32,BOLD>main.js</CLR>

View File

@ -2,9 +2,9 @@ Hash: 775d1eb92a5362121009
Time: Xms
Asset Size Chunks Chunk Names
0.js 152 bytes 0 [emitted]
1.js 288 bytes 1 [emitted]
1.js 289 bytes 1 [emitted]
2.js 227 bytes 2 [emitted]
main.js 6.95 KiB 3 [emitted] main
main.js 6.96 KiB 3 [emitted] main
Entrypoint main = main.js
chunk {0} 0.js 22 bytes {3} [rendered]
> [4] ./index.js 2:0-16

View File

@ -1,7 +1,7 @@
Time: <CLR=BOLD>X</CLR>ms
<CLR=BOLD>Asset</CLR> <CLR=BOLD>Size</CLR> <CLR=BOLD>Chunks</CLR> <CLR=39,BOLD><CLR=22> <CLR=39,BOLD><CLR=22> <CLR=BOLD>Chunk Names</CLR>
<CLR=32,BOLD>0.js</CLR> 182 bytes <CLR=BOLD>0</CLR> <CLR=32,BOLD>[emitted]</CLR>
<CLR=32,BOLD>1.js</CLR> 318 bytes <CLR=BOLD>1</CLR> <CLR=32,BOLD>[emitted]</CLR>
<CLR=32,BOLD>1.js</CLR> 319 bytes <CLR=BOLD>1</CLR> <CLR=32,BOLD>[emitted]</CLR>
<CLR=32,BOLD>2.js</CLR> 257 bytes <CLR=BOLD>2</CLR> <CLR=32,BOLD>[emitted]</CLR>
<CLR=33,BOLD>main.js</CLR> <CLR=33,BOLD>300 KiB</CLR> <CLR=BOLD>3</CLR> <CLR=32,BOLD>[emitted]</CLR> <CLR=33,BOLD>[big]</CLR> main
<CLR=32,BOLD>0.js.map</CLR> 250 bytes <CLR=BOLD>0</CLR> <CLR=32,BOLD>[emitted]</CLR>

View File

@ -1,7 +1,7 @@
Time: <CLR=BOLD>X</CLR>ms
<CLR=BOLD>Asset</CLR> <CLR=BOLD>Size</CLR> <CLR=BOLD>Chunks</CLR> <CLR=39,BOLD><CLR=22> <CLR=39,BOLD><CLR=22> <CLR=BOLD>Chunk Names</CLR>
<CLR=32,BOLD>0.js</CLR> 152 bytes <CLR=BOLD>0</CLR> <CLR=32,BOLD>[emitted]</CLR>
<CLR=32,BOLD>1.js</CLR> 288 bytes <CLR=BOLD>1</CLR> <CLR=32,BOLD>[emitted]</CLR>
<CLR=32,BOLD>1.js</CLR> 289 bytes <CLR=BOLD>1</CLR> <CLR=32,BOLD>[emitted]</CLR>
<CLR=32,BOLD>2.js</CLR> 227 bytes <CLR=BOLD>2</CLR> <CLR=32,BOLD>[emitted]</CLR>
<CLR=33,BOLD>main.js</CLR> <CLR=33,BOLD>300 KiB</CLR> <CLR=BOLD>3</CLR> <CLR=32,BOLD>[emitted]</CLR> <CLR=33,BOLD>[big]</CLR> main
[0] <CLR=BOLD>./d.js</CLR> 22 bytes {<CLR=33,BOLD>2</CLR>}<CLR=32,BOLD> [built]</CLR>

View File

@ -2,9 +2,9 @@ Hash: 775d1eb92a5362121009
Time: Xms
Asset Size Chunks Chunk Names
0.js 152 bytes 0 [emitted]
1.js 288 bytes 1 [emitted]
1.js 289 bytes 1 [emitted]
2.js 227 bytes 2 [emitted]
main.js 6.95 KiB 3 [emitted] main
main.js 6.96 KiB 3 [emitted] main
[0] ./d.js 22 bytes {2} [built]
[1] ./e.js 22 bytes {2} [built]
[2] ./b.js 22 bytes {0} [built]

View File

@ -2,9 +2,9 @@ Hash: 775d1eb92a5362121009
Time: Xms
Asset Size Chunks Chunk Names
0.js 152 bytes 0 [emitted]
1.js 288 bytes 1 [emitted]
1.js 289 bytes 1 [emitted]
2.js 227 bytes 2 [emitted]
main.js 6.95 KiB 3 [emitted] main
main.js 6.96 KiB 3 [emitted] main
Entrypoint main = main.js
chunk {0} 0.js 22 bytes {3} [rendered]
> [4] ./index.js 2:0-16

View File

@ -1,4 +1,4 @@
Hash: 841dd2f7e2da346f7bf1
Hash: e205648cbd984b752d24
Time: Xms
[0] ./entry.js 32 bytes {0} {1} [built]
ModuleConcatenation bailout: Module is an entry point

View File

@ -1,6 +1,6 @@
Hash: 49ce8879437678b6eb8d95fdba0ecbcbce122b34
Hash: 8dd3a18cdbd62ff5464bcdfae2364f6eee940fc9
Child
Hash: 49ce8879437678b6eb8d
Hash: 8dd3a18cdbd62ff5464b
Time: Xms
[0] ./common_lazy_shared.js 25 bytes {0} {1} {2} [built]
[1] ./common2.js 25 bytes {3} {4} [built]
@ -14,7 +14,7 @@ Child
[9] ./module_first.js 31 bytes {3} [built]
[10] ./second.js 177 bytes {4} [built]
Child
Hash: 95fdba0ecbcbce122b34
Hash: cdfae2364f6eee940fc9
Time: Xms
[0] ./common_lazy_shared.js 25 bytes {0} {1} {2} [built]
[1] ./common_lazy.js 25 bytes {1} {2} [built]

View File

@ -1,4 +1,4 @@
Hash: 794590bda66f1b25a4aa
Hash: 3d9c056775babba7f1f7
Time: Xms
Asset Size Chunks Chunk Names
bundle.js 7.26 KiB 0 [emitted] main

View File

@ -8,7 +8,7 @@ module.exports = {
"./module": {
id: 1,
buildMeta: {
harmonyModule: true,
exportsType: "namespace",
providedExports: ["default"]
},
}