html-loader webpack
[![npm][npm]][npm-url] [![node][node]][node-url] [![deps][deps]][deps-url] [![tests][tests]][tests-url] [![coverage][cover]][cover-url] [![chat][chat]][chat-url] [![size][size]][size-url] # html-loader Exports HTML as string. HTML is minimized when the compiler demands. ## Getting Started To begin, you'll need to install `html-loader`: ```console npm install --save-dev html-loader ``` Then add the plugin to your `webpack` config. For example: **file.js** ```js import html from './file.html'; ``` **webpack.config.js** ```js module.exports = { module: { rules: [ { test: /\.html$/i, loader: 'html-loader', }, ], }, }; ``` ## Options | Name | Type | Default | Description | | :---------------------------------: | :-----------------: | :------------------------------------------: | :----------------------------------------------- | | **[`attributes`](#attributes)** | `{Boolean\|Object}` | `true` | Enables/Disables attributes handling | | **[`preprocessor`](#preprocessor)** | `{Function}` | `undefined` | Allows pre-processing of content before handling | | **[`minimize`](#minimize)** | `{Boolean\|Object}` | `true` in production mode, otherwise `false` | Tell `html-loader` to minimize HTML | | **[`esModule`](#esmodule)** | `{Boolean}` | `false` | Use ES modules syntax | ### `attributes` Type: `Boolean|Object` Default: `true` By default every loadable attributes (for example - ``) is imported (`const img = require('./image.png')` or `import img from "./image.png""`). You may need to specify loaders for images in your configuration (recommended `file-loader` or `url-loader`). Supported tags and attributes: - the `src` attribute of the `audio` tag - the `src` attribute of the `embed` tag - the `src` attribute of the `img` tag - the `srcset` attribute of the `img` tag - the `src` attribute of the `input` tag - the `href` attribute of the `link` tag (only for stylesheets) - the `data` attribute of the `object` tag - the `src` attribute of the `script` tag - the `href` attribute of the `script` tag - the `xlink:href` attribute of the `script` tag - the `src` attribute of the `source` tag - the `srcset` attribute of the `source` tag - the `src` attribute of the `track` tag - the `poster` attribute of the `video` tag - the `src` attribute of the `video` tag - the `xlink:href` attribute of the `image` tag - the `href` attribute of the `image` tag - the `xlink:href` attribute of the `use` tag - the `href` attribute of the `use` tag #### `Boolean` The `true` value enables processing of all default elements and attributes, the `false` disable processing of all attributes. **webpack.config.js** ```js module.exports = { module: { rules: [ { test: /\.html$/i, loader: 'html-loader', options: { // Disables attributes processing attributes: false, }, }, ], }, }; ``` #### `Object` Allows you to specify which tags and attributes to process, filter them, filter urls and process sources starts with `/`. For example: **webpack.config.js** ```js module.exports = { module: { rules: [ { test: /\.html$/i, loader: 'html-loader', options: { attributes: { list: [ // All default supported tags and attributes '...', { tag: 'img', attribute: 'data-src', type: 'src', }, { tag: 'img', attribute: 'data-srcset', type: 'srcset', }, ], urlFilter: (attribute, value, resourcePath) => { // The `attribute` argument contains a name of the HTML attribute. // The `value` argument contains a value of the HTML attribute. // The `resourcePath` argument contains a path to the loaded HTML file. if (/example\.pdf$/.test(value)) { return false; } return true; }, root: '.', }, }, }, ], }, }; ``` #### `list` Type: `Array` Default: [supported tags and attributes](#attributes). Allows to setup which tags and attributes to process and how, and the ability to filter some of them. Using `...` syntax allows you to extend [default supported tags and attributes](#attributes). For example: **webpack.config.js** ```js module.exports = { module: { rules: [ { test: /\.html$/i, loader: 'html-loader', options: { attributes: { list: [ // All default supported tags and attributes '...', { tag: 'img', attribute: 'data-src', type: 'src', }, { tag: 'img', attribute: 'data-srcset', type: 'srcset', }, { // Tag name tag: 'link', // Attribute name attribute: 'href', // Type of processing, can be `src` or `scrset` type: 'src', // Allow to filter some attributes filter: (tag, attribute, attributes, resourcePath) => { // The `tag` argument contains a name of the HTML tag. // The `attribute` argument contains a name of the HTML attribute. // The `attributes` argument contains all attributes of the tag. // The `resourcePath` argument contains a path to the loaded HTML file. if (/my-html\.html$/.test(resourcePath)) { return false; } if (!/stylesheet/i.test(attributes.rel)) { return false; } if ( attributes.type && attributes.type.trim().toLowerCase() !== 'text/css' ) { return false; } return true; }, }, ], }, }, }, ], }, }; ``` If the tag name is not specified it will process all the tags. > You can use your custom filter to specify html elements to be processed. For example: **webpack.config.js** ```js module.exports = { module: { rules: [ { test: /\.html$/i, loader: 'html-loader', options: { attributes: { list: [ { // Attribute name attribute: 'src', // Type of processing, can be `src` or `scrset` type: 'src', // Allow to filter some attributes (optional) filter: (tag, attribute, attributes, resourcePath) => { // The `tag` argument contains a name of the HTML tag. // The `attribute` argument contains a name of the HTML attribute. // The `attributes` argument contains all attributes of the tag. // The `resourcePath` argument contains a path to the loaded HTML file. // choose all HTML tags except img tag return tag.toLowerCase() !== 'img'; }, }, ], }, }, }, ], }, }; ``` #### `urlFilter` Type: `Function` Default: `undefined` Allow to filter urls. All filtered urls will not be resolved (left in the code as they were written). All non requestable sources (for example ``) do not handle by default. ```js module.exports = { module: { rules: [ { test: /\.html$/i, loader: 'html-loader', options: { attributes: { urlFilter: (attribute, value, resourcePath) => { // The `attribute` argument contains a name of the HTML attribute. // The `value` argument contains a value of the HTML attribute. // The `resourcePath` argument contains a path to the loaded HTML file. if (/example\.pdf$/.test(value)) { return false; } return true; }, }, }, }, ], }, }; ``` #### `root` Type: `String` Default: `undefined` For urls that start with a `/`, the default behavior is to not translate them. If a `root` query parameter is set, however, it will be prepended to the url and then translated. **webpack.config.js** ```js module.exports = { module: { rules: [ { test: /\.html$/i, loader: 'html-loader', options: { attributes: { root: '.', }, }, }, ], }, }; ``` ### `preprocessor` Type: `Function` Default: `undefined` Allows pre-processing of content before handling. > ⚠ You should always return valid HTML **file.hbs** ```hbs

