1 | <div align="center">
|
2 | <img width="200" height="200" src="https://www.w3.org/html/logo/downloads/HTML5_Logo.svg" alt="html-loader">
|
3 | <a href="https://github.com/webpack/webpack">
|
4 | <img width="200" height="200" vspace="" hspace="25" src="https://webpack.js.org/assets/icon-square-big.svg" alt="webpack">
|
5 | </a>
|
6 | </div>
|
7 |
|
8 | [![npm][npm]][npm-url]
|
9 | [![node][node]][node-url]
|
10 | [![tests][tests]][tests-url]
|
11 | [![coverage][cover]][cover-url]
|
12 | [![chat][chat]][chat-url]
|
13 | [![size][size]][size-url]
|
14 |
|
15 | # html-loader
|
16 |
|
17 | Exports HTML as string. HTML is minimized when the compiler demands.
|
18 |
|
19 | ## Getting Started
|
20 |
|
21 | To begin, you'll need to install `html-loader`:
|
22 |
|
23 | ```console
|
24 | npm install --save-dev html-loader
|
25 | ```
|
26 |
|
27 | or
|
28 |
|
29 | ```console
|
30 | yarn add -D html-loader
|
31 | ```
|
32 |
|
33 | or
|
34 |
|
35 | ```console
|
36 | pnpm add -D html-loader
|
37 | ```
|
38 |
|
39 | Then add the plugin to your `webpack` config. For example:
|
40 |
|
41 | **file.js**
|
42 |
|
43 | ```js
|
44 | import html from "./file.html";
|
45 | ```
|
46 |
|
47 | **webpack.config.js**
|
48 |
|
49 | ```js
|
50 | module.exports = {
|
51 | module: {
|
52 | rules: [
|
53 | {
|
54 | test: /\.html$/i,
|
55 | loader: "html-loader",
|
56 | },
|
57 | ],
|
58 | },
|
59 | };
|
60 | ```
|
61 |
|
62 | ## Options
|
63 |
|
64 | - **[`sources`](#sources)**
|
65 | - **[`preprocessor`](#preprocessor)**
|
66 | - **[`minimize`](#minimize)**
|
67 | - **[`esModule`](#esmodule)**
|
68 |
|
69 | ### `sources`
|
70 |
|
71 | Type:
|
72 |
|
73 | ```ts
|
74 | type sources =
|
75 | | boolean
|
76 | | {
|
77 | list?: Array<{
|
78 | tag?: string;
|
79 | attribute?: string;
|
80 | type?: string;
|
81 | filter?: (
|
82 | tag: string,
|
83 | attribute: string,
|
84 | attributes: string,
|
85 | resourcePath: string
|
86 | ) => boolean;
|
87 | }>;
|
88 | urlFilter?: (
|
89 | attribute: string,
|
90 | value: string,
|
91 | resourcePath: string
|
92 | ) => boolean;
|
93 | };
|
94 | ```
|
95 |
|
96 | Default: `true`
|
97 |
|
98 | By default every loadable attributes (for example - `<img src="image.png">`) is imported (`const img = require('./image.png')` or `import img from "./image.png""`).
|
99 | You may need to specify loaders for images in your configuration (recommended [`asset modules`](https://webpack.js.org/guides/asset-modules/)).
|
100 |
|
101 | Supported tags and attributes:
|
102 |
|
103 | - the `src` attribute of the `audio` tag
|
104 | - the `src` attribute of the `embed` tag
|
105 | - the `src` attribute of the `img` tag
|
106 | - the `srcset` attribute of the `img` tag
|
107 | - the `src` attribute of the `input` tag
|
108 | - the `data` attribute of the `object` tag
|
109 | - the `src` attribute of the `script` tag
|
110 | - the `href` attribute of the `script` tag
|
111 | - the `xlink:href` attribute of the `script` tag
|
112 | - the `src` attribute of the `source` tag
|
113 | - the `srcset` attribute of the `source` tag
|
114 | - the `src` attribute of the `track` tag
|
115 | - the `poster` attribute of the `video` tag
|
116 | - the `src` attribute of the `video` tag
|
117 | - the `xlink:href` attribute of the `image` tag
|
118 | - the `href` attribute of the `image` tag
|
119 | - the `xlink:href` attribute of the `use` tag
|
120 | - the `href` attribute of the `use` tag
|
121 | - the `href` attribute of the `link` tag when the `rel` attribute contains `stylesheet`, `icon`, `shortcut icon`, `mask-icon`, `apple-touch-icon`, `apple-touch-icon-precomposed`, `apple-touch-startup-image`, `manifest`, `prefetch`, `preload` or when the `itemprop` attribute is `image`, `logo`, `screenshot`, `thumbnailurl`, `contenturl`, `downloadurl`, `duringmedia`, `embedurl`, `installurl`, `layoutimage`
|
122 | - the `imagesrcset` attribute of the `link` tag when the `rel` attribute contains `stylesheet`, `icon`, `shortcut icon`, `mask-icon`, `apple-touch-icon`, `apple-touch-icon-precomposed`, `apple-touch-startup-image`, `manifest`, `prefetch`, `preload`
|
123 | - the `content` attribute of the `meta` tag when the `name` attribute is `msapplication-tileimage`, `msapplication-square70x70logo`, `msapplication-square150x150logo`, `msapplication-wide310x150logo`, `msapplication-square310x310logo`, `msapplication-config`, `twitter:image` or when the `property` attribute is `og:image`, `og:image:url`, `og:image:secure_url`, `og:audio`, `og:audio:secure_url`, `og:video`, `og:video:secure_url`, `vk:image` or when the `itemprop` attribute is `image`, `logo`, `screenshot`, `thumbnailurl`, `contenturl`, `downloadurl`, `duringmedia`, `embedurl`, `installurl`, `layoutimage`
|
124 | - the `icon-uri` value component in `content` attribute of the `meta` tag when the `name` attribute is `msapplication-task`
|
125 |
|
126 | #### `boolean`
|
127 |
|
128 | The `true` value enables processing of all default elements and attributes, the `false` disable processing of all attributes.
|
129 |
|
130 | **webpack.config.js**
|
131 |
|
132 | ```js
|
133 | module.exports = {
|
134 | module: {
|
135 | rules: [
|
136 | {
|
137 | test: /\.html$/i,
|
138 | loader: "html-loader",
|
139 | options: {
|
140 | // Disables attributes processing
|
141 | sources: false,
|
142 | },
|
143 | },
|
144 | ],
|
145 | },
|
146 | };
|
147 | ```
|
148 |
|
149 | #### `object`
|
150 |
|
151 | Allows you to specify which tags and attributes to process, filter them, filter urls and process sources starts with `/`.
|
152 |
|
153 | For example:
|
154 |
|
155 | **webpack.config.js**
|
156 |
|
157 | ```js
|
158 | module.exports = {
|
159 | module: {
|
160 | rules: [
|
161 | {
|
162 | test: /\.html$/i,
|
163 | loader: "html-loader",
|
164 | options: {
|
165 | sources: {
|
166 | list: [
|
167 | // All default supported tags and attributes
|
168 | "...",
|
169 | {
|
170 | tag: "img",
|
171 | attribute: "data-src",
|
172 | type: "src",
|
173 | },
|
174 | {
|
175 | tag: "img",
|
176 | attribute: "data-srcset",
|
177 | type: "srcset",
|
178 | },
|
179 | ],
|
180 | urlFilter: (attribute, value, resourcePath) => {
|
181 | // The `attribute` argument contains a name of the HTML attribute.
|
182 | // The `value` argument contains a value of the HTML attribute.
|
183 | // The `resourcePath` argument contains a path to the loaded HTML file.
|
184 |
|
185 | if (/example\.pdf$/.test(value)) {
|
186 | return false;
|
187 | }
|
188 |
|
189 | return true;
|
190 | },
|
191 | },
|
192 | },
|
193 | },
|
194 | ],
|
195 | },
|
196 | };
|
197 | ```
|
198 |
|
199 | #### `list`
|
200 |
|
201 | Type:
|
202 |
|
203 | ```ts
|
204 | type list = Array<{
|
205 | tag?: string;
|
206 | attribute?: string;
|
207 | type?: string;
|
208 | filter?: (
|
209 | tag: string,
|
210 | attribute: string,
|
211 | attributes: string,
|
212 | resourcePath: string
|
213 | ) => boolean;
|
214 | }>;
|
215 | ```
|
216 |
|
217 | Default: [supported tags and attributes](#sources).
|
218 |
|
219 | Allows to setup which tags and attributes to process and how, and the ability to filter some of them.
|
220 |
|
221 | Using `...` syntax allows you to extend [default supported tags and attributes](#sources).
|
222 |
|
223 | For example:
|
224 |
|
225 | **webpack.config.js**
|
226 |
|
227 | ```js
|
228 | module.exports = {
|
229 | module: {
|
230 | rules: [
|
231 | {
|
232 | test: /\.html$/i,
|
233 | loader: "html-loader",
|
234 | options: {
|
235 | sources: {
|
236 | list: [
|
237 | // All default supported tags and attributes
|
238 | "...",
|
239 | {
|
240 | tag: "img",
|
241 | attribute: "data-src",
|
242 | type: "src",
|
243 | },
|
244 | {
|
245 | tag: "img",
|
246 | attribute: "data-srcset",
|
247 | type: "srcset",
|
248 | },
|
249 | {
|
250 | // Tag name
|
251 | tag: "link",
|
252 | // Attribute name
|
253 | attribute: "href",
|
254 | // Type of processing, can be `src` or `scrset`
|
255 | type: "src",
|
256 | // Allow to filter some attributes
|
257 | filter: (tag, attribute, attributes, resourcePath) => {
|
258 | // The `tag` argument contains a name of the HTML tag.
|
259 | // The `attribute` argument contains a name of the HTML attribute.
|
260 | // The `attributes` argument contains all attributes of the tag.
|
261 | // The `resourcePath` argument contains a path to the loaded HTML file.
|
262 |
|
263 | if (/my-html\.html$/.test(resourcePath)) {
|
264 | return false;
|
265 | }
|
266 |
|
267 | if (!/stylesheet/i.test(attributes.rel)) {
|
268 | return false;
|
269 | }
|
270 |
|
271 | if (
|
272 | attributes.type &&
|
273 | attributes.type.trim().toLowerCase() !== "text/css"
|
274 | ) {
|
275 | return false;
|
276 | }
|
277 |
|
278 | return true;
|
279 | },
|
280 | },
|
281 | ],
|
282 | },
|
283 | },
|
284 | },
|
285 | ],
|
286 | },
|
287 | };
|
288 | ```
|
289 |
|
290 | If the tag name is not specified it will process all the tags.
|
291 |
|
292 | > You can use your custom filter to specify html elements to be processed.
|
293 |
|
294 | For example:
|
295 |
|
296 | **webpack.config.js**
|
297 |
|
298 | ```js
|
299 | module.exports = {
|
300 | module: {
|
301 | rules: [
|
302 | {
|
303 | test: /\.html$/i,
|
304 | loader: "html-loader",
|
305 | options: {
|
306 | sources: {
|
307 | list: [
|
308 | {
|
309 | // Attribute name
|
310 | attribute: "src",
|
311 | // Type of processing, can be `src` or `scrset`
|
312 | type: "src",
|
313 | // Allow to filter some attributes (optional)
|
314 | filter: (tag, attribute, attributes, resourcePath) => {
|
315 | // The `tag` argument contains a name of the HTML tag.
|
316 | // The `attribute` argument contains a name of the HTML attribute.
|
317 | // The `attributes` argument contains all attributes of the tag.
|
318 | // The `resourcePath` argument contains a path to the loaded HTML file.
|
319 |
|
320 | // choose all HTML tags except img tag
|
321 | return tag.toLowerCase() !== "img";
|
322 | },
|
323 | },
|
324 | ],
|
325 | },
|
326 | },
|
327 | },
|
328 | ],
|
329 | },
|
330 | };
|
331 | ```
|
332 |
|
333 | Filter can also be used to extend the supported elements and attributes.
|
334 |
|
335 | For example, filter can help process meta tags that reference assets:
|
336 |
|
337 | ```js
|
338 | module.exports = {
|
339 | module: {
|
340 | rules: [
|
341 | {
|
342 | test: /\.html$/i,
|
343 | loader: "html-loader",
|
344 | options: {
|
345 | sources: {
|
346 | list: [
|
347 | {
|
348 | tag: "meta",
|
349 | attribute: "content",
|
350 | type: "src",
|
351 | filter: (tag, attribute, attributes, resourcePath) => {
|
352 | if (
|
353 | attributes.value === "og:image" ||
|
354 | attributes.name === "twitter:image"
|
355 | ) {
|
356 | return true;
|
357 | }
|
358 |
|
359 | return false;
|
360 | },
|
361 | },
|
362 | ],
|
363 | },
|
364 | },
|
365 | },
|
366 | ],
|
367 | },
|
368 | };
|
369 | ```
|
370 |
|
371 | **Note:** source with a `tag` option takes precedence over source without.
|
372 |
|
373 | Filter can be used to disable default sources.
|
374 |
|
375 | For example:
|
376 |
|
377 | ```js
|
378 | module.exports = {
|
379 | module: {
|
380 | rules: [
|
381 | {
|
382 | test: /\.html$/i,
|
383 | loader: "html-loader",
|
384 | options: {
|
385 | sources: {
|
386 | list: [
|
387 | "...",
|
388 | {
|
389 | tag: "img",
|
390 | attribute: "src",
|
391 | type: "src",
|
392 | filter: () => false,
|
393 | },
|
394 | ],
|
395 | },
|
396 | },
|
397 | },
|
398 | ],
|
399 | },
|
400 | };
|
401 | ```
|
402 |
|
403 | #### `urlFilter`
|
404 |
|
405 | Type:
|
406 |
|
407 | ```ts
|
408 | type urlFilter = (
|
409 | attribute: string,
|
410 | value: string,
|
411 | resourcePath: string
|
412 | ) => boolean;
|
413 | ```
|
414 |
|
415 | Default: `undefined`
|
416 |
|
417 | Allow to filter urls. All filtered urls will not be resolved (left in the code as they were written).
|
418 | All non requestable sources (for example `<img src="javascript:void(0)">`) do not handle by default.
|
419 |
|
420 | ```js
|
421 | module.exports = {
|
422 | module: {
|
423 | rules: [
|
424 | {
|
425 | test: /\.html$/i,
|
426 | loader: "html-loader",
|
427 | options: {
|
428 | sources: {
|
429 | urlFilter: (attribute, value, resourcePath) => {
|
430 | // The `attribute` argument contains a name of the HTML attribute.
|
431 | // The `value` argument contains a value of the HTML attribute.
|
432 | // The `resourcePath` argument contains a path to the loaded HTML file.
|
433 |
|
434 | if (/example\.pdf$/.test(value)) {
|
435 | return false;
|
436 | }
|
437 |
|
438 | return true;
|
439 | },
|
440 | },
|
441 | },
|
442 | },
|
443 | ],
|
444 | },
|
445 | };
|
446 | ```
|
447 |
|
448 | ### `preprocessor`
|
449 |
|
450 | Type:
|
451 |
|
452 | ```ts
|
453 | type preprocessor = (
|
454 | content: string | Buffer,
|
455 | loaderContext: LoaderContext
|
456 | ) => HTMLElement;
|
457 | ```
|
458 |
|
459 | Default: `undefined`
|
460 |
|
461 | Allows pre-processing of content before handling.
|
462 |
|
463 | > ⚠ You should always return valid HTML
|
464 |
|
465 | **file.hbs**
|
466 |
|
467 | ```hbs
|
468 | <div>
|
469 | <p>{{firstname}} {{lastname}}</p>
|
470 | <img src="image.png" alt="alt" />
|
471 | <div>
|
472 | ```
|
473 |
|
474 | #### `function`
|
475 |
|
476 | You can set the `preprocessor` option as a `function` instance.
|
477 |
|
478 | **webpack.config.js**
|
479 |
|
480 | ```js
|
481 | const Handlebars = require("handlebars");
|
482 |
|
483 | module.exports = {
|
484 | module: {
|
485 | rules: [
|
486 | {
|
487 | test: /\.hbs$/i,
|
488 | loader: "html-loader",
|
489 | options: {
|
490 | preprocessor: (content, loaderContext) => {
|
491 | let result;
|
492 |
|
493 | try {
|
494 | result = Handlebars.compile(content)({
|
495 | firstname: "Value",
|
496 | lastname: "OtherValue",
|
497 | });
|
498 | } catch (error) {
|
499 | loaderContext.emitError(error);
|
500 |
|
501 | return content;
|
502 | }
|
503 |
|
504 | return result;
|
505 | },
|
506 | },
|
507 | },
|
508 | ],
|
509 | },
|
510 | };
|
511 | ```
|
512 |
|
513 | You can also set the `preprocessor` option as an asynchronous function instance.
|
514 |
|
515 | For example:
|
516 |
|
517 | **webpack.config.js**
|
518 |
|
519 | ```js
|
520 | const Handlebars = require("handlebars");
|
521 |
|
522 | module.exports = {
|
523 | module: {
|
524 | rules: [
|
525 | {
|
526 | test: /\.hbs$/i,
|
527 | loader: "html-loader",
|
528 | options: {
|
529 | preprocessor: async (content, loaderContext) => {
|
530 | let result;
|
531 |
|
532 | try {
|
533 | result = await Handlebars.compile(content)({
|
534 | firstname: "Value",
|
535 | lastname: "OtherValue",
|
536 | });
|
537 | } catch (error) {
|
538 | await loaderContext.emitError(error);
|
539 |
|
540 | return content;
|
541 | }
|
542 |
|
543 | return result;
|
544 | },
|
545 | },
|
546 | },
|
547 | ],
|
548 | },
|
549 | };
|
550 | ```
|
551 |
|
552 | ### `minimize`
|
553 |
|
554 | Type:
|
555 |
|
556 | ```ts
|
557 | type minimize =
|
558 | | boolean
|
559 | | {
|
560 | caseSensitive?: boolean;
|
561 | collapseWhitespace?: boolean;
|
562 | conservativeCollapse?: boolean;
|
563 | keepClosingSlash?: boolean;
|
564 | minifyCSS?: boolean;
|
565 | minifyJS?: boolean;
|
566 | removeComments?: boolean;
|
567 | removeRedundantAttributes?: boolean;
|
568 | removeScriptTypeAttributes?: boolean;
|
569 | removeStyleLinkTypeAttributes?: boolean;
|
570 | };
|
571 | ```
|
572 |
|
573 | Default: `true` in production mode, otherwise `false`
|
574 |
|
575 | Tell `html-loader` to minimize HTML.
|
576 |
|
577 | #### `boolean`
|
578 |
|
579 | The enabled rules for minimizing by default are the following ones:
|
580 |
|
581 | ```js
|
582 | ({
|
583 | caseSensitive: true,
|
584 | collapseWhitespace: true,
|
585 | conservativeCollapse: true,
|
586 | keepClosingSlash: true,
|
587 | minifyCSS: true,
|
588 | minifyJS: true,
|
589 | removeComments: true,
|
590 | removeRedundantAttributes: true,
|
591 | removeScriptTypeAttributes: true,
|
592 | removeStyleLinkTypeAttributes: true,
|
593 | });
|
594 | ```
|
595 |
|
596 | **webpack.config.js**
|
597 |
|
598 | ```js
|
599 | module.exports = {
|
600 | module: {
|
601 | rules: [
|
602 | {
|
603 | test: /\.html$/i,
|
604 | loader: "html-loader",
|
605 | options: {
|
606 | minimize: true,
|
607 | },
|
608 | },
|
609 | ],
|
610 | },
|
611 | };
|
612 | ```
|
613 |
|
614 | #### `object`
|
615 |
|
616 | **webpack.config.js**
|
617 |
|
618 | See [html-minifier-terser](https://github.com/DanielRuf/html-minifier-terser)'s documentation for more information on the available options.
|
619 |
|
620 | The default rules can be overridden using the following options in your `webpack.conf.js`
|
621 |
|
622 | **webpack.config.js**
|
623 |
|
624 | ```js
|
625 | module.exports = {
|
626 | module: {
|
627 | rules: [
|
628 | {
|
629 | test: /\.html$/i,
|
630 | loader: "html-loader",
|
631 | options: {
|
632 | minimize: {
|
633 | removeComments: false,
|
634 | collapseWhitespace: false,
|
635 | },
|
636 | },
|
637 | },
|
638 | ],
|
639 | },
|
640 | };
|
641 | ```
|
642 |
|
643 | The default rules can be extended:
|
644 |
|
645 | **webpack.config.js**
|
646 |
|
647 | ```js
|
648 | const { defaultMinimizerOptions } = require("html-loader");
|
649 |
|
650 | module.exports = {
|
651 | module: {
|
652 | rules: [
|
653 | {
|
654 | test: /\.html$/i,
|
655 | loader: "html-loader",
|
656 | options: {
|
657 | minimize: {
|
658 | ...defaultMinimizerOptions,
|
659 | removeComments: false,
|
660 | collapseWhitespace: false,
|
661 | },
|
662 | },
|
663 | },
|
664 | ],
|
665 | },
|
666 | };
|
667 | ```
|
668 |
|
669 | ### `esModule`
|
670 |
|
671 | Type:
|
672 |
|
673 | ```ts
|
674 | type esModule = boolean;
|
675 | ```
|
676 |
|
677 | Default: `true`
|
678 |
|
679 | By default, `html-loader` generates JS modules that use the ES modules syntax.
|
680 | There are some cases in which using ES modules is beneficial, like in the case of [module concatenation](https://webpack.js.org/plugins/module-concatenation-plugin/) and [tree shaking](https://webpack.js.org/guides/tree-shaking/).
|
681 |
|
682 | You can enable a CommonJS modules syntax using:
|
683 |
|
684 | **webpack.config.js**
|
685 |
|
686 | ```js
|
687 | module.exports = {
|
688 | module: {
|
689 | rules: [
|
690 | {
|
691 | test: /\.html$/i,
|
692 | loader: "html-loader",
|
693 | options: {
|
694 | esModule: false,
|
695 | },
|
696 | },
|
697 | ],
|
698 | },
|
699 | };
|
700 | ```
|
701 |
|
702 | ## Examples
|
703 |
|
704 | ### Disable url resolving using the `<!-- webpackIgnore: true -->` comment
|
705 |
|
706 | With `<!-- webpackIgnore: true -->` comment, can to disable sources handling for next tag.
|
707 |
|
708 | ```html
|
709 | <!-- Disabled url handling for the src attribute -->
|
710 | <!-- webpackIgnore: true -->
|
711 | <img src="image.png" />
|
712 |
|
713 | <!-- Disabled url handling for the src and srcset attributes -->
|
714 | <!-- webpackIgnore: true -->
|
715 | <img
|
716 | srcset="image.png 480w, image.png 768w"
|
717 | src="image.png"
|
718 | alt="Elva dressed as a fairy"
|
719 | />
|
720 |
|
721 | <!-- Disabled url handling for the content attribute -->
|
722 | <!-- webpackIgnore: true -->
|
723 | <meta itemprop="image" content="./image.png" />
|
724 |
|
725 | <!-- Disabled url handling for the href attribute -->
|
726 | <!-- webpackIgnore: true -->
|
727 | <link rel="icon" type="image/png" sizes="192x192" href="./image.png" />
|
728 | ```
|
729 |
|
730 | ### roots
|
731 |
|
732 | With [`resolve.roots`](https://webpack.js.org/configuration/resolve/#resolveroots) can specify a list of directories where requests of server-relative URLs (starting with '/') are resolved.
|
733 |
|
734 | **webpack.config.js**
|
735 |
|
736 | ```js
|
737 | module.exports = {
|
738 | context: __dirname,
|
739 | module: {
|
740 | rules: [
|
741 | {
|
742 | test: /\.html$/i,
|
743 | loader: "html-loader",
|
744 | options: {},
|
745 | },
|
746 | {
|
747 | test: /\.jpg$/,
|
748 | type: "asset/resource",
|
749 | },
|
750 | ],
|
751 | },
|
752 | resolve: {
|
753 | roots: [path.resolve(__dirname, "fixtures")],
|
754 | },
|
755 | };
|
756 | ```
|
757 |
|
758 | **file.html**
|
759 |
|
760 | ```html
|
761 | <img src="/image.jpg" />
|
762 | ```
|
763 |
|
764 | ```js
|
765 | // => image.jpg in __dirname/fixtures will be resolved
|
766 | ```
|
767 |
|
768 | ### CDN
|
769 |
|
770 | **webpack.config.js**
|
771 |
|
772 | ```js
|
773 | module.exports = {
|
774 | module: {
|
775 | rules: [
|
776 | {
|
777 | test: /\.jpg$/,
|
778 | type: "asset/resource",
|
779 | },
|
780 | {
|
781 | test: /\.png$/,
|
782 | type: "asset/inline",
|
783 | },
|
784 | ],
|
785 | },
|
786 | output: {
|
787 | publicPath: "http://cdn.example.com/[fullhash]/",
|
788 | },
|
789 | };
|
790 | ```
|
791 |
|
792 | **file.html**
|
793 |
|
794 | ```html
|
795 | <img src="image.jpg" data-src="image2x.png" />
|
796 | ```
|
797 |
|
798 | **index.js**
|
799 |
|
800 | ```js
|
801 | require("html-loader!./file.html");
|
802 |
|
803 | // => '<img src="http://cdn.example.com/49eba9f/a992ca.jpg" data-src="image2x.png">'
|
804 | ```
|
805 |
|
806 | ```js
|
807 | require('html-loader?{"sources":{"list":[{"tag":"img","attribute":"data-src","type":"src"}]}}!./file.html');
|
808 |
|
809 | // => '<img src="image.jpg" data-src="data:image/png;base64,..." >'
|
810 | ```
|
811 |
|
812 | ```js
|
813 | require('html-loader?{"sources":{"list":[{"tag":"img","attribute":"src","type":"src"},{"tag":"img","attribute":"data-src","type":"src"}]}}!./file.html');
|
814 |
|
815 | // => '<img src="http://cdn.example.com/49eba9f/a992ca.jpg" data-src="data:image/png;base64,..." >'
|
816 | ```
|
817 |
|
818 | ### Process `script` and `link` tags
|
819 |
|
820 | **script.file.js**
|
821 |
|
822 | ```js
|
823 | console.log(document);
|
824 | ```
|
825 |
|
826 | **style.file.css**
|
827 |
|
828 | ```css
|
829 | a {
|
830 | color: red;
|
831 | }
|
832 | ```
|
833 |
|
834 | **file.html**
|
835 |
|
836 | ```html
|
837 | <!DOCTYPE html>
|
838 | <html>
|
839 | <head>
|
840 | <meta charset="UTF-8" />
|
841 | <title>Title of the document</title>
|
842 | <link rel="stylesheet" type="text/css" href="./style.file.css" />
|
843 | </head>
|
844 | <body>
|
845 | Content of the document......
|
846 | <script src="./script.file.js"></script>
|
847 | </body>
|
848 | </html>
|
849 | ```
|
850 |
|
851 | **webpack.config.js**
|
852 |
|
853 | ```js
|
854 | module.exports = {
|
855 | module: {
|
856 | rules: [
|
857 | {
|
858 | test: /\.html$/,
|
859 | type: "asset/resource",
|
860 | generator: {
|
861 | filename: "[name][ext]",
|
862 | },
|
863 | },
|
864 | {
|
865 | test: /\.html$/i,
|
866 | use: ["html-loader"],
|
867 | },
|
868 | {
|
869 | test: /\.js$/i,
|
870 | exclude: /\.file.js$/i,
|
871 | loader: "babel-loader",
|
872 | },
|
873 | {
|
874 | test: /\.file.js$/i,
|
875 | type: "asset/resource",
|
876 | },
|
877 | {
|
878 | test: /\.css$/i,
|
879 | exclude: /\.file.css$/i,
|
880 | loader: "css-loader",
|
881 | },
|
882 | {
|
883 | test: /\.file.css$/i,
|
884 | type: "asset/resource",
|
885 | },
|
886 | ],
|
887 | },
|
888 | };
|
889 | ```
|
890 |
|
891 | ### Templating
|
892 |
|
893 | You can use any template system. Below is an example for [handlebars](https://handlebarsjs.com/).
|
894 |
|
895 | **file.hbs**
|
896 |
|
897 | ```hbs
|
898 | <div>
|
899 | <p>{{firstname}} {{lastname}}</p>
|
900 | <img src="image.png" alt="alt" />
|
901 | <div>
|
902 | ```
|
903 |
|
904 | **webpack.config.js**
|
905 |
|
906 | ```js
|
907 | const Handlebars = require("handlebars");
|
908 |
|
909 | module.exports = {
|
910 | module: {
|
911 | rules: [
|
912 | {
|
913 | test: /\.hbs$/i,
|
914 | loader: "html-loader",
|
915 | options: {
|
916 | preprocessor: (content, loaderContext) => {
|
917 | let result;
|
918 |
|
919 | try {
|
920 | result = Handlebars.compile(content)({
|
921 | firstname: "Value",
|
922 | lastname: "OtherValue",
|
923 | });
|
924 | } catch (error) {
|
925 | loaderContext.emitError(error);
|
926 |
|
927 | return content;
|
928 | }
|
929 |
|
930 | return result;
|
931 | },
|
932 | },
|
933 | },
|
934 | ],
|
935 | },
|
936 | };
|
937 | ```
|
938 |
|
939 | ### PostHTML
|
940 |
|
941 | You can use [PostHTML](https://github.com/posthtml/posthtml) without any additional loaders.
|
942 |
|
943 | **file.html**
|
944 |
|
945 | ```html
|
946 | <img src="image.jpg" />
|
947 | ```
|
948 |
|
949 | **webpack.config.js**
|
950 |
|
951 | ```js
|
952 | const posthtml = require("posthtml");
|
953 | const posthtmlWebp = require("posthtml-webp");
|
954 |
|
955 | module.exports = {
|
956 | module: {
|
957 | rules: [
|
958 | {
|
959 | test: /\.hbs$/i,
|
960 | loader: "html-loader",
|
961 | options: {
|
962 | preprocessor: (content, loaderContext) => {
|
963 | let result;
|
964 |
|
965 | try {
|
966 | result = posthtml().use(plugin).process(content, { sync: true });
|
967 | } catch (error) {
|
968 | loaderContext.emitError(error);
|
969 |
|
970 | return content;
|
971 | }
|
972 |
|
973 | return result.html;
|
974 | },
|
975 | },
|
976 | },
|
977 | ],
|
978 | },
|
979 | };
|
980 | ```
|
981 |
|
982 | ### Export into HTML files
|
983 |
|
984 | A very common scenario is exporting the HTML into their own _.html_ file, to
|
985 | serve them directly instead of injecting with javascript. This can be achieved
|
986 | with a combination of 2 loaders:
|
987 |
|
988 | - [extract-loader](https://github.com/peerigon/extract-loader)
|
989 | - html-loader
|
990 |
|
991 | and [`asset modules`](https://webpack.js.org/guides/asset-modules/)
|
992 |
|
993 | The html-loader will parse the URLs, require the images and everything you
|
994 | expect. The extract loader will parse the javascript back into a proper html
|
995 | file, ensuring images are required and point to proper path, and the [`asset modules`](https://webpack.js.org/guides/asset-modules/)
|
996 | will write the _.html_ file for you. Example:
|
997 |
|
998 | **webpack.config.js**
|
999 |
|
1000 | ```js
|
1001 | module.exports = {
|
1002 | output: {
|
1003 | assetModuleFilename: "[name][ext]",
|
1004 | },
|
1005 | module: {
|
1006 | rules: [
|
1007 | {
|
1008 | test: /\.html$/,
|
1009 | type: "asset/resource",
|
1010 | generator: {
|
1011 | filename: "[name][ext]",
|
1012 | },
|
1013 | },
|
1014 | {
|
1015 | test: /\.html$/i,
|
1016 | use: ["html-loader"],
|
1017 | },
|
1018 | ],
|
1019 | },
|
1020 | };
|
1021 | ```
|
1022 |
|
1023 | ## Contributing
|
1024 |
|
1025 | Please take a moment to read our contributing guidelines if you haven't yet done so.
|
1026 |
|
1027 | [CONTRIBUTING](./.github/CONTRIBUTING.md)
|
1028 |
|
1029 | ## License
|
1030 |
|
1031 | [MIT](./LICENSE)
|
1032 |
|
1033 | [npm]: https://img.shields.io/npm/v/html-loader.svg
|
1034 | [npm-url]: https://npmjs.com/package/html-loader
|
1035 | [node]: https://img.shields.io/node/v/html-loader.svg
|
1036 | [node-url]: https://nodejs.org
|
1037 | [tests]: https://github.com/webpack-contrib/html-loader/workflows/html-loader/badge.svg
|
1038 | [tests-url]: https://github.com/webpack-contrib/html-loader/actions
|
1039 | [cover]: https://codecov.io/gh/webpack-contrib/html-loader/branch/master/graph/badge.svg
|
1040 | [cover-url]: https://codecov.io/gh/webpack-contrib/html-loader
|
1041 | [chat]: https://img.shields.io/badge/gitter-webpack%2Fwebpack-brightgreen.svg
|
1042 | [chat-url]: https://gitter.im/webpack/webpack
|
1043 | [size]: https://packagephobia.now.sh/badge?p=html-loader
|
1044 | [size-url]: https://packagephobia.now.sh/result?p=html-loader
|