* Applies the plugin by registering its hooks on the compiler. * @param {Dependency} dependency the dependency for which the template should be applied * @param {ReplaceSource} source the current replace source which can be modified * @param {DependencyTemplateContext} templateContext the cont
(dependency, source, templateContext)
| 449 | * @returns {void} |
| 450 | */ |
| 451 | apply(dependency, source, templateContext) { |
| 452 | const { runtimeTemplate } = templateContext; |
| 453 | const dep = /** @type {HtmlEntryDependency} */ (dependency); |
| 454 | const compilation = runtimeTemplate.compilation; |
| 455 | const { chunkGraph } = compilation; |
| 456 | const { crossOriginLoading } = compilation.outputOptions; |
| 457 | const entrypoint = /** @type {Entrypoint | undefined} */ ( |
| 458 | compilation.entrypoints.get(dep.entryName) |
| 459 | ); |
| 460 | |
| 461 | if (!entrypoint) { |
| 462 | source.replace(dep.range[0], dep.range[1] - 1, "data:,"); |
| 463 | return; |
| 464 | } |
| 465 | |
| 466 | const orderedChunks = getEntrypointChunksInLoadOrder(entrypoint); |
| 467 | const entryChunk = orderedChunks[orderedChunks.length - 1]; |
| 468 | const isStylesheet = dep.elementKind === "stylesheet"; |
| 469 | |
| 470 | // Rewrite src/href to a chunk-URL sentinel (resolved by renderManifest): |
| 471 | // `.css` for `<link rel="stylesheet">`, `.js` for everything else. |
| 472 | const entryContentHashType = isStylesheet ? "css" : "javascript"; |
| 473 | const entryUrl = HtmlGenerator.makeChunkUrlSentinel( |
| 474 | entryChunk, |
| 475 | entryContentHashType |
| 476 | ); |
| 477 | source.replace(dep.range[0], dep.range[1] - 1, entryUrl); |
| 478 | |
| 479 | if (dep.tagStart < 0 || dep.tagOpenEnd <= dep.tagStart) { |
| 480 | return; |
| 481 | } |
| 482 | |
| 483 | // The browser must load every chunk the entry needs, not just the |
| 484 | // entry chunk. For `<script>` entries that's the JS for sibling |
| 485 | // chunks plus — critically — the CSS for any chunk that holds |
| 486 | // stylesheets imported transitively from the JS source. Previously |
| 487 | // every sibling was cloned as a `<script>` pointing at a `.js` |
| 488 | // filename, so CSS chunks ended up as `<script src="foo.css">` |
| 489 | // pointing at non-existent `.js` files (the bug in |
| 490 | // html-webpack-plugin#1838 / webpack/mini-css-extract-plugin#959, |
| 491 | // magnified here because the entry chunk's own CSS was emitted to |
| 492 | // disk but never linked from the HTML at all). |
| 493 | const originalContent = /** @type {string} */ (source.original().source()); |
| 494 | const originalTag = originalContent.slice(dep.tagStart, dep.tagOpenEnd); |
| 495 | const srcStartInTag = dep.range[0] - dep.tagStart; |
| 496 | const srcEndInTag = dep.range[1] - dep.tagStart; |
| 497 | // Non-native originating elements (a custom element mapped to a |
| 498 | // `script`/`stylesheet` source `type`) can't be cloned verbatim — the |
| 499 | // clone would be invalid markup (e.g. `<my-script …></script>`), so a |
| 500 | // real native tag is synthesized instead. Decided at parse time from the |
| 501 | // tag name (`dep.tagIsNative`) rather than re-parsing the source text. |
| 502 | const tagIsNative = dep.tagIsNative; |
| 503 | |
| 504 | // `crossorigin` to mirror `output.crossOriginLoading` onto every injected |
| 505 | // tag. Empty when the option is off or the originating tag already set |
| 506 | // `crossorigin` (author value wins, flagged at parse time). Mirrors |
| 507 | // webpack's runtime, which sets `crossOrigin` on chunk-loading scripts, |
| 508 | // and matches Vite, which emits it on every injected script/stylesheet. |
nothing calls this directly
no test coverage detected