source: imaps-frontend/node_modules/webpack/lib/sharing/ProvideSharedPlugin.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: 7.2 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra and Zackary Jackson @ScriptedAlchemy
4*/
5
6"use strict";
7
8const WebpackError = require("../WebpackError");
9const { parseOptions } = require("../container/options");
10const createSchemaValidation = require("../util/create-schema-validation");
11const ProvideForSharedDependency = require("./ProvideForSharedDependency");
12const ProvideSharedDependency = require("./ProvideSharedDependency");
13const ProvideSharedModuleFactory = require("./ProvideSharedModuleFactory");
14
15/** @typedef {import("../../declarations/plugins/sharing/ProvideSharedPlugin").ProvideSharedPluginOptions} ProvideSharedPluginOptions */
16/** @typedef {import("../Compilation")} Compilation */
17/** @typedef {import("../Compiler")} Compiler */
18/** @typedef {import("../NormalModuleFactory").NormalModuleCreateData} NormalModuleCreateData */
19
20const validate = createSchemaValidation(
21 require("../../schemas/plugins/sharing/ProvideSharedPlugin.check.js"),
22 () => require("../../schemas/plugins/sharing/ProvideSharedPlugin.json"),
23 {
24 name: "Provide Shared Plugin",
25 baseDataPath: "options"
26 }
27);
28
29/**
30 * @typedef {object} ProvideOptions
31 * @property {string} shareKey
32 * @property {string} shareScope
33 * @property {string | undefined | false} version
34 * @property {boolean} eager
35 */
36
37/** @typedef {Map<string, { config: ProvideOptions, version: string | undefined | false }>} ResolvedProvideMap */
38
39class ProvideSharedPlugin {
40 /**
41 * @param {ProvideSharedPluginOptions} options options
42 */
43 constructor(options) {
44 validate(options);
45
46 this._provides = /** @type {[string, ProvideOptions][]} */ (
47 parseOptions(
48 options.provides,
49 item => {
50 if (Array.isArray(item))
51 throw new Error("Unexpected array of provides");
52 /** @type {ProvideOptions} */
53 const result = {
54 shareKey: item,
55 version: undefined,
56 shareScope: options.shareScope || "default",
57 eager: false
58 };
59 return result;
60 },
61 item => ({
62 shareKey: item.shareKey,
63 version: item.version,
64 shareScope: item.shareScope || options.shareScope || "default",
65 eager: Boolean(item.eager)
66 })
67 )
68 );
69 this._provides.sort(([a], [b]) => {
70 if (a < b) return -1;
71 if (b < a) return 1;
72 return 0;
73 });
74 }
75
76 /**
77 * Apply the plugin
78 * @param {Compiler} compiler the compiler instance
79 * @returns {void}
80 */
81 apply(compiler) {
82 /** @type {WeakMap<Compilation, ResolvedProvideMap>} */
83 const compilationData = new WeakMap();
84
85 compiler.hooks.compilation.tap(
86 "ProvideSharedPlugin",
87 (compilation, { normalModuleFactory }) => {
88 /** @type {ResolvedProvideMap} */
89 const resolvedProvideMap = new Map();
90 /** @type {Map<string, ProvideOptions>} */
91 const matchProvides = new Map();
92 /** @type {Map<string, ProvideOptions>} */
93 const prefixMatchProvides = new Map();
94 for (const [request, config] of this._provides) {
95 if (/^(\/|[A-Za-z]:\\|\\\\|\.\.?(\/|$))/.test(request)) {
96 // relative request
97 resolvedProvideMap.set(request, {
98 config,
99 version: config.version
100 });
101 } else if (/^(\/|[A-Za-z]:\\|\\\\)/.test(request)) {
102 // absolute path
103 resolvedProvideMap.set(request, {
104 config,
105 version: config.version
106 });
107 } else if (request.endsWith("/")) {
108 // module request prefix
109 prefixMatchProvides.set(request, config);
110 } else {
111 // module request
112 matchProvides.set(request, config);
113 }
114 }
115 compilationData.set(compilation, resolvedProvideMap);
116 /**
117 * @param {string} key key
118 * @param {ProvideOptions} config config
119 * @param {NormalModuleCreateData["resource"]} resource resource
120 * @param {NormalModuleCreateData["resourceResolveData"]} resourceResolveData resource resolve data
121 */
122 const provideSharedModule = (
123 key,
124 config,
125 resource,
126 resourceResolveData
127 ) => {
128 let version = config.version;
129 if (version === undefined) {
130 let details = "";
131 if (!resourceResolveData) {
132 details = "No resolve data provided from resolver.";
133 } else {
134 const descriptionFileData =
135 resourceResolveData.descriptionFileData;
136 if (!descriptionFileData) {
137 details =
138 "No description file (usually package.json) found. Add description file with name and version, or manually specify version in shared config.";
139 } else if (!descriptionFileData.version) {
140 details = `No version in description file (usually package.json). Add version to description file ${resourceResolveData.descriptionFilePath}, or manually specify version in shared config.`;
141 } else {
142 version = descriptionFileData.version;
143 }
144 }
145 if (!version) {
146 const error = new WebpackError(
147 `No version specified and unable to automatically determine one. ${details}`
148 );
149 error.file = `shared module ${key} -> ${resource}`;
150 compilation.warnings.push(error);
151 }
152 }
153 resolvedProvideMap.set(resource, {
154 config,
155 version
156 });
157 };
158 normalModuleFactory.hooks.module.tap(
159 "ProvideSharedPlugin",
160 (module, { resource, resourceResolveData }, resolveData) => {
161 if (resolvedProvideMap.has(/** @type {string} */ (resource))) {
162 return module;
163 }
164 const { request } = resolveData;
165 {
166 const config = matchProvides.get(request);
167 if (config !== undefined) {
168 provideSharedModule(
169 request,
170 config,
171 /** @type {string} */ (resource),
172 resourceResolveData
173 );
174 resolveData.cacheable = false;
175 }
176 }
177 for (const [prefix, config] of prefixMatchProvides) {
178 if (request.startsWith(prefix)) {
179 const remainder = request.slice(prefix.length);
180 provideSharedModule(
181 /** @type {string} */ (resource),
182 {
183 ...config,
184 shareKey: config.shareKey + remainder
185 },
186 /** @type {string} */ (resource),
187 resourceResolveData
188 );
189 resolveData.cacheable = false;
190 }
191 }
192 return module;
193 }
194 );
195 }
196 );
197 compiler.hooks.finishMake.tapPromise("ProvideSharedPlugin", compilation => {
198 const resolvedProvideMap = compilationData.get(compilation);
199 if (!resolvedProvideMap) return Promise.resolve();
200 return Promise.all(
201 Array.from(
202 resolvedProvideMap,
203 ([resource, { config, version }]) =>
204 new Promise((resolve, reject) => {
205 compilation.addInclude(
206 compiler.context,
207 new ProvideSharedDependency(
208 config.shareScope,
209 config.shareKey,
210 version || false,
211 resource,
212 config.eager
213 ),
214 {
215 name: undefined
216 },
217 err => {
218 if (err) return reject(err);
219 resolve(null);
220 }
221 );
222 })
223 )
224 ).then(() => {});
225 });
226
227 compiler.hooks.compilation.tap(
228 "ProvideSharedPlugin",
229 (compilation, { normalModuleFactory }) => {
230 compilation.dependencyFactories.set(
231 ProvideForSharedDependency,
232 normalModuleFactory
233 );
234
235 compilation.dependencyFactories.set(
236 ProvideSharedDependency,
237 new ProvideSharedModuleFactory()
238 );
239 }
240 );
241 }
242}
243
244module.exports = ProvideSharedPlugin;
Note: See TracBrowser for help on using the repository browser.