UNPKG

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