UNPKG

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