UNPKG

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