DllReferencePlugin.js
5.0 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const parseJson = require("json-parse-even-better-errors");
const DelegatedModuleFactoryPlugin = require("./DelegatedModuleFactoryPlugin");
const ExternalModuleFactoryPlugin = require("./ExternalModuleFactoryPlugin");
const WebpackError = require("./WebpackError");
const DelegatedSourceDependency = require("./dependencies/DelegatedSourceDependency");
const createSchemaValidation = require("./util/create-schema-validation");
const makePathsRelative = require("./util/identifier").makePathsRelative;
/** @typedef {import("../declarations/WebpackOptions").Externals} Externals */
/** @typedef {import("../declarations/plugins/DllReferencePlugin").DllReferencePluginOptions} DllReferencePluginOptions */
/** @typedef {import("../declarations/plugins/DllReferencePlugin").DllReferencePluginOptionsManifest} DllReferencePluginOptionsManifest */
const validate = createSchemaValidation(
require("../schemas/plugins/DllReferencePlugin.check.js"),
() => require("../schemas/plugins/DllReferencePlugin.json"),
{
name: "Dll Reference Plugin",
baseDataPath: "options"
}
);
class DllReferencePlugin {
/**
* @param {DllReferencePluginOptions} options options object
*/
constructor(options) {
validate(options);
this.options = options;
/** @type {WeakMap<Object, {path: string, data: DllReferencePluginOptionsManifest?, error: Error?}>} */
this._compilationData = new WeakMap();
}
apply(compiler) {
compiler.hooks.compilation.tap(
"DllReferencePlugin",
(compilation, { normalModuleFactory }) => {
compilation.dependencyFactories.set(
DelegatedSourceDependency,
normalModuleFactory
);
}
);
compiler.hooks.beforeCompile.tapAsync(
"DllReferencePlugin",
(params, callback) => {
if ("manifest" in this.options) {
const manifest = this.options.manifest;
if (typeof manifest === "string") {
compiler.inputFileSystem.readFile(manifest, (err, result) => {
if (err) return callback(err);
const data = {
path: manifest,
data: undefined,
error: undefined
};
// Catch errors parsing the manifest so that blank
// or malformed manifest files don't kill the process.
try {
data.data = parseJson(result.toString("utf-8"));
} catch (e) {
// Store the error in the params so that it can
// be added as a compilation error later on.
const manifestPath = makePathsRelative(
compiler.options.context,
manifest,
compiler.root
);
data.error = new DllManifestError(manifestPath, e.message);
}
this._compilationData.set(params, data);
return callback();
});
return;
}
}
return callback();
}
);
compiler.hooks.compile.tap("DllReferencePlugin", params => {
let name = this.options.name;
let sourceType = this.options.sourceType;
let content =
"content" in this.options ? this.options.content : undefined;
if ("manifest" in this.options) {
let manifestParameter = this.options.manifest;
let manifest;
if (typeof manifestParameter === "string") {
const data = this._compilationData.get(params);
// If there was an error parsing the manifest
// file, exit now because the error will be added
// as a compilation error in the "compilation" hook.
if (data.error) {
return;
}
manifest = data.data;
} else {
manifest = manifestParameter;
}
if (manifest) {
if (!name) name = manifest.name;
if (!sourceType) sourceType = manifest.type;
if (!content) content = manifest.content;
}
}
/** @type {Externals} */
const externals = {};
const source = "dll-reference " + name;
externals[source] = name;
const normalModuleFactory = params.normalModuleFactory;
new ExternalModuleFactoryPlugin(sourceType || "var", externals).apply(
normalModuleFactory
);
new DelegatedModuleFactoryPlugin({
source: source,
type: this.options.type,
scope: this.options.scope,
context: this.options.context || compiler.options.context,
content,
extensions: this.options.extensions,
associatedObjectForCache: compiler.root
}).apply(normalModuleFactory);
});
compiler.hooks.compilation.tap(
"DllReferencePlugin",
(compilation, params) => {
if ("manifest" in this.options) {
let manifest = this.options.manifest;
if (typeof manifest === "string") {
const data = this._compilationData.get(params);
// If there was an error parsing the manifest file, add the
// error as a compilation error to make the compilation fail.
if (data.error) {
compilation.errors.push(data.error);
}
compilation.fileDependencies.add(manifest);
}
}
}
);
}
}
class DllManifestError extends WebpackError {
constructor(filename, message) {
super();
this.name = "DllManifestError";
this.message = `Dll manifest ${filename}\n${message}`;
}
}
module.exports = DllReferencePlugin;