* Applies the plugin by registering its hooks on the compiler. * @param {Compiler} compiler the compiler instance * @returns {void}
(compiler)
| 124 | * @returns {void} |
| 125 | */ |
| 126 | apply(compiler) { |
| 127 | const { output } = compiler.options; |
| 128 | const htmlOption = output.html; |
| 129 | const scriptLoading = |
| 130 | (typeof htmlOption === class="st">"object" && htmlOption.scriptLoading) || class="st">"auto"; |
| 131 | class="cm">// ESM output emits `type=class="st">"module"` (already deferred), so scriptLoading |
| 132 | class="cm">// is ignored under output.module — warn on an explicit defer/blocking. |
| 133 | let scriptAttr = class="st">" defer"; |
| 134 | if (output.module) { |
| 135 | scriptAttr = class="st">""; |
| 136 | if (scriptLoading === class="st">"defer" || scriptLoading === class="st">"blocking") { |
| 137 | compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => { |
| 138 | compilation.warnings.push( |
| 139 | new WebpackError( |
| 140 | `output.html.scriptLoading: class="st">"${scriptLoading}" is ignored with output.module — ES module scripts are always deferred.` |
| 141 | ) |
| 142 | ); |
| 143 | }); |
| 144 | } |
| 145 | } else if (scriptLoading === class="st">"blocking") { |
| 146 | scriptAttr = class="st">""; |
| 147 | } |
| 148 | |
| 149 | class="cm">// `output.html` (or an entry's `html`) wraps a non-HTML entry in a |
| 150 | class="cm">// synthetic HTML module so the existing pipeline injects its JS/CSS |
| 151 | class="cm">// chunks and applies the `template` option. `dependOn` ancestors are |
| 152 | class="cm">// injected first so the page loads the shared/runtime chunks before |
| 153 | class="cm">// the entry's own (see `collectHtmlEntryRequests`). `crossOriginLoading` |
| 154 | class="cm">// and SRI are applied to the injected tags centrally in |
| 155 | class="cm">// HtmlEntryDependency. |
| 156 | EntryOptionPlugin.getHooks(compiler).entry.tap( |
| 157 | PLUGIN_NAME, |
| 158 | (context, name, desc) => { |
| 159 | const html = desc.html !== undefined ? desc.html : htmlOption; |
| 160 | const imports = desc.import; |
| 161 | if ( |
| 162 | !html || |
| 163 | !imports || |
| 164 | imports.every((r) => HTML_REQUEST_RE.test(r)) |
| 165 | ) { |
| 166 | return; |
| 167 | } |
| 168 | const entries = compiler.options.entry; |
| 169 | const requests = |
| 170 | typeof entries === class="st">"object" && entries[name] |
| 171 | ? collectHtmlEntryRequests(name, entries) |
| 172 | : imports.filter((r) => !HTML_REQUEST_RE.test(r)); |
| 173 | const links = []; |
| 174 | const scripts = []; |
| 175 | for (const r of requests) { |
| 176 | if (CSS_REQUEST_RE.test(r)) { |
| 177 | links.push(`<link rel=class="st">"stylesheet" href=class="st">"${r}">`); |
| 178 | } else { |
| 179 | scripts.push(`<script${scriptAttr} src=class="st">"${r}"></script>`); |
| 180 | } |
| 181 | } |
| 182 | return `data:text/html,<!doctype html><html><head>${links.join( |
| 183 | class="st">"" |
nothing calls this directly
no test coverage detected