mirror of https://github.com/webpack/webpack.git
add manifest option
This commit is contained in:
parent
7ec1187eb3
commit
a5e113f289
|
|
@ -231,6 +231,10 @@ export type FilterTypes = FilterItemTypes[] | FilterItemTypes;
|
|||
* Filtering value, regexp or function.
|
||||
*/
|
||||
export type FilterItemTypes = RegExp | string | ((value: string) => boolean);
|
||||
/**
|
||||
* Options for manifest.
|
||||
*/
|
||||
export type Manifest = false | string;
|
||||
/**
|
||||
* Enable production optimizations or development hints.
|
||||
*/
|
||||
|
|
@ -817,6 +821,10 @@ export interface WebpackOptions {
|
|||
* Custom values available in the loader context.
|
||||
*/
|
||||
loader?: Loader;
|
||||
/**
|
||||
* Options for manifest.
|
||||
*/
|
||||
manifest?: Manifest;
|
||||
/**
|
||||
* Enable production optimizations or development hints.
|
||||
*/
|
||||
|
|
@ -3247,6 +3255,10 @@ export interface WebpackOptionsNormalized {
|
|||
* Custom values available in the loader context.
|
||||
*/
|
||||
loader?: Loader;
|
||||
/**
|
||||
* Options for manifest.
|
||||
*/
|
||||
manifest?: Manifest;
|
||||
/**
|
||||
* Enable production optimizations or development hints.
|
||||
*/
|
||||
|
|
@ -3336,6 +3348,10 @@ export interface ExperimentsExtra {
|
|||
* Compile entrypoints and import()s only when they are accessed.
|
||||
*/
|
||||
lazyCompilation?: boolean | LazyCompilationOptions;
|
||||
/**
|
||||
* Allow to output manifest, request child manifest in compilation.
|
||||
*/
|
||||
manifest?: boolean;
|
||||
}
|
||||
/**
|
||||
* Enables/Disables experiments (experimental features with relax SemVer compatibility).
|
||||
|
|
@ -3349,6 +3365,10 @@ export interface ExperimentsNormalizedExtra {
|
|||
* Compile entrypoints and import()s only when they are accessed.
|
||||
*/
|
||||
lazyCompilation?: LazyCompilationOptions;
|
||||
/**
|
||||
* Allow to output manifest, request child manifest in compilation.
|
||||
*/
|
||||
manifest?: boolean;
|
||||
}
|
||||
/**
|
||||
* If an dependency matches exactly a property of the object, the property value is used as dependency.
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ const { SyncHook, MultiHook } = require("tapable");
|
|||
const ConcurrentCompilationError = require("./ConcurrentCompilationError");
|
||||
const MultiStats = require("./MultiStats");
|
||||
const MultiWatching = require("./MultiWatching");
|
||||
const ManifestConsumerPlugin = require("./stats/ManifestConsumerPlugin");
|
||||
const ArrayQueue = require("./util/ArrayQueue");
|
||||
|
||||
/** @template T @typedef {import("tapable").AsyncSeriesHook<T>} AsyncSeriesHook<T> */
|
||||
|
|
@ -193,6 +194,17 @@ module.exports = class MultiCompiler {
|
|||
this.dependencies.set(compiler, dependencies);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Compiler} compiler compiler
|
||||
* @param {Compiler[]} dependencies parents of child compiler
|
||||
* @returns {void}
|
||||
*/
|
||||
applyDependencies(compiler, dependencies) {
|
||||
if (compiler.options.experiments.manifest) {
|
||||
new ManifestConsumerPlugin().apply(compiler, dependencies);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Callback<MultiStats>} callback signals when the validation is complete
|
||||
* @returns {boolean} true if the dependencies are valid
|
||||
|
|
@ -358,7 +370,15 @@ module.exports = class MultiCompiler {
|
|||
node.state = "queued";
|
||||
queue.enqueue(node);
|
||||
}
|
||||
|
||||
// we should apply dependencies even for empty list
|
||||
// this allows to pass correct compilation errors
|
||||
this.applyDependencies(
|
||||
node.compiler,
|
||||
node.parents.map(({ compiler }) => compiler)
|
||||
);
|
||||
}
|
||||
|
||||
let errored = false;
|
||||
let running = 0;
|
||||
const parallelism = this._options.parallelism;
|
||||
|
|
|
|||
|
|
@ -508,6 +508,11 @@ class WebpackOptionsApply extends OptionsApply {
|
|||
}
|
||||
}
|
||||
|
||||
if (options.manifest) {
|
||||
const ManifestPlugin = require("./stats/ManifestPlugin");
|
||||
new ManifestPlugin(options.manifest).apply(compiler);
|
||||
}
|
||||
|
||||
if (options.performance) {
|
||||
const SizeLimitsPlugin = require("./performance/SizeLimitsPlugin");
|
||||
new SizeLimitsPlugin(options.performance).apply(compiler);
|
||||
|
|
|
|||
|
|
@ -154,6 +154,7 @@ const applyWebpackOptionsDefaults = options => {
|
|||
}
|
||||
|
||||
F(options, "devtool", () => (development ? "eval" : false));
|
||||
D(options, "manifest", false);
|
||||
D(options, "watch", false);
|
||||
D(options, "profile", false);
|
||||
D(options, "parallelism", 100);
|
||||
|
|
@ -272,6 +273,7 @@ const applyExperimentsDefaults = (experiments, { production, development }) => {
|
|||
D(experiments, "asset", false);
|
||||
D(experiments, "layers", false);
|
||||
D(experiments, "lazyCompilation", undefined);
|
||||
D(experiments, "manifest", false);
|
||||
D(experiments, "buildHttp", undefined);
|
||||
D(experiments, "futureDefaults", false);
|
||||
D(experiments, "cacheUnaffected", experiments.futureDefaults);
|
||||
|
|
|
|||
|
|
@ -212,6 +212,7 @@ const getNormalizedWebpackOptions = config => {
|
|||
: undefined,
|
||||
infrastructureLogging: cloneObject(config.infrastructureLogging),
|
||||
loader: cloneObject(config.loader),
|
||||
manifest: config.manifest,
|
||||
mode: config.mode,
|
||||
module: nestedConfig(config.module, module => ({
|
||||
noParse: module.noParse,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Ivan Kopeykin @vankop
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const NormalModule = require("../NormalModule");
|
||||
const { extractManifest } = require("./ManifestPlugin");
|
||||
|
||||
/** @typedef {import("../Compiler")} Compiler */
|
||||
|
||||
const STAGE = 101;
|
||||
|
||||
function getCompilerName(request) {
|
||||
return request.slice(/* 'webpack-manifest:'.length */ 17);
|
||||
}
|
||||
|
||||
class ManifestConsumerPlugin {
|
||||
/**
|
||||
* Every stats provider compiler should have name
|
||||
* @param {Compiler} statsConsumerCompiler compiler that consumes stats
|
||||
* @param {Compiler[]} statsProviderCompilers compiler that provides stats
|
||||
*/
|
||||
apply(statsConsumerCompiler, statsProviderCompilers) {
|
||||
if (!statsConsumerCompiler.options.experiments.manifest) {
|
||||
throw new Error(
|
||||
"'manifest' is only allowed when 'experiments.manifest' is enabled"
|
||||
);
|
||||
}
|
||||
|
||||
const statsByCompilerName = new Map();
|
||||
const manifestByCompilerName = new Map();
|
||||
const names = new Set();
|
||||
|
||||
function getRawManifest(rawRequest) {
|
||||
const name = getCompilerName(rawRequest);
|
||||
let manifest = manifestByCompilerName.get(name);
|
||||
|
||||
if (!manifest) {
|
||||
const stats = statsByCompilerName.get(name);
|
||||
if (!stats) return;
|
||||
manifest = extractManifest(stats);
|
||||
statsByCompilerName.delete(name);
|
||||
manifestByCompilerName.set(name, manifest);
|
||||
}
|
||||
|
||||
return JSON.stringify(manifest);
|
||||
}
|
||||
|
||||
for (const compiler of statsProviderCompilers) {
|
||||
const name = compiler.name;
|
||||
names.add(name);
|
||||
compiler.hooks.done.tap(
|
||||
{
|
||||
stage: STAGE,
|
||||
name: "ManifestConsumerPlugin"
|
||||
},
|
||||
stats => {
|
||||
statsByCompilerName.set(name, stats);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
statsConsumerCompiler.hooks.compilation.tap(
|
||||
"ManifestConsumerPlugin",
|
||||
(compilation, { normalModuleFactory }) => {
|
||||
normalModuleFactory.hooks.resolveForScheme
|
||||
.for("webpack-manifest")
|
||||
.tapAsync(
|
||||
"ManifestConsumerPlugin",
|
||||
(resourceData, resolveData, callback) => {
|
||||
const compilerName = getCompilerName(resourceData.resource);
|
||||
|
||||
if (!names.has(compilerName)) {
|
||||
return callback(
|
||||
new Error(
|
||||
`Compiler ${JSON.stringify(compilerName)} not found.`
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
resourceData.data.name = compilerName;
|
||||
resourceData.data.mimetype = "application/json";
|
||||
callback(null, true);
|
||||
}
|
||||
);
|
||||
NormalModule.getCompilationHooks(compilation)
|
||||
.readResourceForScheme.for("webpack-manifest")
|
||||
.tap("ManifestConsumerPlugin", getRawManifest);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ManifestConsumerPlugin;
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Ivan Kopeykin @vankop
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
/** @typedef {import("../Compiler")} Compiler */
|
||||
/** @typedef {import("../Stats")} Stats */
|
||||
|
||||
const STAGE = 100;
|
||||
|
||||
/**
|
||||
* @param {Stats} stats stats
|
||||
* @returns {object} json
|
||||
*/
|
||||
function extractManifest(stats) {
|
||||
return stats.toJson({ preset: "manifest" });
|
||||
}
|
||||
|
||||
class ManifestPlugin {
|
||||
/**
|
||||
* @param {string} path path
|
||||
*/
|
||||
constructor(path) {
|
||||
/** @type {string} */
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Compiler} compiler compiler that provides stats
|
||||
*/
|
||||
apply(compiler) {
|
||||
if (!compiler.options.experiments.manifest) {
|
||||
throw new Error(
|
||||
"'manifest' is only allowed when 'experiments.manifest' is enabled"
|
||||
);
|
||||
}
|
||||
|
||||
compiler.hooks.done.tapAsync(
|
||||
{
|
||||
stage: STAGE,
|
||||
name: "ManifestPlugin"
|
||||
},
|
||||
(stats, cb) => {
|
||||
const manifest = extractManifest(stats);
|
||||
compiler.outputFileSystem.writeFile(
|
||||
this.path,
|
||||
JSON.stringify(manifest),
|
||||
err => {
|
||||
if (!err) return cb();
|
||||
|
||||
err.message = `Error during writing manifest. ${err.message}`;
|
||||
cb(err);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ManifestPlugin.extractManifest = extractManifest;
|
||||
|
||||
module.exports = ManifestPlugin;
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -723,6 +723,10 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"manifest": {
|
||||
"description": "Allow to output manifest, request child manifest in compilation.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"outputModule": {
|
||||
"description": "Allow output javascript files as module source type.",
|
||||
"type": "boolean"
|
||||
|
|
@ -818,6 +822,10 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"manifest": {
|
||||
"description": "Allow to output manifest, request child manifest in compilation.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"outputModule": {
|
||||
"description": "Allow output javascript files as module source type.",
|
||||
"type": "boolean"
|
||||
|
|
@ -1817,6 +1825,17 @@
|
|||
"description": "Custom values available in the loader context.",
|
||||
"type": "object"
|
||||
},
|
||||
"Manifest": {
|
||||
"description": "Options for manifest.",
|
||||
"anyOf": [
|
||||
{
|
||||
"enum": [false]
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"MemoryCacheOptions": {
|
||||
"description": "Options object for in-memory caching.",
|
||||
"type": "object",
|
||||
|
|
@ -4887,6 +4906,9 @@
|
|||
"loader": {
|
||||
"$ref": "#/definitions/Loader"
|
||||
},
|
||||
"manifest": {
|
||||
"$ref": "#/definitions/Manifest"
|
||||
},
|
||||
"mode": {
|
||||
"$ref": "#/definitions/Mode"
|
||||
},
|
||||
|
|
@ -5033,6 +5055,9 @@
|
|||
"loader": {
|
||||
"$ref": "#/definitions/Loader"
|
||||
},
|
||||
"manifest": {
|
||||
"$ref": "#/definitions/Manifest"
|
||||
},
|
||||
"mode": {
|
||||
"$ref": "#/definitions/Mode"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ Object {
|
|||
"futureDefaults": false,
|
||||
"layers": false,
|
||||
"lazyCompilation": undefined,
|
||||
"manifest": false,
|
||||
"outputModule": false,
|
||||
"syncWebAssembly": false,
|
||||
"topLevelAwait": false,
|
||||
|
|
@ -118,6 +119,7 @@ Object {
|
|||
"loader": Object {
|
||||
"target": "web",
|
||||
},
|
||||
"manifest": false,
|
||||
"mode": "none",
|
||||
"module": Object {
|
||||
"defaultRules": Array [
|
||||
|
|
|
|||
|
|
@ -691,6 +691,19 @@ Object {
|
|||
"multiple": false,
|
||||
"simpleType": "string",
|
||||
},
|
||||
"experiments-manifest": Object {
|
||||
"configs": Array [
|
||||
Object {
|
||||
"description": "Allow to output manifest, request child manifest in compilation.",
|
||||
"multiple": false,
|
||||
"path": "experiments.manifest",
|
||||
"type": "boolean",
|
||||
},
|
||||
],
|
||||
"description": "Allow to output manifest, request child manifest in compilation.",
|
||||
"multiple": false,
|
||||
"simpleType": "boolean",
|
||||
},
|
||||
"experiments-output-module": Object {
|
||||
"configs": Array [
|
||||
Object {
|
||||
|
|
@ -1051,6 +1064,28 @@ Object {
|
|||
"multiple": false,
|
||||
"simpleType": "string",
|
||||
},
|
||||
"manifest": Object {
|
||||
"configs": Array [
|
||||
Object {
|
||||
"description": "Options for manifest.",
|
||||
"multiple": false,
|
||||
"path": "manifest",
|
||||
"type": "enum",
|
||||
"values": Array [
|
||||
false,
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"description": "Options for manifest.",
|
||||
"multiple": false,
|
||||
"path": "manifest",
|
||||
"type": "string",
|
||||
},
|
||||
],
|
||||
"description": "Options for manifest.",
|
||||
"multiple": false,
|
||||
"simpleType": "string",
|
||||
},
|
||||
"mode": Object {
|
||||
"configs": Array [
|
||||
Object {
|
||||
|
|
@ -7267,6 +7302,7 @@ Object {
|
|||
"summary",
|
||||
"errors-only",
|
||||
"errors-warnings",
|
||||
"manifest",
|
||||
"minimal",
|
||||
"normal",
|
||||
"detailed",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
import manifest1 from "webpack-manifest:web";
|
||||
import manifest2 from "webpack-manifest:web2";
|
||||
|
||||
it("should provide correct entrypoints", () => {
|
||||
expect(Object.keys(manifest1.entrypoints)).toEqual(
|
||||
expect.arrayContaining(["page1", "page2"])
|
||||
);
|
||||
expect(Object.keys(manifest2.entrypoints)).toEqual(
|
||||
expect.arrayContaining(["main"])
|
||||
);
|
||||
});
|
||||
|
|
@ -0,0 +1 @@
|
|||
it("should compile", () => {});
|
||||
|
|
@ -0,0 +1 @@
|
|||
it("should compile", () => {});
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
module.exports = {
|
||||
findBundle: function(i, options) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
return ["./page1.js", "./page2.js"];
|
||||
case 1:
|
||||
return "./web2.js";
|
||||
case 2:
|
||||
return "./main.js";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/** @type {import("../../../../").Configuration} */
|
||||
module.exports = [
|
||||
{
|
||||
name: "web",
|
||||
target: "web",
|
||||
entry: {
|
||||
page1: "./page1.js",
|
||||
page2: "./page2.js"
|
||||
},
|
||||
output: {
|
||||
filename: "[name].js"
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "web2",
|
||||
target: "web",
|
||||
entry: "./page1.js",
|
||||
output: {
|
||||
filename: "web2.js"
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "node",
|
||||
target: "node",
|
||||
entry: "./node.js",
|
||||
experiments: {
|
||||
manifest: true
|
||||
},
|
||||
output: {
|
||||
filename: "main.js"
|
||||
},
|
||||
dependencies: ["web", "web2"]
|
||||
}
|
||||
];
|
||||
|
|
@ -2131,6 +2131,11 @@ declare interface Configuration {
|
|||
*/
|
||||
loader?: Loader;
|
||||
|
||||
/**
|
||||
* Options for manifest.
|
||||
*/
|
||||
manifest?: string | false;
|
||||
|
||||
/**
|
||||
* Enable production optimizations or development hints.
|
||||
*/
|
||||
|
|
@ -3351,6 +3356,11 @@ declare interface ExperimentsExtra {
|
|||
* Compile entrypoints and import()s only when they are accessed.
|
||||
*/
|
||||
lazyCompilation?: boolean | LazyCompilationOptions;
|
||||
|
||||
/**
|
||||
* Allow to output manifest, request child manifest in compilation.
|
||||
*/
|
||||
manifest?: boolean;
|
||||
}
|
||||
type ExperimentsNormalized = ExperimentsCommon & ExperimentsNormalizedExtra;
|
||||
|
||||
|
|
@ -3367,6 +3377,11 @@ declare interface ExperimentsNormalizedExtra {
|
|||
* Compile entrypoints and import()s only when they are accessed.
|
||||
*/
|
||||
lazyCompilation?: LazyCompilationOptions;
|
||||
|
||||
/**
|
||||
* Allow to output manifest, request child manifest in compilation.
|
||||
*/
|
||||
manifest?: boolean;
|
||||
}
|
||||
declare abstract class ExportInfo {
|
||||
name: string;
|
||||
|
|
@ -7069,6 +7084,7 @@ declare class MultiCompiler {
|
|||
intermediateFileSystem: IntermediateFileSystem;
|
||||
getInfrastructureLogger(name?: any): WebpackLogger;
|
||||
setDependencies(compiler: Compiler, dependencies: string[]): void;
|
||||
applyDependencies(compiler: Compiler, dependencies: Compiler[]): void;
|
||||
validateDependencies(callback: CallbackFunction<MultiStats>): boolean;
|
||||
runWithDependencies(
|
||||
compilers: Compiler[],
|
||||
|
|
@ -11924,6 +11940,11 @@ declare interface WebpackOptionsNormalized {
|
|||
*/
|
||||
loader?: Loader;
|
||||
|
||||
/**
|
||||
* Options for manifest.
|
||||
*/
|
||||
manifest?: string | false;
|
||||
|
||||
/**
|
||||
* Enable production optimizations or development hints.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue