allow to disable runtime chunk per entry via `runtime: false`

and also via `ModuleFederationPlugin`.`runtime`
This commit is contained in:
Tobias Koppers 2021-07-05 10:53:18 +02:00
parent 4fb45402ee
commit 94852e07f7
20 changed files with 119 additions and 13 deletions

View File

@ -138,7 +138,7 @@ export type RawPublicPath =
/**
* The name of the runtime chunk. If set a runtime chunk with this name is created or an existing entrypoint is used as runtime.
*/
export type EntryRuntime = string;
export type EntryRuntime = false | string;
/**
* The method of loading WebAssembly Modules (methods included by default are 'fetch' (web/WebWorker), 'async-node' (node.js), but others might be added by plugins).
*/

View File

@ -56,6 +56,10 @@ export type LibraryType =
* If `output.libraryTarget` is set to umd and `output.library` is set, setting this to true will name the AMD module.
*/
export type UmdNamedDefine = boolean;
/**
* The name of the runtime chunk. If set a runtime chunk with this name is created or an existing entrypoint is used as runtime.
*/
export type EntryRuntime = false | string;
export interface ContainerPluginOptions {
/**
@ -74,6 +78,10 @@ export interface ContainerPluginOptions {
* The name for this container.
*/
name: string;
/**
* The name of the runtime chunk. If set a runtime chunk with this name is created or an existing entrypoint is used as runtime.
*/
runtime?: EntryRuntime;
/**
* The name of the share scope which is shared with the host (defaults to 'default').
*/

View File

@ -92,6 +92,10 @@ export type RemotesItem = string;
* Container locations from which modules should be resolved and loaded at runtime.
*/
export type RemotesItems = RemotesItem[];
/**
* The name of the runtime chunk. If set a runtime chunk with this name is created or an existing entrypoint is used as runtime.
*/
export type EntryRuntime = false | string;
/**
* Modules that should be shared in the share scope. When provided, property names are used to match requested modules in this compilation.
*/
@ -126,6 +130,10 @@ export interface ModuleFederationPluginOptions {
* Container locations and request scopes from which modules should be resolved and loaded at runtime. When provided, property name is used as request scope, otherwise request scope is automatically inferred from container location.
*/
remotes?: Remotes;
/**
* The name of the runtime chunk. If set a runtime chunk with this name is created or an existing entrypoint is used as runtime.
*/
runtime?: EntryRuntime;
/**
* Share scope name used for all shared modules (defaults to 'default').
*/

View File

@ -180,7 +180,11 @@ class FlagDependencyUsagePlugin {
b.groupOptions &&
b.groupOptions.entryOptions
) {
processModule(b, b.groupOptions.entryOptions.runtime, true);
processModule(
b,
b.groupOptions.entryOptions.runtime || undefined,
true
);
} else {
queue.enqueue(b);
}

View File

@ -39,6 +39,7 @@ class ContainerPlugin {
type: "var",
name: options.name
},
runtime: options.runtime,
filename: options.filename || undefined,
exposes: parseOptions(
options.exposes,
@ -60,7 +61,8 @@ class ContainerPlugin {
* @returns {void}
*/
apply(compiler) {
const { name, exposes, shareScope, filename, library } = this._options;
const { name, exposes, shareScope, filename, library, runtime } =
this._options;
compiler.options.output.enabledLibraryTypes.push(library.type);
@ -73,6 +75,7 @@ class ContainerPlugin {
{
name,
filename,
runtime,
library
},
error => {

View File

@ -64,6 +64,7 @@ class ModuleFederationPlugin {
name: options.name,
library,
filename: options.filename,
runtime: options.runtime,
exposes: options.exposes
}).apply(compiler);
}

View File

@ -270,7 +270,7 @@ class WorkerPlugin {
entryOptions.name = options.name;
}
if (!entryOptions.runtime) {
if (entryOptions.runtime === undefined) {
let i = workerIndexMap.get(parser.state) || 0;
workerIndexMap.set(parser.state, i + 1);
let name = `${cachedContextify(

View File

@ -27,7 +27,7 @@ class RuntimeChunkPlugin {
(_, { name: entryName }) => {
if (entryName === undefined) return;
const data = compilation.entries.get(entryName);
if (!data.options.runtime && !data.options.dependOn) {
if (data.options.runtime === undefined && !data.options.dependOn) {
// Determine runtime chunk name
let name = this.options.name;
if (typeof name === "function") {

File diff suppressed because one or more lines are too long

View File

@ -599,8 +599,15 @@
},
"EntryRuntime": {
"description": "The name of the runtime chunk. If set a runtime chunk with this name is created or an existing entrypoint is used as runtime.",
"type": "string",
"minLength": 1
"anyOf": [
{
"enum": [false]
},
{
"type": "string",
"minLength": 1
}
]
},
"EntryStatic": {
"description": "A static entry description.",

File diff suppressed because one or more lines are too long

View File

@ -12,6 +12,18 @@
}
]
},
"EntryRuntime": {
"description": "The name of the runtime chunk. If set a runtime chunk with this name is created or an existing entrypoint is used as runtime.",
"anyOf": [
{
"enum": [false]
},
{
"type": "string",
"minLength": 1
}
]
},
"Exposes": {
"description": "Modules that should be exposed by this container. When provided, property name is used as public name, otherwise public name is automatically inferred from request.",
"anyOf": [
@ -260,6 +272,9 @@
"type": "string",
"minLength": 1
},
"runtime": {
"$ref": "#/definitions/EntryRuntime"
},
"shareScope": {
"description": "The name of the share scope which is shared with the host (defaults to 'default').",
"type": "string",

File diff suppressed because one or more lines are too long

View File

@ -12,6 +12,18 @@
}
]
},
"EntryRuntime": {
"description": "The name of the runtime chunk. If set a runtime chunk with this name is created or an existing entrypoint is used as runtime.",
"anyOf": [
{
"enum": [false]
},
{
"type": "string",
"minLength": 1
}
]
},
"Exposes": {
"description": "Modules that should be exposed by this container. When provided, property name is used as public name, otherwise public name is automatically inferred from request.",
"anyOf": [
@ -484,6 +496,9 @@
"remotes": {
"$ref": "#/definitions/Remotes"
},
"runtime": {
"$ref": "#/definitions/EntryRuntime"
},
"shareScope": {
"description": "Share scope name used for all shared modules (defaults to 'default').",
"type": "string",

View File

@ -1,7 +1,10 @@
import React from "react";
import ComponentA from "containerA/ComponentA";
import ComponentB from "containerB/ComponentB";
import LocalComponentB from "./ComponentB";
export default () => {
return `App rendered with [${React()}] and [${ComponentA()}] and [${ComponentB()}]`;
};
expect(ComponentB).not.toBe(LocalComponentB);

View File

@ -3,11 +3,18 @@ const { ModuleFederationPlugin } = require("../../../../").container;
/** @type {import("../../../../").Configuration} */
module.exports = {
entry: {
bundle0: "./index.js"
},
output: {
filename: "[name].js"
},
plugins: [
new ModuleFederationPlugin({
name: "container",
library: { type: "commonjs-module" },
filename: "container.js",
runtime: false,
exposes: {
"./ComponentB": "./ComponentB",
"./ComponentC": "./ComponentC"
@ -18,5 +25,8 @@ module.exports = {
},
shared: ["react"]
})
]
],
optimization: {
runtimeChunk: "single"
}
};

View File

@ -0,0 +1 @@
it("should load without runtime", () => {});

View File

@ -0,0 +1,5 @@
module.exports = {
findBundle: function () {
return "./main.js";
}
};

View File

@ -0,0 +1,16 @@
/** @type {import("../../../../").Configuration} */
module.exports = {
entry: {
main: {
import: "./index",
runtime: false
}
},
target: "web",
output: {
filename: "[name].js"
},
optimization: {
runtimeChunk: "single"
}
};

14
types.d.ts vendored
View File

@ -2334,6 +2334,11 @@ declare interface ContainerPluginOptions {
*/
name: string;
/**
* The name of the runtime chunk. If set a runtime chunk with this name is created or an existing entrypoint is used as runtime.
*/
runtime?: string | false;
/**
* The name of the share scope which is shared with the host (defaults to 'default').
*/
@ -2986,7 +2991,7 @@ declare interface EntryDescription {
/**
* The name of the runtime chunk. If set a runtime chunk with this name is created or an existing entrypoint is used as runtime.
*/
runtime?: string;
runtime?: string | false;
/**
* The method of loading WebAssembly Modules (methods included by default are 'fetch' (web/WebWorker), 'async-node' (node.js), but others might be added by plugins).
@ -3036,7 +3041,7 @@ declare interface EntryDescriptionNormalized {
/**
* The name of the runtime chunk. If set a runtime chunk with this name is created or an existing entrypoint is used as runtime.
*/
runtime?: string;
runtime?: string | false;
/**
* The method of loading WebAssembly Modules (methods included by default are 'fetch' (web/WebWorker), 'async-node' (node.js), but others might be added by plugins).
@ -6455,6 +6460,11 @@ declare interface ModuleFederationPluginOptions {
*/
remotes?: (string | RemotesObject)[] | RemotesObject;
/**
* The name of the runtime chunk. If set a runtime chunk with this name is created or an existing entrypoint is used as runtime.
*/
runtime?: string | false;
/**
* Share scope name used for all shared modules (defaults to 'default').
*/