{{firstname}} {{lastname}}

alt
``` #### `Function` You can set the `preprocessor` option as a `Function` instance. **webpack.config.js** ```js const Handlebars = require('handlebars'); module.exports = { module: { rules: [ { test: /\.hbs$/i, loader: 'html-loader', options: { preprocessor: (content, loaderContext) => { let result; try { result = Handlebars.compile(content)({ firstname: 'Value', lastname: 'OtherValue', }); } catch (error) { loaderContext.emitError(error); return content; } return result; }, }, }, ], }, }; ``` You can also set the `preprocessor` option as an asynchronous function instance. For example: **webpack.config.js** ```js const Handlebars = require('handlebars'); module.exports = { module: { rules: [ { test: /\.hbs$/i, loader: 'html-loader', options: { preprocessor: async (content, loaderContext) => { let result; try { result = await Handlebars.compile(content)({ firstname: 'Value', lastname: 'OtherValue', }); } catch (error) { await loaderContext.emitError(error); return content; } return result; }, }, }, ], }, }; ``` ### `minimize` Type: `Boolean|Object` Default: `true` in production mode, otherwise `false` Tell `html-loader` to minimize HTML. #### `Boolean` The enabled rules for minimizing by default are the following ones: ```js ({ caseSensitive: true, collapseWhitespace: true, conservativeCollapse: true, keepClosingSlash: true, minifyCSS: true, minifyJS: true, removeComments: true, removeRedundantAttributes: true, removeScriptTypeAttributes: true, removeStyleLinkTypeAttributes: true, }); ``` **webpack.config.js** ```js module.exports = { module: { rules: [ { test: /\.html$/i, loader: 'html-loader', options: { minimize: true, }, }, ], }, }; ``` #### `Object` **webpack.config.js** See [html-minifier-terser](https://github.com/DanielRuf/html-minifier-terser)'s documentation for more information on the available options. The rules can be disabled using the following options in your `webpack.conf.js` **webpack.config.js** ```js module.exports = { module: { rules: [ { test: /\.html$/i, loader: 'html-loader', options: { minimize: { removeComments: false, collapseWhitespace: false, }, }, }, ], }, }; ``` ### `esModule` Type: `Boolean` Default: `false` By default, `html-loader` generates JS modules that use the CommonJS modules syntax. There 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/). You can enable a ES module syntax using: **webpack.config.js** ```js module.exports = { module: { rules: [ { test: /\.html$/i, loader: 'html-loader', options: { esModule: true, }, }, ], }, }; ``` ## Examples ### CDN **webpack.config.js** ```js module.exports = { module: { rules: [ { test: /\.jpg$/, loader: 'file-loader' }, { test: /\.png$/, loader: 'url-loader' }, ], }, output: { publicPath: 'http://cdn.example.com/[hash]/', }, }; ``` **file.html** ```html ``` **index.js** ```js require('html-loader!./file.html'); // => '' ``` ```js require('html-loader?{"attributes":{"list":[{"tag":"img","attribute":"data-src","type":"src"}]}}!./file.html'); // => '' ``` ```js require('html-loader?{"attributes":{"list":[{"tag":"img","attribute":"src","type":"src"},{"tag":"img","attribute":"data-src","type":"src"}]}}!./file.html'); // => '' ``` ```js require('html-loader?-attributes!./file.html'); // => '' ``` > :warning: `-attributes` sets `attributes: false`. ### Process `script` and `link` tags **script.file.js** ```js console.log(document); ``` **style.file.css** ```css a { color: red; } ``` **file.html** ```html Title of the document Content of the document...... ``` **webpack.config.js** ```js module.exports = { module: { rules: [ { test: /\.html$/i, use: ['file-loader?name=[name].[ext]', 'extract-loader', 'html-loader'], }, { test: /\.js$/i, exclude: /\.file.js$/i, loader: 'babel-loader', }, { test: /\.file.js$/i, loader: 'file-loader', }, { test: /\.css$/i, exclude: /\.file.css$/i, loader: 'css-loader', }, { test: /\.file.css$/i, loader: 'file-loader', }, ], }, }; ``` ### 'Root-relative' URLs With the same configuration as in the CDN example: **file.html** ```html ``` **scripts.js** ```js require('html-loader!./file.html'); // => '' ``` **other-scripts.js** ```js require('html-loader?{"attributes":{"root":"."}}!./file.html'); // => '' ``` ### Templating You can use any template system. Below is an example for [handlebars](https://handlebarsjs.com/). **file.hbs** ```hbs

