[6a3a178] | 1 | "use strict";
|
---|
| 2 |
|
---|
| 3 | Object.defineProperty(exports, "__esModule", {
|
---|
| 4 | value: true
|
---|
| 5 | });
|
---|
| 6 | exports.default = exports.pluginSymbol = exports.pluginName = void 0;
|
---|
| 7 |
|
---|
| 8 | var _schemaUtils = require("schema-utils");
|
---|
| 9 |
|
---|
| 10 | var _pluginOptions = _interopRequireDefault(require("./plugin-options.json"));
|
---|
| 11 |
|
---|
| 12 | var _utils = require("./utils");
|
---|
| 13 |
|
---|
| 14 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
---|
| 15 |
|
---|
| 16 | /* eslint-disable class-methods-use-this */
|
---|
| 17 | const pluginName = "mini-css-extract-plugin";
|
---|
| 18 | exports.pluginName = pluginName;
|
---|
| 19 | const pluginSymbol = Symbol(pluginName);
|
---|
| 20 | exports.pluginSymbol = pluginSymbol;
|
---|
| 21 | const DEFAULT_FILENAME = "[name].css";
|
---|
| 22 | const TYPES = new Set([_utils.MODULE_TYPE]);
|
---|
| 23 | const CODE_GENERATION_RESULT = {
|
---|
| 24 | sources: new Map(),
|
---|
| 25 | runtimeRequirements: new Set()
|
---|
| 26 | };
|
---|
| 27 | /**
|
---|
| 28 | * @type WeakMap<webpack, CssModule>
|
---|
| 29 | */
|
---|
| 30 |
|
---|
| 31 | const cssModuleCache = new WeakMap();
|
---|
| 32 | /**
|
---|
| 33 | * @type WeakMap<webpack, CssDependency>
|
---|
| 34 | */
|
---|
| 35 |
|
---|
| 36 | const cssDependencyCache = new WeakMap();
|
---|
| 37 | const registered = new WeakSet();
|
---|
| 38 |
|
---|
| 39 | class 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,
|
---|
[e29cc2e] | 54 | layer,
|
---|
| 55 | supports,
|
---|
[6a3a178] | 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;
|
---|
[e29cc2e] | 67 | this.layer = layer;
|
---|
| 68 | this.supports = supports;
|
---|
[6a3a178] | 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) {
|
---|
[e29cc2e] | 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) {
|
---|
[6a3a178] | 113 | this._needBuild = true;
|
---|
| 114 | this.content = module.content;
|
---|
[e29cc2e] | 115 | this.layer = module.layer;
|
---|
| 116 | this.supports = module.supports;
|
---|
[6a3a178] | 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);
|
---|
[e29cc2e] | 149 |
|
---|
| 150 | if (this.layer) {
|
---|
| 151 | hash.update(this.layer);
|
---|
| 152 | }
|
---|
| 153 |
|
---|
| 154 | hash.update(this.supports || "");
|
---|
[6a3a178] | 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);
|
---|
[e29cc2e] | 173 | write(this.layer);
|
---|
| 174 | write(this.supports);
|
---|
[6a3a178] | 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();
|
---|
[e29cc2e] | 204 | const layer = read();
|
---|
| 205 | const supports = read();
|
---|
[6a3a178] | 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,
|
---|
[e29cc2e] | 215 | layer,
|
---|
| 216 | supports,
|
---|
[6a3a178] | 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,
|
---|
[e29cc2e] | 243 | layer,
|
---|
| 244 | supports,
|
---|
[6a3a178] | 245 | media,
|
---|
| 246 | sourceMap
|
---|
| 247 | }, context, identifierIndex) {
|
---|
| 248 | super();
|
---|
| 249 | this.identifier = identifier;
|
---|
| 250 | this.identifierIndex = identifierIndex;
|
---|
| 251 | this.content = content;
|
---|
[e29cc2e] | 252 | this.layer = layer;
|
---|
| 253 | this.supports = supports;
|
---|
[6a3a178] | 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);
|
---|
[e29cc2e] | 278 | write(this.layer);
|
---|
| 279 | write(this.supports);
|
---|
[6a3a178] | 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(),
|
---|
[e29cc2e] | 308 | layer: read(),
|
---|
| 309 | supports: read(),
|
---|
[6a3a178] | 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,
|
---|
[e29cc2e] | 333 | // TODO remove in the next major release
|
---|
| 334 | // eslint-disable-next-line no-undefined
|
---|
| 335 | experimentalUseImportModule: undefined,
|
---|
| 336 | runtime: true
|
---|
[6a3a178] | 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 | }
|
---|
[e29cc2e] | 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 |
|
---|
[6a3a178] | 500 | const {
|
---|
[e29cc2e] | 501 | Template,
|
---|
[6a3a178] | 502 | RuntimeGlobals,
|
---|
[e29cc2e] | 503 | RuntimeModule,
|
---|
[6a3a178] | 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 | }, true));
|
---|
| 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 |
|
---|
[e29cc2e] | 740 | if (module.supports) {
|
---|
| 741 | source.add(`@supports (${module.supports}) {\n`);
|
---|
| 742 | }
|
---|
| 743 |
|
---|
[6a3a178] | 744 | if (module.media) {
|
---|
| 745 | source.add(`@media ${module.media} {\n`);
|
---|
| 746 | }
|
---|
| 747 |
|
---|
[e29cc2e] | 748 | const needLayer = typeof module.layer !== "undefined";
|
---|
| 749 |
|
---|
| 750 | if (needLayer) {
|
---|
| 751 | source.add(`@layer${module.layer.length > 0 ? ` ${module.layer}` : ""} {\n`);
|
---|
| 752 | }
|
---|
| 753 |
|
---|
[6a3a178] | 754 | const {
|
---|
| 755 | path: filename
|
---|
| 756 | } = compilation.getPathWithInfo(filenameTemplate, pathData);
|
---|
[e29cc2e] | 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"), ".");
|
---|
[6a3a178] | 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 |
|
---|
[e29cc2e] | 770 | if (needLayer) {
|
---|
| 771 | source.add("}\n");
|
---|
| 772 | }
|
---|
| 773 |
|
---|
[6a3a178] | 774 | if (module.media) {
|
---|
| 775 | source.add("}\n");
|
---|
| 776 | }
|
---|
[e29cc2e] | 777 |
|
---|
| 778 | if (module.supports) {
|
---|
| 779 | source.add("}\n");
|
---|
| 780 | }
|
---|
[6a3a178] | 781 | }
|
---|
| 782 | }
|
---|
| 783 |
|
---|
| 784 | return new ConcatSource(externalsSource, source);
|
---|
| 785 | }
|
---|
| 786 |
|
---|
| 787 | }
|
---|
| 788 |
|
---|
| 789 | MiniCssExtractPlugin.loader = require.resolve("./loader");
|
---|
| 790 | var _default = MiniCssExtractPlugin;
|
---|
| 791 | exports.default = _default; |
---|