UNPKG

23.6 kBMarkdownView Raw
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
17Exports HTML as string. HTML is minimized when the compiler demands.
18
19## Getting Started
20
21To begin, you'll need to install `html-loader`:
22
23```console
24npm install --save-dev html-loader
25```
26
27or
28
29```console
30yarn add -D html-loader
31```
32
33or
34
35```console
36pnpm add -D html-loader
37```
38
39Then add the plugin to your `webpack` config. For example:
40
41**file.js**
42
43```js
44import html from "./file.html";
45```
46
47**webpack.config.js**
48
49```js
50module.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
71Type:
72
73```ts
74type 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
96Default: `true`
97
98By default every loadable attributes (for example - `<img src="image.png">`) is imported (`const img = require('./image.png')` or `import img from "./image.png""`).
99You may need to specify loaders for images in your configuration (recommended [`asset modules`](https://webpack.js.org/guides/asset-modules/)).
100
101Supported 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
128The `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
133module.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
151Allows you to specify which tags and attributes to process, filter them, filter urls and process sources starts with `/`.
152
153For example:
154
155**webpack.config.js**
156
157```js
158module.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
201Type:
202
203```ts
204type 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
217Default: [supported tags and attributes](#sources).
218
219Allows to setup which tags and attributes to process and how, and the ability to filter some of them.
220
221Using `...` syntax allows you to extend [default supported tags and attributes](#sources).
222
223For example:
224
225**webpack.config.js**
226
227```js
228module.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
290If 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
294For example:
295
296**webpack.config.js**
297
298```js
299module.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
333Filter can also be used to extend the supported elements and attributes.
334
335For example, filter can help process meta tags that reference assets:
336
337```js
338module.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
373Filter can be used to disable default sources.
374
375For example:
376
377```js
378module.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
405Type:
406
407```ts
408type urlFilter = (
409 attribute: string,
410 value: string,
411 resourcePath: string
412) => boolean;
413```
414
415Default: `undefined`
416
417Allow to filter urls. All filtered urls will not be resolved (left in the code as they were written).
418All non requestable sources (for example `<img src="javascript:void(0)">`) do not handle by default.
419
420```js
421module.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
450Type:
451
452```ts
453type preprocessor = (
454 content: string | Buffer,
455 loaderContext: LoaderContext
456) => HTMLElement;
457```
458
459Default: `undefined`
460
461Allows 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
476You can set the `preprocessor` option as a `function` instance.
477
478**webpack.config.js**
479
480```js
481const Handlebars = require("handlebars");
482
483module.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
513You can also set the `preprocessor` option as an asynchronous function instance.
514
515For example:
516
517**webpack.config.js**
518
519```js
520const Handlebars = require("handlebars");
521
522module.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
554Type:
555
556```ts
557type 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
573Default: `true` in production mode, otherwise `false`
574
575Tell `html-loader` to minimize HTML.
576
577#### `boolean`
578
579The 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
599module.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
618See [html-minifier-terser](https://github.com/DanielRuf/html-minifier-terser)'s documentation for more information on the available options.
619
620The default rules can be overridden using the following options in your `webpack.conf.js`
621
622**webpack.config.js**
623
624```js
625module.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
643The default rules can be extended:
644
645**webpack.config.js**
646
647```js
648const { defaultMinimizerOptions } = require("html-loader");
649
650module.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
671Type:
672
673```ts
674type esModule = boolean;
675```
676
677Default: `true`
678
679By default, `html-loader` generates JS modules that use the ES modules syntax.
680There 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
682You can enable a CommonJS modules syntax using:
683
684**webpack.config.js**
685
686```js
687module.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
706With `<!-- 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
732With [`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
737module.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
773module.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
801require("html-loader!./file.html");
802
803// => '<img src="http://cdn.example.com/49eba9f/a992ca.jpg" data-src="image2x.png">'
804```
805
806```js
807require('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
813require('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
823console.log(document);
824```
825
826**style.file.css**
827
828```css
829a {
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
854module.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
893You 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
907const Handlebars = require("handlebars");
908
909module.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
941You 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
952const posthtml = require("posthtml");
953const posthtmlWebp = require("posthtml-webp");
954
955module.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
984A very common scenario is exporting the HTML into their own _.html_ file, to
985serve them directly instead of injecting with javascript. This can be achieved
986with a combination of 2 loaders:
987
988- [extract-loader](https://github.com/peerigon/extract-loader)
989- html-loader
990
991and [`asset modules`](https://webpack.js.org/guides/asset-modules/)
992
993The html-loader will parse the URLs, require the images and everything you
994expect. The extract loader will parse the javascript back into a proper html
995file, ensuring images are required and point to proper path, and the [`asset modules`](https://webpack.js.org/guides/asset-modules/)
996will write the _.html_ file for you. Example:
997
998**webpack.config.js**
999
1000```js
1001module.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
1025Please 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