UNPKG

30.2 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.pluginSymbol = exports.pluginName = exports.default = void 0;
7
8var _schemaUtils = require("schema-utils");
9
10var _pluginOptions = _interopRequireDefault(require("./plugin-options.json"));
11
12var _utils = require("./utils");
13
14function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
16/* eslint-disable class-methods-use-this */
17const pluginName = "mini-css-extract-plugin";
18exports.pluginName = pluginName;
19const pluginSymbol = Symbol(pluginName);
20exports.pluginSymbol = pluginSymbol;
21const DEFAULT_FILENAME = "[name].css";
22const TYPES = new Set([_utils.MODULE_TYPE]);
23const CODE_GENERATION_RESULT = {
24 sources: new Map(),
25 runtimeRequirements: new Set()
26};
27/**
28 * @type WeakMap<webpack, CssModule>
29 */
30
31const cssModuleCache = new WeakMap();
32/**
33 * @type WeakMap<webpack, CssDependency>
34 */
35
36const cssDependencyCache = new WeakMap();
37const registered = new WeakSet();
38
39class MiniCssExtractPlugin {
40 static getCssModule(webpack) {
41 /**
42 * Prevent creation of multiple CssModule classes to allow other integrations to get the current CssModule.
43 */
44 if (cssModuleCache.has(webpack)) {
45 return cssModuleCache.get(webpack);
46 }
47
48 class CssModule extends webpack.Module {
49 constructor({
50 context,
51 identifier,
52 identifierIndex,
53 content,
54 layer,
55 supports,
56 media,
57 sourceMap,
58 assets,
59 assetsInfo
60 }) {
61 super(_utils.MODULE_TYPE, context);
62 this.id = "";
63 this._context = context;
64 this._identifier = identifier;
65 this._identifierIndex = identifierIndex;
66 this.content = content;
67 this.layer = layer;
68 this.supports = supports;
69 this.media = media;
70 this.sourceMap = sourceMap;
71 this.assets = assets;
72 this.assetsInfo = assetsInfo;
73 this._needBuild = true;
74 } // no source() so webpack 4 doesn't do add stuff to the bundle
75
76
77 size() {
78 return this.content.length;
79 }
80
81 identifier() {
82 return `css|${this._identifier}|${this._identifierIndex}`;
83 }
84
85 readableIdentifier(requestShortener) {
86 return `css ${requestShortener.shorten(this._identifier)}${this._identifierIndex ? ` (${this._identifierIndex})` : ""}`;
87 } // eslint-disable-next-line class-methods-use-this
88
89
90 getSourceTypes() {
91 return TYPES;
92 } // eslint-disable-next-line class-methods-use-this
93
94
95 codeGeneration() {
96 return CODE_GENERATION_RESULT;
97 }
98
99 nameForCondition() {
100 const resource = this._identifier.split("!").pop();
101
102 const idx = resource.indexOf("?");
103
104 if (idx >= 0) {
105 return resource.substring(0, idx);
106 }
107
108 return resource;
109 }
110
111 updateCacheModule(module) {
112 if (this.content !== module.content || this.layer !== module.layer || this.supports !== module.supports || this.media !== module.media || this.sourceMap !== module.sourceMap || this.assets !== module.assets || this.assetsInfo !== module.assetsInfo) {
113 this._needBuild = true;
114 this.content = module.content;
115 this.layer = module.layer;
116 this.supports = module.supports;
117 this.media = module.media;
118 this.sourceMap = module.sourceMap;
119 this.assets = module.assets;
120 this.assetsInfo = module.assetsInfo;
121 }
122 } // eslint-disable-next-line class-methods-use-this
123
124
125 needRebuild() {
126 return this._needBuild;
127 } // eslint-disable-next-line class-methods-use-this
128
129
130 needBuild(context, callback) {
131 callback(null, this._needBuild);
132 }
133
134 build(options, compilation, resolver, fileSystem, callback) {
135 this.buildInfo = {
136 assets: this.assets,
137 assetsInfo: this.assetsInfo,
138 cacheable: true,
139 hash: this._computeHash(compilation.outputOptions.hashFunction)
140 };
141 this.buildMeta = {};
142 this._needBuild = false;
143 callback();
144 }
145
146 _computeHash(hashFunction) {
147 const hash = webpack.util.createHash(hashFunction);
148 hash.update(this.content);
149
150 if (this.layer) {
151 hash.update(this.layer);
152 }
153
154 hash.update(this.supports || "");
155 hash.update(this.media || "");
156 hash.update(this.sourceMap || "");
157 return hash.digest("hex");
158 }
159
160 updateHash(hash, context) {
161 super.updateHash(hash, context);
162 hash.update(this.buildInfo.hash);
163 }
164
165 serialize(context) {
166 const {
167 write
168 } = context;
169 write(this._context);
170 write(this._identifier);
171 write(this._identifierIndex);
172 write(this.content);
173 write(this.layer);
174 write(this.supports);
175 write(this.media);
176 write(this.sourceMap);
177 write(this.assets);
178 write(this.assetsInfo);
179 write(this._needBuild);
180 super.serialize(context);
181 }
182
183 deserialize(context) {
184 this._needBuild = context.read();
185 super.deserialize(context);
186 }
187
188 }
189
190 cssModuleCache.set(webpack, CssModule);
191 webpack.util.serialization.register(CssModule, "mini-css-extract-plugin/dist/CssModule", null, {
192 serialize(instance, context) {
193 instance.serialize(context);
194 },
195
196 deserialize(context) {
197 const {
198 read
199 } = context;
200 const contextModule = read();
201 const identifier = read();
202 const identifierIndex = read();
203 const content = read();
204 const layer = read();
205 const supports = read();
206 const media = read();
207 const sourceMap = read();
208 const assets = read();
209 const assetsInfo = read();
210 const dep = new CssModule({
211 context: contextModule,
212 identifier,
213 identifierIndex,
214 content,
215 layer,
216 supports,
217 media,
218 sourceMap,
219 assets,
220 assetsInfo
221 });
222 dep.deserialize(context);
223 return dep;
224 }
225
226 });
227 return CssModule;
228 }
229
230 static getCssDependency(webpack) {
231 /**
232 * Prevent creation of multiple CssDependency classes to allow other integrations to get the current CssDependency.
233 */
234 if (cssDependencyCache.has(webpack)) {
235 return cssDependencyCache.get(webpack);
236 } // eslint-disable-next-line no-shadow
237
238
239 class CssDependency extends webpack.Dependency {
240 constructor({
241 identifier,
242 content,
243 layer,
244 supports,
245 media,
246 sourceMap
247 }, context, identifierIndex) {
248 super();
249 this.identifier = identifier;
250 this.identifierIndex = identifierIndex;
251 this.content = content;
252 this.layer = layer;
253 this.supports = supports;
254 this.media = media;
255 this.sourceMap = sourceMap;
256 this.context = context; // eslint-disable-next-line no-undefined
257
258 this.assets = undefined; // eslint-disable-next-line no-undefined
259
260 this.assetsInfo = undefined;
261 }
262
263 getResourceIdentifier() {
264 return `css-module-${this.identifier}-${this.identifierIndex}`;
265 } // eslint-disable-next-line class-methods-use-this
266
267
268 getModuleEvaluationSideEffectsState() {
269 return webpack.ModuleGraphConnection.TRANSITIVE_ONLY;
270 }
271
272 serialize(context) {
273 const {
274 write
275 } = context;
276 write(this.identifier);
277 write(this.content);
278 write(this.layer);
279 write(this.supports);
280 write(this.media);
281 write(this.sourceMap);
282 write(this.context);
283 write(this.identifierIndex);
284 write(this.assets);
285 write(this.assetsInfo);
286 super.serialize(context);
287 }
288
289 deserialize(context) {
290 super.deserialize(context);
291 }
292
293 }
294
295 cssDependencyCache.set(webpack, CssDependency);
296 webpack.util.serialization.register(CssDependency, "mini-css-extract-plugin/dist/CssDependency", null, {
297 serialize(instance, context) {
298 instance.serialize(context);
299 },
300
301 deserialize(context) {
302 const {
303 read
304 } = context;
305 const dep = new CssDependency({
306 identifier: read(),
307 content: read(),
308 layer: read(),
309 supports: read(),
310 media: read(),
311 sourceMap: read()
312 }, read(), read());
313 const assets = read();
314 const assetsInfo = read();
315 dep.assets = assets;
316 dep.assetsInfo = assetsInfo;
317 dep.deserialize(context);
318 return dep;
319 }
320
321 });
322 return CssDependency;
323 }
324
325 constructor(options = {}) {
326 (0, _schemaUtils.validate)(_pluginOptions.default, options, {
327 baseDataPath: "options"
328 });
329 this._sortedModulesCache = new WeakMap();
330 this.options = Object.assign({
331 filename: DEFAULT_FILENAME,
332 ignoreOrder: false,
333 // TODO remove in the next major release
334 // eslint-disable-next-line no-undefined
335 experimentalUseImportModule: undefined,
336 runtime: true
337 }, options);
338 this.runtimeOptions = {
339 insert: options.insert,
340 linkType: // Todo in next major release set default to "false"
341 options.linkType === true || typeof options.linkType === "undefined" ? "text/css" : options.linkType,
342 attributes: options.attributes
343 };
344
345 if (!this.options.chunkFilename) {
346 const {
347 filename
348 } = this.options;
349
350 if (typeof filename !== "function") {
351 const hasName = filename.includes("[name]");
352 const hasId = filename.includes("[id]");
353 const hasChunkHash = filename.includes("[chunkhash]");
354 const hasContentHash = filename.includes("[contenthash]"); // Anything changing depending on chunk is fine
355
356 if (hasChunkHash || hasContentHash || hasName || hasId) {
357 this.options.chunkFilename = filename;
358 } else {
359 // Otherwise prefix "[id]." in front of the basename to make it changing
360 this.options.chunkFilename = filename.replace(/(^|\/)([^/]*(?:\?|$))/, "$1[id].$2");
361 }
362 } else {
363 this.options.chunkFilename = "[id].css";
364 }
365 }
366 }
367 /** @param {import("webpack").Compiler} compiler */
368
369
370 apply(compiler) {
371 const {
372 webpack
373 } = compiler;
374
375 if (this.options.experimentalUseImportModule) {
376 if (typeof compiler.options.experiments.executeModule === "undefined") {
377 // eslint-disable-next-line no-param-reassign
378 compiler.options.experiments.executeModule = true;
379 }
380 } // TODO bug in webpack, remove it after it will be fixed
381 // webpack tries to `require` loader firstly when serializer doesn't found
382
383
384 if (!registered.has(webpack)) {
385 registered.add(webpack);
386 webpack.util.serialization.registerLoader(/^mini-css-extract-plugin\//, _utils.trueFn);
387 }
388
389 const {
390 splitChunks
391 } = compiler.options.optimization;
392
393 if (splitChunks) {
394 if (splitChunks.defaultSizeTypes.includes("...")) {
395 splitChunks.defaultSizeTypes.push(_utils.MODULE_TYPE);
396 }
397 }
398
399 const CssModule = MiniCssExtractPlugin.getCssModule(webpack);
400 const CssDependency = MiniCssExtractPlugin.getCssDependency(webpack);
401 const {
402 NormalModule
403 } = compiler.webpack;
404 compiler.hooks.compilation.tap(pluginName, compilation => {
405 const {
406 loader: normalModuleHook
407 } = NormalModule.getCompilationHooks(compilation);
408 normalModuleHook.tap(pluginName, loaderContext => {
409 // eslint-disable-next-line no-param-reassign
410 loaderContext[pluginSymbol] = {
411 experimentalUseImportModule: this.options.experimentalUseImportModule
412 };
413 });
414 });
415 compiler.hooks.thisCompilation.tap(pluginName, compilation => {
416 class CssModuleFactory {
417 // eslint-disable-next-line class-methods-use-this
418 create({
419 dependencies: [dependency]
420 }, callback) {
421 callback(null, new CssModule(dependency));
422 }
423
424 }
425
426 compilation.dependencyFactories.set(CssDependency, new CssModuleFactory());
427
428 class CssDependencyTemplate {
429 // eslint-disable-next-line class-methods-use-this
430 apply() {}
431
432 }
433
434 compilation.dependencyTemplates.set(CssDependency, new CssDependencyTemplate());
435 compilation.hooks.renderManifest.tap(pluginName, (result, {
436 chunk
437 }) => {
438 const {
439 chunkGraph
440 } = compilation;
441 const {
442 HotUpdateChunk
443 } = webpack; // We don't need hot update chunks for css
444 // We will use the real asset instead to update
445
446 if (chunk instanceof HotUpdateChunk) {
447 return;
448 }
449
450 const renderedModules = Array.from(this.getChunkModules(chunk, chunkGraph)).filter(module => module.type === _utils.MODULE_TYPE);
451 const filenameTemplate = chunk.canBeInitial() ? this.options.filename : this.options.chunkFilename;
452
453 if (renderedModules.length > 0) {
454 result.push({
455 render: () => this.renderContentAsset(compiler, compilation, chunk, renderedModules, compilation.runtimeTemplate.requestShortener, filenameTemplate, {
456 contentHashType: _utils.MODULE_TYPE,
457 chunk
458 }),
459 filenameTemplate,
460 pathOptions: {
461 chunk,
462 contentHashType: _utils.MODULE_TYPE
463 },
464 identifier: `${pluginName}.${chunk.id}`,
465 hash: chunk.contentHash[_utils.MODULE_TYPE]
466 });
467 }
468 });
469 compilation.hooks.contentHash.tap(pluginName, chunk => {
470 const {
471 outputOptions,
472 chunkGraph
473 } = compilation;
474 const modules = this.sortModules(compilation, chunk, chunkGraph.getChunkModulesIterableBySourceType(chunk, _utils.MODULE_TYPE), compilation.runtimeTemplate.requestShortener);
475
476 if (modules) {
477 const {
478 hashFunction,
479 hashDigest,
480 hashDigestLength
481 } = outputOptions;
482 const {
483 createHash
484 } = compiler.webpack.util;
485 const hash = createHash(hashFunction);
486
487 for (const m of modules) {
488 hash.update(chunkGraph.getModuleHash(m, chunk.runtime));
489 } // eslint-disable-next-line no-param-reassign
490
491
492 chunk.contentHash[_utils.MODULE_TYPE] = hash.digest(hashDigest).substring(0, hashDigestLength);
493 }
494 }); // All the code below is dedicated to the runtime and can be skipped when the `runtime` option is `false`
495
496 if (!this.options.runtime) {
497 return;
498 }
499
500 const {
501 Template,
502 RuntimeGlobals,
503 RuntimeModule,
504 runtime
505 } = webpack; // eslint-disable-next-line no-shadow
506
507 const getCssChunkObject = (mainChunk, compilation) => {
508 const obj = {};
509 const {
510 chunkGraph
511 } = compilation;
512
513 for (const chunk of mainChunk.getAllAsyncChunks()) {
514 const modules = chunkGraph.getOrderedChunkModulesIterable(chunk, _utils.compareModulesByIdentifier);
515
516 for (const module of modules) {
517 if (module.type === _utils.MODULE_TYPE) {
518 obj[chunk.id] = 1;
519 break;
520 }
521 }
522 }
523
524 return obj;
525 };
526
527 class CssLoadingRuntimeModule extends RuntimeModule {
528 constructor(runtimeRequirements, runtimeOptions) {
529 super("css loading", 10);
530 this.runtimeRequirements = runtimeRequirements;
531 this.runtimeOptions = runtimeOptions;
532 }
533
534 generate() {
535 const {
536 chunk,
537 runtimeRequirements
538 } = this;
539 const {
540 runtimeTemplate,
541 outputOptions: {
542 crossOriginLoading
543 }
544 } = this.compilation;
545 const chunkMap = getCssChunkObject(chunk, this.compilation);
546 const withLoading = runtimeRequirements.has(RuntimeGlobals.ensureChunkHandlers) && Object.keys(chunkMap).length > 0;
547 const withHmr = runtimeRequirements.has(RuntimeGlobals.hmrDownloadUpdateHandlers);
548
549 if (!withLoading && !withHmr) {
550 return null;
551 }
552
553 return Template.asString([`var createStylesheet = ${runtimeTemplate.basicFunction("chunkId, fullhref, resolve, reject", ['var linkTag = document.createElement("link");', this.runtimeOptions.attributes ? Template.asString(Object.entries(this.runtimeOptions.attributes).map(entry => {
554 const [key, value] = entry;
555 return `linkTag.setAttribute(${JSON.stringify(key)}, ${JSON.stringify(value)});`;
556 })) : "", 'linkTag.rel = "stylesheet";', this.runtimeOptions.linkType ? `linkTag.type = ${JSON.stringify(this.runtimeOptions.linkType)};` : "", `var onLinkComplete = ${runtimeTemplate.basicFunction("event", ["// avoid mem leaks.", "linkTag.onerror = linkTag.onload = null;", "if (event.type === 'load') {", Template.indent(["resolve();"]), "} else {", Template.indent(["var errorType = event && (event.type === 'load' ? 'missing' : event.type);", "var realHref = event && event.target && event.target.href || fullhref;", 'var err = new Error("Loading CSS chunk " + chunkId + " failed.\\n(" + realHref + ")");', 'err.code = "CSS_CHUNK_LOAD_FAILED";', "err.type = errorType;", "err.request = realHref;", "linkTag.parentNode.removeChild(linkTag)", "reject(err);"]), "}"])}`, "linkTag.onerror = linkTag.onload = onLinkComplete;", "linkTag.href = fullhref;", crossOriginLoading ? Template.asString([`if (linkTag.href.indexOf(window.location.origin + '/') !== 0) {`, Template.indent(`linkTag.crossOrigin = ${JSON.stringify(crossOriginLoading)};`), "}"]) : "", typeof this.runtimeOptions.insert !== "undefined" ? typeof this.runtimeOptions.insert === "function" ? `(${this.runtimeOptions.insert.toString()})(linkTag)` : Template.asString([`var target = document.querySelector("${this.runtimeOptions.insert}");`, `target.parentNode.insertBefore(linkTag, target.nextSibling);`]) : Template.asString(["document.head.appendChild(linkTag);"]), "return linkTag;"])};`, `var findStylesheet = ${runtimeTemplate.basicFunction("href, fullhref", ['var existingLinkTags = document.getElementsByTagName("link");', "for(var i = 0; i < existingLinkTags.length; i++) {", Template.indent(["var tag = existingLinkTags[i];", 'var dataHref = tag.getAttribute("data-href") || tag.getAttribute("href");', 'if(tag.rel === "stylesheet" && (dataHref === href || dataHref === fullhref)) return tag;']), "}", 'var existingStyleTags = document.getElementsByTagName("style");', "for(var i = 0; i < existingStyleTags.length; i++) {", Template.indent(["var tag = existingStyleTags[i];", 'var dataHref = tag.getAttribute("data-href");', "if(dataHref === href || dataHref === fullhref) return tag;"]), "}"])};`, `var loadStylesheet = ${runtimeTemplate.basicFunction("chunkId", `return new Promise(${runtimeTemplate.basicFunction("resolve, reject", [`var href = ${RuntimeGlobals.require}.miniCssF(chunkId);`, `var fullhref = ${RuntimeGlobals.publicPath} + href;`, "if(findStylesheet(href, fullhref)) return resolve();", "createStylesheet(chunkId, fullhref, resolve, reject);"])});`)}`, withLoading ? Template.asString(["// object to store loaded CSS chunks", "var installedCssChunks = {", Template.indent(chunk.ids.map(id => `${JSON.stringify(id)}: 0`).join(",\n")), "};", "", `${RuntimeGlobals.ensureChunkHandlers}.miniCss = ${runtimeTemplate.basicFunction("chunkId, promises", [`var cssChunks = ${JSON.stringify(chunkMap)};`, "if(installedCssChunks[chunkId]) promises.push(installedCssChunks[chunkId]);", "else if(installedCssChunks[chunkId] !== 0 && cssChunks[chunkId]) {", Template.indent([`promises.push(installedCssChunks[chunkId] = loadStylesheet(chunkId).then(${runtimeTemplate.basicFunction("", "installedCssChunks[chunkId] = 0;")}, ${runtimeTemplate.basicFunction("e", ["delete installedCssChunks[chunkId];", "throw e;"])}));`]), "}"])};`]) : "// no chunk loading", "", withHmr ? Template.asString(["var oldTags = [];", "var newTags = [];", `var applyHandler = ${runtimeTemplate.basicFunction("options", [`return { dispose: ${runtimeTemplate.basicFunction("", ["for(var i = 0; i < oldTags.length; i++) {", Template.indent(["var oldTag = oldTags[i];", "if(oldTag.parentNode) oldTag.parentNode.removeChild(oldTag);"]), "}", "oldTags.length = 0;"])}, apply: ${runtimeTemplate.basicFunction("", ['for(var i = 0; i < newTags.length; i++) newTags[i].rel = "stylesheet";', "newTags.length = 0;"])} };`])}`, `${RuntimeGlobals.hmrDownloadUpdateHandlers}.miniCss = ${runtimeTemplate.basicFunction("chunkIds, removedChunks, removedModules, promises, applyHandlers, updatedModulesList", ["applyHandlers.push(applyHandler);", `chunkIds.forEach(${runtimeTemplate.basicFunction("chunkId", [`var href = ${RuntimeGlobals.require}.miniCssF(chunkId);`, `var fullhref = ${RuntimeGlobals.publicPath} + href;`, "var oldTag = findStylesheet(href, fullhref);", "if(!oldTag) return;", `promises.push(new Promise(${runtimeTemplate.basicFunction("resolve, reject", [`var tag = createStylesheet(chunkId, fullhref, ${runtimeTemplate.basicFunction("", ['tag.as = "style";', 'tag.rel = "preload";', "resolve();"])}, reject);`, "oldTags.push(oldTag);", "newTags.push(tag);"])}));`])});`])}`]) : "// no hmr"]);
557 }
558
559 }
560
561 const enabledChunks = new WeakSet();
562
563 const handler = (chunk, set) => {
564 if (enabledChunks.has(chunk)) {
565 return;
566 }
567
568 enabledChunks.add(chunk);
569
570 if (typeof this.options.chunkFilename === "string" && /\[(full)?hash(:\d+)?\]/.test(this.options.chunkFilename)) {
571 set.add(RuntimeGlobals.getFullHash);
572 }
573
574 set.add(RuntimeGlobals.publicPath);
575 compilation.addRuntimeModule(chunk, new runtime.GetChunkFilenameRuntimeModule(_utils.MODULE_TYPE, "mini-css", `${RuntimeGlobals.require}.miniCssF`, referencedChunk => {
576 if (!referencedChunk.contentHash[_utils.MODULE_TYPE]) {
577 return false;
578 }
579
580 return referencedChunk.canBeInitial() ? this.options.filename : this.options.chunkFilename;
581 }));
582 compilation.addRuntimeModule(chunk, new CssLoadingRuntimeModule(set, this.runtimeOptions));
583 };
584
585 compilation.hooks.runtimeRequirementInTree.for(RuntimeGlobals.ensureChunkHandlers).tap(pluginName, handler);
586 compilation.hooks.runtimeRequirementInTree.for(RuntimeGlobals.hmrDownloadUpdateHandlers).tap(pluginName, handler);
587 });
588 }
589
590 getChunkModules(chunk, chunkGraph) {
591 return typeof chunkGraph !== "undefined" ? chunkGraph.getOrderedChunkModulesIterable(chunk, _utils.compareModulesByIdentifier) : chunk.modulesIterable;
592 }
593
594 sortModules(compilation, chunk, modules, requestShortener) {
595 let usedModules = this._sortedModulesCache.get(chunk);
596
597 if (usedModules || !modules) {
598 return usedModules;
599 }
600
601 const modulesList = [...modules]; // Store dependencies for modules
602
603 const moduleDependencies = new Map(modulesList.map(m => [m, new Set()]));
604 const moduleDependenciesReasons = new Map(modulesList.map(m => [m, new Map()])); // Get ordered list of modules per chunk group
605 // This loop also gathers dependencies from the ordered lists
606 // Lists are in reverse order to allow to use Array.pop()
607
608 const modulesByChunkGroup = Array.from(chunk.groupsIterable, chunkGroup => {
609 const sortedModules = modulesList.map(module => {
610 return {
611 module,
612 index: chunkGroup.getModulePostOrderIndex(module)
613 };
614 }) // eslint-disable-next-line no-undefined
615 .filter(item => item.index !== undefined).sort((a, b) => b.index - a.index).map(item => item.module);
616
617 for (let i = 0; i < sortedModules.length; i++) {
618 const set = moduleDependencies.get(sortedModules[i]);
619 const reasons = moduleDependenciesReasons.get(sortedModules[i]);
620
621 for (let j = i + 1; j < sortedModules.length; j++) {
622 const module = sortedModules[j];
623 set.add(module);
624 const reason = reasons.get(module) || new Set();
625 reason.add(chunkGroup);
626 reasons.set(module, reason);
627 }
628 }
629
630 return sortedModules;
631 }); // set with already included modules in correct order
632
633 usedModules = new Set();
634
635 const unusedModulesFilter = m => !usedModules.has(m);
636
637 while (usedModules.size < modulesList.length) {
638 let success = false;
639 let bestMatch;
640 let bestMatchDeps; // get first module where dependencies are fulfilled
641
642 for (const list of modulesByChunkGroup) {
643 // skip and remove already added modules
644 while (list.length > 0 && usedModules.has(list[list.length - 1])) {
645 list.pop();
646 } // skip empty lists
647
648
649 if (list.length !== 0) {
650 const module = list[list.length - 1];
651 const deps = moduleDependencies.get(module); // determine dependencies that are not yet included
652
653 const failedDeps = Array.from(deps).filter(unusedModulesFilter); // store best match for fallback behavior
654
655 if (!bestMatchDeps || bestMatchDeps.length > failedDeps.length) {
656 bestMatch = list;
657 bestMatchDeps = failedDeps;
658 }
659
660 if (failedDeps.length === 0) {
661 // use this module and remove it from list
662 usedModules.add(list.pop());
663 success = true;
664 break;
665 }
666 }
667 }
668
669 if (!success) {
670 // no module found => there is a conflict
671 // use list with fewest failed deps
672 // and emit a warning
673 const fallbackModule = bestMatch.pop();
674
675 if (!this.options.ignoreOrder) {
676 const reasons = moduleDependenciesReasons.get(fallbackModule);
677 compilation.warnings.push(new Error([`chunk ${chunk.name || chunk.id} [${pluginName}]`, "Conflicting order. Following module has been added:", ` * ${fallbackModule.readableIdentifier(requestShortener)}`, "despite it was not able to fulfill desired ordering with these modules:", ...bestMatchDeps.map(m => {
678 const goodReasonsMap = moduleDependenciesReasons.get(m);
679 const goodReasons = goodReasonsMap && goodReasonsMap.get(fallbackModule);
680 const failedChunkGroups = Array.from(reasons.get(m), cg => cg.name).join(", ");
681 const goodChunkGroups = goodReasons && Array.from(goodReasons, cg => cg.name).join(", ");
682 return [` * ${m.readableIdentifier(requestShortener)}`, ` - couldn't fulfill desired order of chunk group(s) ${failedChunkGroups}`, goodChunkGroups && ` - while fulfilling desired order of chunk group(s) ${goodChunkGroups}`].filter(Boolean).join("\n");
683 })].join("\n")));
684 }
685
686 usedModules.add(fallbackModule);
687 }
688 }
689
690 this._sortedModulesCache.set(chunk, usedModules);
691
692 return usedModules;
693 }
694
695 renderContentAsset(compiler, compilation, chunk, modules, requestShortener, filenameTemplate, pathData) {
696 const usedModules = this.sortModules(compilation, chunk, modules, requestShortener);
697 const {
698 ConcatSource,
699 SourceMapSource,
700 RawSource
701 } = compiler.webpack.sources;
702 const source = new ConcatSource();
703 const externalsSource = new ConcatSource();
704
705 for (const module of usedModules) {
706 let content = module.content.toString();
707 const readableIdentifier = module.readableIdentifier(requestShortener);
708 const startsWithAtRuleImport = /^@import url/.test(content);
709 let header;
710
711 if (compilation.outputOptions.pathinfo) {
712 // From https://github.com/webpack/webpack/blob/29eff8a74ecc2f87517b627dee451c2af9ed3f3f/lib/ModuleInfoHeaderPlugin.js#L191-L194
713 const reqStr = readableIdentifier.replace(/\*\//g, "*_/");
714 const reqStrStar = "*".repeat(reqStr.length);
715 const headerStr = `/*!****${reqStrStar}****!*\\\n !*** ${reqStr} ***!\n \\****${reqStrStar}****/\n`;
716 header = new RawSource(headerStr);
717 }
718
719 if (startsWithAtRuleImport) {
720 if (typeof header !== "undefined") {
721 externalsSource.add(header);
722 } // HACK for IE
723 // http://stackoverflow.com/a/14676665/1458162
724
725
726 if (module.media) {
727 // insert media into the @import
728 // this is rar
729 // TODO improve this and parse the CSS to support multiple medias
730 content = content.replace(/;|\s*$/, module.media);
731 }
732
733 externalsSource.add(content);
734 externalsSource.add("\n");
735 } else {
736 if (typeof header !== "undefined") {
737 source.add(header);
738 }
739
740 if (module.supports) {
741 source.add(`@supports (${module.supports}) {\n`);
742 }
743
744 if (module.media) {
745 source.add(`@media ${module.media} {\n`);
746 }
747
748 const needLayer = typeof module.layer !== "undefined";
749
750 if (needLayer) {
751 source.add(`@layer${module.layer.length > 0 ? ` ${module.layer}` : ""} {\n`);
752 }
753
754 const {
755 path: filename
756 } = compilation.getPathWithInfo(filenameTemplate, pathData);
757 const undoPath = (0, _utils.getUndoPath)(filename, compiler.outputPath, false);
758 content = content.replace(new RegExp(_utils.ABSOLUTE_PUBLIC_PATH, "g"), "");
759 content = content.replace(new RegExp(_utils.SINGLE_DOT_PATH_SEGMENT, "g"), ".");
760 content = content.replace(new RegExp(_utils.AUTO_PUBLIC_PATH, "g"), undoPath);
761
762 if (module.sourceMap) {
763 source.add(new SourceMapSource(content, readableIdentifier, module.sourceMap.toString()));
764 } else {
765 source.add(new RawSource(content, readableIdentifier));
766 }
767
768 source.add("\n");
769
770 if (needLayer) {
771 source.add("}\n");
772 }
773
774 if (module.media) {
775 source.add("}\n");
776 }
777
778 if (module.supports) {
779 source.add("}\n");
780 }
781 }
782 }
783
784 return new ConcatSource(externalsSource, source);
785 }
786
787}
788
789MiniCssExtractPlugin.loader = require.resolve("./loader");
790var _default = MiniCssExtractPlugin;
791exports.default = _default;
\No newline at end of file