source: imaps-frontend/node_modules/webpack/lib/sharing/ConsumeSharedPlugin.js@ 79a0317

main
Last change on this file since 79a0317 was 79a0317, checked in by stefan toskovski <stefantoska84@…>, 3 days ago

F4 Finalna Verzija

  • Property mode set to 100644
File size: 11.6 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const ModuleNotFoundError = require("../ModuleNotFoundError");
9const RuntimeGlobals = require("../RuntimeGlobals");
10const WebpackError = require("../WebpackError");
11const { parseOptions } = require("../container/options");
12const LazySet = require("../util/LazySet");
13const createSchemaValidation = require("../util/create-schema-validation");
14const { parseRange } = require("../util/semver");
15const ConsumeSharedFallbackDependency = require("./ConsumeSharedFallbackDependency");
16const ConsumeSharedModule = require("./ConsumeSharedModule");
17const ConsumeSharedRuntimeModule = require("./ConsumeSharedRuntimeModule");
18const ProvideForSharedDependency = require("./ProvideForSharedDependency");
19const { resolveMatchedConfigs } = require("./resolveMatchedConfigs");
20const {
21 isRequiredVersion,
22 getDescriptionFile,
23 getRequiredVersionFromDescriptionFile
24} = require("./utils");
25
26/** @typedef {import("../../declarations/plugins/sharing/ConsumeSharedPlugin").ConsumeSharedPluginOptions} ConsumeSharedPluginOptions */
27/** @typedef {import("../../declarations/plugins/sharing/ConsumeSharedPlugin").ConsumesConfig} ConsumesConfig */
28/** @typedef {import("../Compiler")} Compiler */
29/** @typedef {import("../ResolverFactory").ResolveOptionsWithDependencyType} ResolveOptionsWithDependencyType */
30/** @typedef {import("../util/semver").SemVerRange} SemVerRange */
31/** @typedef {import("./ConsumeSharedModule").ConsumeOptions} ConsumeOptions */
32/** @typedef {import("./utils").DescriptionFile} DescriptionFile */
33
34const validate = createSchemaValidation(
35 require("../../schemas/plugins/sharing/ConsumeSharedPlugin.check.js"),
36 () => require("../../schemas/plugins/sharing/ConsumeSharedPlugin.json"),
37 {
38 name: "Consume Shared Plugin",
39 baseDataPath: "options"
40 }
41);
42
43/** @type {ResolveOptionsWithDependencyType} */
44const RESOLVE_OPTIONS = { dependencyType: "esm" };
45const PLUGIN_NAME = "ConsumeSharedPlugin";
46
47class ConsumeSharedPlugin {
48 /**
49 * @param {ConsumeSharedPluginOptions} options options
50 */
51 constructor(options) {
52 if (typeof options !== "string") {
53 validate(options);
54 }
55
56 /** @type {[string, ConsumeOptions][]} */
57 this._consumes = parseOptions(
58 options.consumes,
59 (item, key) => {
60 if (Array.isArray(item)) throw new Error("Unexpected array in options");
61 /** @type {ConsumeOptions} */
62 const result =
63 item === key || !isRequiredVersion(item)
64 ? // item is a request/key
65 {
66 import: key,
67 shareScope: options.shareScope || "default",
68 shareKey: key,
69 requiredVersion: undefined,
70 packageName: undefined,
71 strictVersion: false,
72 singleton: false,
73 eager: false
74 }
75 : // key is a request/key
76 // item is a version
77 {
78 import: key,
79 shareScope: options.shareScope || "default",
80 shareKey: key,
81 requiredVersion: parseRange(item),
82 strictVersion: true,
83 packageName: undefined,
84 singleton: false,
85 eager: false
86 };
87 return result;
88 },
89 (item, key) => ({
90 import: item.import === false ? undefined : item.import || key,
91 shareScope: item.shareScope || options.shareScope || "default",
92 shareKey: item.shareKey || key,
93 requiredVersion:
94 typeof item.requiredVersion === "string"
95 ? parseRange(item.requiredVersion)
96 : item.requiredVersion,
97 strictVersion:
98 typeof item.strictVersion === "boolean"
99 ? item.strictVersion
100 : item.import !== false && !item.singleton,
101 packageName: item.packageName,
102 singleton: Boolean(item.singleton),
103 eager: Boolean(item.eager)
104 })
105 );
106 }
107
108 /**
109 * Apply the plugin
110 * @param {Compiler} compiler the compiler instance
111 * @returns {void}
112 */
113 apply(compiler) {
114 compiler.hooks.thisCompilation.tap(
115 PLUGIN_NAME,
116 (compilation, { normalModuleFactory }) => {
117 compilation.dependencyFactories.set(
118 ConsumeSharedFallbackDependency,
119 normalModuleFactory
120 );
121
122 /** @type {Map<string, ConsumeOptions>} */
123 let unresolvedConsumes;
124 /** @type {Map<string, ConsumeOptions>} */
125 let resolvedConsumes;
126 /** @type {Map<string, ConsumeOptions>} */
127 let prefixedConsumes;
128 const promise = resolveMatchedConfigs(compilation, this._consumes).then(
129 ({ resolved, unresolved, prefixed }) => {
130 resolvedConsumes = resolved;
131 unresolvedConsumes = unresolved;
132 prefixedConsumes = prefixed;
133 }
134 );
135
136 const resolver = compilation.resolverFactory.get(
137 "normal",
138 RESOLVE_OPTIONS
139 );
140
141 /**
142 * @param {string} context issuer directory
143 * @param {string} request request
144 * @param {ConsumeOptions} config options
145 * @returns {Promise<ConsumeSharedModule>} create module
146 */
147 const createConsumeSharedModule = (context, request, config) => {
148 /**
149 * @param {string} details details
150 */
151 const requiredVersionWarning = details => {
152 const error = new WebpackError(
153 `No required version specified and unable to automatically determine one. ${details}`
154 );
155 error.file = `shared module ${request}`;
156 compilation.warnings.push(error);
157 };
158 const directFallback =
159 config.import &&
160 /^(\.\.?(\/|$)|\/|[A-Za-z]:|\\\\)/.test(config.import);
161 return Promise.all([
162 new Promise(
163 /**
164 * @param {(value?: string) => void} resolve resolve
165 */
166 resolve => {
167 if (!config.import) {
168 resolve();
169 return;
170 }
171 const resolveContext = {
172 /** @type {LazySet<string>} */
173 fileDependencies: new LazySet(),
174 /** @type {LazySet<string>} */
175 contextDependencies: new LazySet(),
176 /** @type {LazySet<string>} */
177 missingDependencies: new LazySet()
178 };
179 resolver.resolve(
180 {},
181 directFallback ? compiler.context : context,
182 config.import,
183 resolveContext,
184 (err, result) => {
185 compilation.contextDependencies.addAll(
186 resolveContext.contextDependencies
187 );
188 compilation.fileDependencies.addAll(
189 resolveContext.fileDependencies
190 );
191 compilation.missingDependencies.addAll(
192 resolveContext.missingDependencies
193 );
194 if (err) {
195 compilation.errors.push(
196 new ModuleNotFoundError(null, err, {
197 name: `resolving fallback for shared module ${request}`
198 })
199 );
200 return resolve();
201 }
202 resolve(/** @type {string} */ (result));
203 }
204 );
205 }
206 ),
207 new Promise(
208 /**
209 * @param {(value?: SemVerRange) => void} resolve resolve
210 */
211 resolve => {
212 if (config.requiredVersion !== undefined) {
213 resolve(/** @type {SemVerRange} */ (config.requiredVersion));
214 return;
215 }
216 let packageName = config.packageName;
217 if (packageName === undefined) {
218 if (/^(\/|[A-Za-z]:|\\\\)/.test(request)) {
219 // For relative or absolute requests we don't automatically use a packageName.
220 // If wished one can specify one with the packageName option.
221 resolve();
222 return;
223 }
224 const match = /^((?:@[^\\/]+[\\/])?[^\\/]+)/.exec(request);
225 if (!match) {
226 requiredVersionWarning(
227 "Unable to extract the package name from request."
228 );
229 resolve();
230 return;
231 }
232 packageName = match[0];
233 }
234
235 getDescriptionFile(
236 compilation.inputFileSystem,
237 context,
238 ["package.json"],
239 (err, result, checkedDescriptionFilePaths) => {
240 if (err) {
241 requiredVersionWarning(
242 `Unable to read description file: ${err}`
243 );
244 return resolve();
245 }
246 const { data } =
247 /** @type {DescriptionFile} */
248 (result || {});
249 if (!data) {
250 if (checkedDescriptionFilePaths) {
251 requiredVersionWarning(
252 [
253 `Unable to find required version for "${packageName}" in description file/s`,
254 checkedDescriptionFilePaths.join("\n"),
255 "It need to be in dependencies, devDependencies or peerDependencies."
256 ].join("\n")
257 );
258 } else {
259 requiredVersionWarning(
260 `Unable to find description file in ${context}.`
261 );
262 }
263
264 return resolve();
265 }
266 if (data.name === packageName) {
267 // Package self-referencing
268 return resolve();
269 }
270 const requiredVersion =
271 getRequiredVersionFromDescriptionFile(data, packageName);
272
273 if (requiredVersion) {
274 return resolve(parseRange(requiredVersion));
275 }
276
277 resolve();
278 },
279 result => {
280 if (!result) return false;
281 const maybeRequiredVersion =
282 getRequiredVersionFromDescriptionFile(
283 result.data,
284 packageName
285 );
286 return (
287 result.data.name === packageName ||
288 typeof maybeRequiredVersion === "string"
289 );
290 }
291 );
292 }
293 )
294 ]).then(
295 ([importResolved, requiredVersion]) =>
296 new ConsumeSharedModule(
297 directFallback ? compiler.context : context,
298 {
299 ...config,
300 importResolved,
301 import: importResolved ? config.import : undefined,
302 requiredVersion
303 }
304 )
305 );
306 };
307
308 normalModuleFactory.hooks.factorize.tapPromise(
309 PLUGIN_NAME,
310 ({ context, request, dependencies }) =>
311 // wait for resolving to be complete
312 promise.then(() => {
313 if (
314 dependencies[0] instanceof ConsumeSharedFallbackDependency ||
315 dependencies[0] instanceof ProvideForSharedDependency
316 ) {
317 return;
318 }
319 const match = unresolvedConsumes.get(request);
320 if (match !== undefined) {
321 return createConsumeSharedModule(context, request, match);
322 }
323 for (const [prefix, options] of prefixedConsumes) {
324 if (request.startsWith(prefix)) {
325 const remainder = request.slice(prefix.length);
326 return createConsumeSharedModule(context, request, {
327 ...options,
328 import: options.import
329 ? options.import + remainder
330 : undefined,
331 shareKey: options.shareKey + remainder
332 });
333 }
334 }
335 })
336 );
337 normalModuleFactory.hooks.createModule.tapPromise(
338 PLUGIN_NAME,
339 ({ resource }, { context, dependencies }) => {
340 if (
341 dependencies[0] instanceof ConsumeSharedFallbackDependency ||
342 dependencies[0] instanceof ProvideForSharedDependency
343 ) {
344 return Promise.resolve();
345 }
346 const options = resolvedConsumes.get(
347 /** @type {string} */ (resource)
348 );
349 if (options !== undefined) {
350 return createConsumeSharedModule(
351 context,
352 /** @type {string} */ (resource),
353 options
354 );
355 }
356 return Promise.resolve();
357 }
358 );
359 compilation.hooks.additionalTreeRuntimeRequirements.tap(
360 PLUGIN_NAME,
361 (chunk, set) => {
362 set.add(RuntimeGlobals.module);
363 set.add(RuntimeGlobals.moduleCache);
364 set.add(RuntimeGlobals.moduleFactoriesAddOnly);
365 set.add(RuntimeGlobals.shareScopeMap);
366 set.add(RuntimeGlobals.initializeSharing);
367 set.add(RuntimeGlobals.hasOwnProperty);
368 compilation.addRuntimeModule(
369 chunk,
370 new ConsumeSharedRuntimeModule(set)
371 );
372 }
373 );
374 }
375 );
376 }
377}
378
379module.exports = ConsumeSharedPlugin;
Note: See TracBrowser for help on using the repository browser.