{{firstname}} {{lastname}}

alt
``` **webpack.config.js** ```js const Handlebars = require('handlebars'); module.exports = { module: { rules: [ { test: /\.hbs$/i, loader: 'html-loader', options: { preprocessor: (content, loaderContext) => { let result; try { result = Handlebars.compile(content)({ firstname: 'Value', lastname: 'OtherValue', }); } catch (error) { loaderContext.emitError(error); return content; } return result; }, }, }, ], }, }; ``` ### PostHTML You can use [PostHTML](https://github.com/posthtml/posthtml) without any additional loaders. **file.html** ```html ``` **webpack.config.js** ```js const posthtml = require('posthtml'); const posthtmlWebp = require('posthtml-webp'); module.exports = { module: { rules: [ { test: /\.hbs$/i, loader: 'html-loader', options: { preprocessor: (content, loaderContext) => { let result; try { result = posthtml().use(plugin).process(content, { sync: true }); } catch (error) { loaderContext.emitError(error); return content; } return result.html; }, }, }, ], }, }; ``` ### Export into HTML files A very common scenario is exporting the HTML into their own _.html_ file, to serve them directly instead of injecting with javascript. This can be achieved with a combination of 3 loaders: - [file-loader](https://github.com/webpack/file-loader) - [extract-loader](https://github.com/peerigon/extract-loader) - html-loader The html-loader will parse the URLs, require the images and everything you expect. The extract loader will parse the javascript back into a proper html file, ensuring images are required and point to proper path, and the file loader will write the _.html_ file for you. Example: **webpack.config.js** ```js module.exports = { module: { rules: [ { test: /\.html$/i, use: ['file-loader?name=[name].[ext]', 'extract-loader', 'html-loader'], }, ], }, }; ``` ## Contributing Please take a moment to read our contributing guidelines if you haven't yet done so. [CONTRIBUTING](./.github/CONTRIBUTING.md) ## License [MIT](./LICENSE) [npm]: https://img.shields.io/npm/v/html-loader.svg [npm-url]: https://npmjs.com/package/html-loader [node]: https://img.shields.io/node/v/html-loader.svg [node-url]: https://nodejs.org [deps]: https://david-dm.org/webpack-contrib/html-loader.svg [deps-url]: https://david-dm.org/webpack-contrib/html-loader [tests]: https://github.com/webpack-contrib/html-loader/workflows/html-loader/badge.svg [tests-url]: https://github.com/webpack-contrib/html-loader/actions [cover]: https://codecov.io/gh/webpack-contrib/html-loader/branch/master/graph/badge.svg [cover-url]: https://codecov.io/gh/webpack-contrib/html-loader [chat]: https://img.shields.io/badge/gitter-webpack%2Fwebpack-brightgreen.svg [chat-url]: https://gitter.im/webpack/webpack [size]: https://packagephobia.now.sh/badge?p=html-loader [size-url]: https://packagephobia.now.sh/result?p=html-loader