UNPKG

21.7 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. For example, filter can help process meta tags that reference assets:
286
287```js
288module.exports = {
289 module: {
290 rules: [
291 {
292 test: /\.html$/i,
293 loader: 'html-loader',
294 options: {
295 sources: {
296 list: [
297 {
298 tag: 'meta',
299 attribute: 'content',
300 type: 'src',
301 filter: (tag, attribute, attributes, resourcePath) => {
302 if (
303 attributes.value === 'og:image' ||
304 attributes.name === 'twitter:image'
305 ) {
306 return true;
307 }
308 return false;
309 },
310 },
311 ],
312 },
313 },
314 },
315 ],
316 },
317};
318```
319
320#### `urlFilter`
321
322Type: `Function`
323Default: `undefined`
324
325Allow to filter urls. All filtered urls will not be resolved (left in the code as they were written).
326All non requestable sources (for example `<img src="javascript:void(0)">`) do not handle by default.
327
328```js
329module.exports = {
330 module: {
331 rules: [
332 {
333 test: /\.html$/i,
334 loader: 'html-loader',
335 options: {
336 sources: {
337 urlFilter: (attribute, value, resourcePath) => {
338 // The `attribute` argument contains a name of the HTML attribute.
339 // The `value` argument contains a value of the HTML attribute.
340 // The `resourcePath` argument contains a path to the loaded HTML file.
341
342 if (/example\.pdf$/.test(value)) {
343 return false;
344 }
345
346 return true;
347 },
348 },
349 },
350 },
351 ],
352 },
353};
354```
355
356### `preprocessor`
357
358Type: `Function`
359Default: `undefined`
360
361Allows pre-processing of content before handling.
362
363> ⚠ You should always return valid HTML
364
365**file.hbs**
366
367```hbs
368<div>
369 <p>{{firstname}} {{lastname}}</p>
370 <img src="image.png" alt="alt" />
371<div>
372```
373
374#### `Function`
375
376You can set the `preprocessor` option as a `Function` instance.
377
378**webpack.config.js**
379
380```js
381const Handlebars = require('handlebars');
382
383module.exports = {
384 module: {
385 rules: [
386 {
387 test: /\.hbs$/i,
388 loader: 'html-loader',
389 options: {
390 preprocessor: (content, loaderContext) => {
391 let result;
392
393 try {
394 result = Handlebars.compile(content)({
395 firstname: 'Value',
396 lastname: 'OtherValue',
397 });
398 } catch (error) {
399 loaderContext.emitError(error);
400
401 return content;
402 }
403
404 return result;
405 },
406 },
407 },
408 ],
409 },
410};
411```
412
413You can also set the `preprocessor` option as an asynchronous function instance.
414
415For example:
416
417**webpack.config.js**
418
419```js
420const Handlebars = require('handlebars');
421
422module.exports = {
423 module: {
424 rules: [
425 {
426 test: /\.hbs$/i,
427 loader: 'html-loader',
428 options: {
429 preprocessor: async (content, loaderContext) => {
430 let result;
431
432 try {
433 result = await Handlebars.compile(content)({
434 firstname: 'Value',
435 lastname: 'OtherValue',
436 });
437 } catch (error) {
438 await loaderContext.emitError(error);
439
440 return content;
441 }
442
443 return result;
444 },
445 },
446 },
447 ],
448 },
449};
450```
451
452### `minimize`
453
454Type: `Boolean|Object`
455Default: `true` in production mode, otherwise `false`
456
457Tell `html-loader` to minimize HTML.
458
459#### `Boolean`
460
461The enabled rules for minimizing by default are the following ones:
462
463```js
464({
465 caseSensitive: true,
466 collapseWhitespace: true,
467 conservativeCollapse: true,
468 keepClosingSlash: true,
469 minifyCSS: true,
470 minifyJS: true,
471 removeComments: true,
472 removeRedundantAttributes: true,
473 removeScriptTypeAttributes: true,
474 removeStyleLinkTypeAttributes: true,
475});
476```
477
478**webpack.config.js**
479
480```js
481module.exports = {
482 module: {
483 rules: [
484 {
485 test: /\.html$/i,
486 loader: 'html-loader',
487 options: {
488 minimize: true,
489 },
490 },
491 ],
492 },
493};
494```
495
496#### `Object`
497
498**webpack.config.js**
499
500See [html-minifier-terser](https://github.com/DanielRuf/html-minifier-terser)'s documentation for more information on the available options.
501
502The rules can be disabled using the following options in your `webpack.conf.js`
503
504**webpack.config.js**
505
506```js
507module.exports = {
508 module: {
509 rules: [
510 {
511 test: /\.html$/i,
512 loader: 'html-loader',
513 options: {
514 minimize: {
515 removeComments: false,
516 collapseWhitespace: false,
517 },
518 },
519 },
520 ],
521 },
522};
523```
524
525### `esModule`
526
527Type: `Boolean`
528Default: `true`
529
530By default, `html-loader` generates JS modules that use the ES modules syntax.
531There 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/).
532
533You can enable a CommonJS modules syntax using:
534
535**webpack.config.js**
536
537```js
538module.exports = {
539 module: {
540 rules: [
541 {
542 test: /\.html$/i,
543 loader: 'html-loader',
544 options: {
545 esModule: false,
546 },
547 },
548 ],
549 },
550};
551```
552
553## Examples
554
555### roots
556
557With [`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.
558
559**webpack.config.js**
560
561```js
562module.exports = {
563 context: __dirname,
564 module: {
565 rules: [
566 {
567 test: /\.html$/i,
568 loader: 'html-loader',
569 options: {},
570 },
571 {
572 test: /\.jpg$/,
573 type: 'asset/resource',
574 },
575 ],
576 },
577 resolve: {
578 roots: [path.resolve(__dirname, 'fixtures')],
579 },
580};
581```
582
583**file.html**
584
585```html
586<img src="/image.jpg" />
587```
588
589```js
590// => image.jpg in __dirname/fixtures will be resolved
591```
592
593### CDN
594
595**webpack.config.js**
596
597```js
598module.exports = {
599 module: {
600 rules: [
601 {
602 test: /\.jpg$/,
603 type: 'asset/resource',
604 },
605 {
606 test: /\.png$/,
607 type: 'asset/inline',
608 },
609 ],
610 },
611 output: {
612 publicPath: 'http://cdn.example.com/[hash]/',
613 },
614};
615```
616
617**file.html**
618
619```html
620<img src="image.jpg" data-src="image2x.png" />
621```
622
623**index.js**
624
625```js
626require('html-loader!./file.html');
627
628// => '<img src="http://cdn.example.com/49eba9f/a992ca.jpg" data-src="image2x.png">'
629```
630
631```js
632require('html-loader?{"sources":{"list":[{"tag":"img","attribute":"data-src","type":"src"}]}}!./file.html');
633
634// => '<img src="image.jpg" data-src="data:image/png;base64,..." >'
635```
636
637```js
638require('html-loader?{"sources":{"list":[{"tag":"img","attribute":"src","type":"src"},{"tag":"img","attribute":"data-src","type":"src"}]}}!./file.html');
639
640// => '<img src="http://cdn.example.com/49eba9f/a992ca.jpg" data-src="data:image/png;base64,..." >'
641```
642
643```js
644require('html-loader?-sources!./file.html');
645
646// => '<img src="image.jpg" data-src="image2x.png" >'
647```
648
649> :warning: `-sources` sets `sources: false`.
650
651### Process `script` and `link` tags
652
653**script.file.js**
654
655```js
656console.log(document);
657```
658
659**style.file.css**
660
661```css
662a {
663 color: red;
664}
665```
666
667**file.html**
668
669```html
670<!DOCTYPE html>
671<html>
672 <head>
673 <meta charset="UTF-8" />
674 <title>Title of the document</title>
675 <link rel="stylesheet" type="text/css" href="./style.file.css" />
676 </head>
677 <body>
678 Content of the document......
679 <script src="./script.file.js"></script>
680 </body>
681</html>
682```
683
684**webpack.config.js**
685
686```js
687module.exports = {
688 module: {
689 rules: [
690 {
691 test: /\.html$/,
692 type: 'asset/resource',
693 generator: {
694 filename: '[name][ext]',
695 },
696 },
697 {
698 test: /\.html$/i,
699 use: ['extract-loader', 'html-loader'],
700 },
701 {
702 test: /\.js$/i,
703 exclude: /\.file.js$/i,
704 loader: 'babel-loader',
705 },
706 {
707 test: /\.file.js$/i,
708 type: 'asset/resource',
709 },
710 {
711 test: /\.css$/i,
712 exclude: /\.file.css$/i,
713 loader: 'css-loader',
714 },
715 {
716 test: /\.file.css$/i,
717 type: 'asset/resource',
718 },
719 ],
720 },
721};
722```
723
724### Templating
725
726You can use any template system. Below is an example for [handlebars](https://handlebarsjs.com/).
727
728**file.hbs**
729
730```hbs
731<div>
732 <p>{{firstname}} {{lastname}}</p>
733 <img src="image.png" alt="alt" />
734<div>
735```
736
737**webpack.config.js**
738
739```js
740const Handlebars = require('handlebars');
741
742module.exports = {
743 module: {
744 rules: [
745 {
746 test: /\.hbs$/i,
747 loader: 'html-loader',
748 options: {
749 preprocessor: (content, loaderContext) => {
750 let result;
751
752 try {
753 result = Handlebars.compile(content)({
754 firstname: 'Value',
755 lastname: 'OtherValue',
756 });
757 } catch (error) {
758 loaderContext.emitError(error);
759
760 return content;
761 }
762
763 return result;
764 },
765 },
766 },
767 ],
768 },
769};
770```
771
772### PostHTML
773
774You can use [PostHTML](https://github.com/posthtml/posthtml) without any additional loaders.
775
776**file.html**
777
778```html
779<img src="image.jpg" />
780```
781
782**webpack.config.js**
783
784```js
785const posthtml = require('posthtml');
786const posthtmlWebp = require('posthtml-webp');
787
788module.exports = {
789 module: {
790 rules: [
791 {
792 test: /\.hbs$/i,
793 loader: 'html-loader',
794 options: {
795 preprocessor: (content, loaderContext) => {
796 let result;
797
798 try {
799 result = posthtml().use(plugin).process(content, { sync: true });
800 } catch (error) {
801 loaderContext.emitError(error);
802
803 return content;
804 }
805
806 return result.html;
807 },
808 },
809 },
810 ],
811 },
812};
813```
814
815### Export into HTML files
816
817A very common scenario is exporting the HTML into their own _.html_ file, to
818serve them directly instead of injecting with javascript. This can be achieved
819with a combination of 2 loaders:
820
821- [extract-loader](https://github.com/peerigon/extract-loader)
822- html-loader
823
824and [`asset modules`](https://webpack.js.org/guides/asset-modules/)
825
826The html-loader will parse the URLs, require the images and everything you
827expect. The extract loader will parse the javascript back into a proper html
828file, ensuring images are required and point to proper path, and the [`asset modules`](https://webpack.js.org/guides/asset-modules/)
829will write the _.html_ file for you. Example:
830
831**webpack.config.js**
832
833```js
834module.exports = {
835 output: {
836 assetModuleFilename: '[name][ext]',
837 },
838 module: {
839 rules: [
840 {
841 test: /\.html$/,
842 type: 'asset/resource',
843 generator: {
844 filename: '[name][ext]',
845 },
846 },
847 {
848 test: /\.html$/i,
849 use: ['extract-loader', 'html-loader'],
850 },
851 ],
852 },
853};
854```
855
856## Contributing
857
858Please take a moment to read our contributing guidelines if you haven't yet done so.
859
860[CONTRIBUTING](./.github/CONTRIBUTING.md)
861
862## License
863
864[MIT](./LICENSE)
865
866[npm]: https://img.shields.io/npm/v/html-loader.svg
867[npm-url]: https://npmjs.com/package/html-loader
868[node]: https://img.shields.io/node/v/html-loader.svg
869[node-url]: https://nodejs.org
870[deps]: https://david-dm.org/webpack-contrib/html-loader.svg
871[deps-url]: https://david-dm.org/webpack-contrib/html-loader
872[tests]: https://github.com/webpack-contrib/html-loader/workflows/html-loader/badge.svg
873[tests-url]: https://github.com/webpack-contrib/html-loader/actions
874[cover]: https://codecov.io/gh/webpack-contrib/html-loader/branch/master/graph/badge.svg
875[cover-url]: https://codecov.io/gh/webpack-contrib/html-loader
876[chat]: https://img.shields.io/badge/gitter-webpack%2Fwebpack-brightgreen.svg
877[chat-url]: https://gitter.im/webpack/webpack
878[size]: https://packagephobia.now.sh/badge?p=html-loader
879[size-url]: https://packagephobia.now.sh/result?p=html-loader