mirror of https://github.com/webpack/webpack.git
add lazy compilation for entrypoints
This commit is contained in:
parent
988cf8d47a
commit
100317556e
|
@ -1042,7 +1042,7 @@ export interface Experiments {
|
||||||
*/
|
*/
|
||||||
layers?: boolean;
|
layers?: boolean;
|
||||||
/**
|
/**
|
||||||
* Compile import()s only when they are accessed.
|
* Compile entrypoints and import()s only when they are accessed.
|
||||||
*/
|
*/
|
||||||
lazyCompilation?:
|
lazyCompilation?:
|
||||||
| boolean
|
| boolean
|
||||||
|
@ -1064,6 +1064,10 @@ export interface Experiments {
|
||||||
* A custom client.
|
* A custom client.
|
||||||
*/
|
*/
|
||||||
client?: string;
|
client?: string;
|
||||||
|
/**
|
||||||
|
* Enable/disable lazy compilation for entries.
|
||||||
|
*/
|
||||||
|
entries?: boolean;
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* Allow output javascript files as module source type.
|
* Allow output javascript files as module source type.
|
||||||
|
|
|
@ -10,7 +10,9 @@ module.exports = {
|
||||||
idleTimeout: 5000
|
idleTimeout: 5000
|
||||||
},
|
},
|
||||||
experiments: {
|
experiments: {
|
||||||
lazyCompilation: true
|
lazyCompilation: {
|
||||||
|
entries: false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
devServer: {
|
devServer: {
|
||||||
hot: true,
|
hot: true,
|
||||||
|
|
|
@ -2,16 +2,12 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
if (!module.hot) {
|
|
||||||
throw new Error(
|
|
||||||
"Environment doesn't support lazy compilation (requires Hot Module Replacement enabled)"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
var urlBase = decodeURIComponent(__resourceQuery.slice(1));
|
var urlBase = decodeURIComponent(__resourceQuery.slice(1));
|
||||||
exports.keepAlive = function (options) {
|
exports.keepAlive = function (options) {
|
||||||
var data = options.data;
|
var data = options.data;
|
||||||
var onError = options.onError;
|
var onError = options.onError;
|
||||||
|
var active = options.active;
|
||||||
|
var module = options.module;
|
||||||
var response;
|
var response;
|
||||||
var request = require("http").request(
|
var request = require("http").request(
|
||||||
urlBase + data,
|
urlBase + data,
|
||||||
|
@ -22,6 +18,11 @@ exports.keepAlive = function (options) {
|
||||||
function (res) {
|
function (res) {
|
||||||
response = res;
|
response = res;
|
||||||
response.on("error", errorHandler);
|
response.on("error", errorHandler);
|
||||||
|
if (!active && !module.hot) {
|
||||||
|
console.log(
|
||||||
|
"Hot Module Replacement is not enabled. Waiting for process restart..."
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
function errorHandler(err) {
|
function errorHandler(err) {
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
if (typeof EventSource !== "function" || !module.hot) {
|
if (typeof EventSource !== "function") {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Environment doesn't support lazy compilation (requires EventSource and Hot Module Replacement enabled)"
|
"Environment doesn't support lazy compilation (requires EventSource)"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,12 +45,19 @@ var updateEventSource = function updateEventSource() {
|
||||||
exports.keepAlive = function (options) {
|
exports.keepAlive = function (options) {
|
||||||
var data = options.data;
|
var data = options.data;
|
||||||
var onError = options.onError;
|
var onError = options.onError;
|
||||||
|
var active = options.active;
|
||||||
|
var module = options.module;
|
||||||
errorHandlers.add(onError);
|
errorHandlers.add(onError);
|
||||||
var value = activeKeys.get(data) || 0;
|
var value = activeKeys.get(data) || 0;
|
||||||
activeKeys.set(data, value + 1);
|
activeKeys.set(data, value + 1);
|
||||||
if (value === 0) {
|
if (value === 0) {
|
||||||
updateEventSource();
|
updateEventSource();
|
||||||
}
|
}
|
||||||
|
if (!active && !module.hot) {
|
||||||
|
console.log(
|
||||||
|
"Hot Module Replacement is not enabled. Waiting for process restart..."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return function () {
|
return function () {
|
||||||
errorHandlers.delete(onError);
|
errorHandlers.delete(onError);
|
||||||
|
|
|
@ -256,7 +256,10 @@ class WebpackOptionsApply extends OptionsApply {
|
||||||
options.experiments.lazyCompilation.client) ||
|
options.experiments.lazyCompilation.client) ||
|
||||||
`webpack/hot/lazy-compilation-${
|
`webpack/hot/lazy-compilation-${
|
||||||
options.externalsPresets.node ? "node" : "web"
|
options.externalsPresets.node ? "node" : "web"
|
||||||
}.js`
|
}.js`,
|
||||||
|
entries:
|
||||||
|
typeof options.experiments.lazyCompilation !== "object" ||
|
||||||
|
options.experiments.lazyCompilation.entries !== false
|
||||||
}).apply(compiler);
|
}).apply(compiler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,12 +59,8 @@ class LazyCompilationDependency extends Dependency {
|
||||||
registerNotSerializable(LazyCompilationDependency);
|
registerNotSerializable(LazyCompilationDependency);
|
||||||
|
|
||||||
class LazyCompilationProxyModule extends Module {
|
class LazyCompilationProxyModule extends Module {
|
||||||
constructor(originalModule, request, client, data, active) {
|
constructor(context, originalModule, request, client, data, active) {
|
||||||
super(
|
super("lazy-compilation-proxy", context, originalModule.layer);
|
||||||
"lazy-compilation-proxy",
|
|
||||||
originalModule.context,
|
|
||||||
originalModule.layer
|
|
||||||
);
|
|
||||||
this.originalModule = originalModule;
|
this.originalModule = originalModule;
|
||||||
this.request = request;
|
this.request = request;
|
||||||
this.client = client;
|
this.client = client;
|
||||||
|
@ -172,14 +168,16 @@ class LazyCompilationProxyModule extends Module {
|
||||||
.dependencies[0]);
|
.dependencies[0]);
|
||||||
const clientModule = moduleGraph.getModule(clientDep);
|
const clientModule = moduleGraph.getModule(clientDep);
|
||||||
const block = this.blocks[0];
|
const block = this.blocks[0];
|
||||||
const keepActive = Template.asString([
|
const client = Template.asString([
|
||||||
`var client = ${runtimeTemplate.moduleExports({
|
`var client = ${runtimeTemplate.moduleExports({
|
||||||
module: clientModule,
|
module: clientModule,
|
||||||
chunkGraph,
|
chunkGraph,
|
||||||
request: clientDep.userRequest,
|
request: clientDep.userRequest,
|
||||||
runtimeRequirements
|
runtimeRequirements
|
||||||
})}`,
|
})}`,
|
||||||
`var data = ${JSON.stringify(this.data)};`,
|
`var data = ${JSON.stringify(this.data)};`
|
||||||
|
]);
|
||||||
|
const keepActive = Template.asString([
|
||||||
`var dispose = client.keepAlive({ data, active: ${JSON.stringify(
|
`var dispose = client.keepAlive({ data, active: ${JSON.stringify(
|
||||||
!!block
|
!!block
|
||||||
)}, module, onError });`
|
)}, module, onError });`
|
||||||
|
@ -189,11 +187,7 @@ class LazyCompilationProxyModule extends Module {
|
||||||
const dep = block.dependencies[0];
|
const dep = block.dependencies[0];
|
||||||
const module = moduleGraph.getModule(dep);
|
const module = moduleGraph.getModule(dep);
|
||||||
source = Template.asString([
|
source = Template.asString([
|
||||||
"module.hot.accept();",
|
client,
|
||||||
`module.hot.accept(${JSON.stringify(
|
|
||||||
chunkGraph.getModuleId(module)
|
|
||||||
)}, function() { module.hot.invalidate(); });`,
|
|
||||||
"module.hot.dispose(function(data) { delete data.resolveSelf; dispose(data); });",
|
|
||||||
`module.exports = ${runtimeTemplate.moduleNamespacePromise({
|
`module.exports = ${runtimeTemplate.moduleNamespacePromise({
|
||||||
chunkGraph,
|
chunkGraph,
|
||||||
block,
|
block,
|
||||||
|
@ -203,17 +197,31 @@ class LazyCompilationProxyModule extends Module {
|
||||||
message: "import()",
|
message: "import()",
|
||||||
runtimeRequirements
|
runtimeRequirements
|
||||||
})};`,
|
})};`,
|
||||||
"if (module.hot.data && module.hot.data.resolveSelf) module.hot.data.resolveSelf(module.exports);",
|
"if (module.hot) {",
|
||||||
|
Template.indent([
|
||||||
|
"module.hot.accept();",
|
||||||
|
`module.hot.accept(${JSON.stringify(
|
||||||
|
chunkGraph.getModuleId(module)
|
||||||
|
)}, function() { module.hot.invalidate(); });`,
|
||||||
|
"module.hot.dispose(function(data) { delete data.resolveSelf; dispose(data); });",
|
||||||
|
"if (module.hot.data && module.hot.data.resolveSelf) module.hot.data.resolveSelf(module.exports);"
|
||||||
|
]),
|
||||||
|
"}",
|
||||||
"function onError() { /* ignore */ }",
|
"function onError() { /* ignore */ }",
|
||||||
keepActive
|
keepActive
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
source = Template.asString([
|
source = Template.asString([
|
||||||
"module.hot.accept();",
|
client,
|
||||||
"var resolveSelf, onError;",
|
"var resolveSelf, onError;",
|
||||||
`module.exports = new Promise(function(resolve, reject) { resolveSelf = resolve; onError = reject; });`,
|
`module.exports = new Promise(function(resolve, reject) { resolveSelf = resolve; onError = reject; });`,
|
||||||
|
"if (module.hot) {",
|
||||||
|
Template.indent([
|
||||||
|
"module.hot.accept();",
|
||||||
"if (module.hot.data && module.hot.data.resolveSelf) module.hot.data.resolveSelf(module.exports);",
|
"if (module.hot.data && module.hot.data.resolveSelf) module.hot.data.resolveSelf(module.exports);",
|
||||||
"module.hot.dispose(function(data) { data.resolveSelf = resolveSelf; dispose(data); });",
|
"module.hot.dispose(function(data) { data.resolveSelf = resolveSelf; dispose(data); });"
|
||||||
|
]),
|
||||||
|
"}",
|
||||||
keepActive
|
keepActive
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@ -263,10 +271,12 @@ class LazyCompilationPlugin {
|
||||||
* @param {Object} options options
|
* @param {Object} options options
|
||||||
* @param {(function(Compiler, string, function(Error?, any?): void): void) | function(Compiler, string): Promise<any>} options.backend the backend
|
* @param {(function(Compiler, string, function(Error?, any?): void): void) | function(Compiler, string): Promise<any>} options.backend the backend
|
||||||
* @param {string} options.client the client reference
|
* @param {string} options.client the client reference
|
||||||
|
* @param {boolean} options.entries true, when entries are lazy compiled
|
||||||
*/
|
*/
|
||||||
constructor({ backend, client }) {
|
constructor({ backend, client, entries }) {
|
||||||
this.backend = backend;
|
this.backend = backend;
|
||||||
this.client = client;
|
this.client = client;
|
||||||
|
this.entries = entries;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Apply the plugin
|
* Apply the plugin
|
||||||
|
@ -292,20 +302,28 @@ class LazyCompilationPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
compiler.hooks.compilation.tap(
|
compiler.hooks.thisCompilation.tap(
|
||||||
"LazyCompilationPlugin",
|
"LazyCompilationPlugin",
|
||||||
(compilation, { normalModuleFactory }) => {
|
(compilation, { normalModuleFactory }) => {
|
||||||
normalModuleFactory.hooks.module.tap(
|
normalModuleFactory.hooks.module.tap(
|
||||||
"LazyCompilationPlugin",
|
"LazyCompilationPlugin",
|
||||||
(originalModule, createData, resolveData) => {
|
(originalModule, createData, resolveData) => {
|
||||||
if (
|
if (
|
||||||
resolveData.dependencies.every(dep => dep.type === "import()")
|
resolveData.dependencies.every(
|
||||||
|
dep =>
|
||||||
|
dep.type === "import()" ||
|
||||||
|
(this.entries && dep.type === "entry")
|
||||||
|
) &&
|
||||||
|
!/webpack[/\\]hot[/\\]|webpack-dev-server[/\\]client/.test(
|
||||||
|
resolveData.request
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
const moduleInfo = backend.module(originalModule);
|
const moduleInfo = backend.module(originalModule);
|
||||||
if (!moduleInfo) return;
|
if (!moduleInfo) return;
|
||||||
const { client, data, active } = moduleInfo;
|
const { client, data, active } = moduleInfo;
|
||||||
|
|
||||||
return new LazyCompilationProxyModule(
|
return new LazyCompilationProxyModule(
|
||||||
|
compiler.context,
|
||||||
originalModule,
|
originalModule,
|
||||||
resolveData.request,
|
resolveData.request,
|
||||||
client,
|
client,
|
||||||
|
|
|
@ -582,7 +582,7 @@
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"lazyCompilation": {
|
"lazyCompilation": {
|
||||||
"description": "Compile import()s only when they are accessed.",
|
"description": "Compile entrypoints and import()s only when they are accessed.",
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
@ -599,6 +599,10 @@
|
||||||
"client": {
|
"client": {
|
||||||
"description": "A custom client.",
|
"description": "A custom client.",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"entries": {
|
||||||
|
"description": "Enable/disable lazy compilation for entries.",
|
||||||
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
/** @type {import("../../../../").Configuration} */
|
/** @type {import("../../../../").Configuration} */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
experiments: {
|
experiments: {
|
||||||
lazyCompilation: true
|
lazyCompilation: {
|
||||||
|
entries: false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -2956,7 +2956,7 @@ declare interface Experiments {
|
||||||
layers?: boolean;
|
layers?: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compile import()s only when they are accessed.
|
* Compile entrypoints and import()s only when they are accessed.
|
||||||
*/
|
*/
|
||||||
lazyCompilation?:
|
lazyCompilation?:
|
||||||
| boolean
|
| boolean
|
||||||
|
@ -2975,6 +2975,10 @@ declare interface Experiments {
|
||||||
* A custom client.
|
* A custom client.
|
||||||
*/
|
*/
|
||||||
client?: string;
|
client?: string;
|
||||||
|
/**
|
||||||
|
* Enable/disable lazy compilation for entries.
|
||||||
|
*/
|
||||||
|
entries?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue