HTML Template

During the build process, Builder will compile based on the HTML template and template parameters to generate several HTML files.

Builder provides some configs to set the HTML template. Through this chapter, you can learn the basic usage of these configs.

Set Template

HTML templates are usually predefined by the upper framework.

For example, in the Modern.js framework, the HTML template is preset by default, and users can also customize the content of the template. You can read the "Modern.js - HTML Template" chapter to learn about it.

In Builder, you can use html.template and html.templateByEntries configs to define the path to the custom HTML template.

export default {
  html: {
    template: './static/index.html',
  },
};

Set Page Title

You can set the HTML <title> tag through the html.title and html.titleByEntries configs.

When there is only one page in your project, just use the html.title setting directly:

export default {
  html: {
    title: 'example',
  },
};

When there are multiple pages in your project, please use html.titleByEntries to set corresponding titles for different pages. html.titleByEntries uses the page's "entry name" as the key.

export default {
  html: {
    titleByEntries: {
      foo: 'Foo',
      bar: 'Bar',
    },
  },
};

Set Page Icon

Builder supports setting favicon icon and apple-touch-icon icon.

You can set the favicon through the html.favicon and html.faviconByEntries configs.

export default {
  html: {
    favicon: './src/assets/icon.png',
  },
};

You can also set the apple-touch-icon for iOS system through the html.appIcon config.

export default {
  html: {
    appIcon: './src/assets/icon.png',
  },
};

Set Meta Tags

You can set the meta tags through the html.meta and html.metaByEntries configs.

For example to setting description:

export default {
  html: {
    meta: {
      description: 'a description of the page',
    },
  },
};

The generated meta tag in HTML is:

<meta name="description" content="a description of the page" />

Set Template Parameters

In HTML templates, you can use a variety of template parameters. The template parameters injected by Builder by default include:

type DefaultParameters = {
  meta: string; // corresponding to html.meta config
  title: string; // corresponding to html.title config
  mountId: string; // corresponding to html.mountId config
  entryName: string; // entry name
  assetPrefix: string; // corresponding to output.assetPrefix config
  compilation: webpack.Compilation; // Compilation object corresponding to webpack
  webpackConfig: config; // webpack config
  // htmlWebpackPlugin built-in parameters
  // See https://github.com/jantimon/html-webpack-plugin for details
  htmlWebpackPlugin: {
    tags: object;
    files: object;
    options: object;
  };
};

You can also use the html.templateParameters and html.templateParametersByEntries configs to pass in custom template parameters.

For example:

export default {
  html: {
    templateParameters: {
      text: 'World',
    },
  },
};

Then you can read parameters in the HTML template with <%= text %>:

<div>hello <%= text %>!</div>

The generated HTML code is as follows:

<div>hello world!</div>

Template Engine

Builder supports using Lodash Template, EJS, Pug as template engines, the most basic Lodash Template is used as the default template engine.

Lodash Template

When the suffix of the template is .html, Builder will use Lodash Template to compile it.

For example, if you define a text parameter in a template with a value of 'world', Builder will automatically replace <%= text %> with the value.

<!-- input -->
<div>hello <%= text %>!</div>

<!-- output -->
<div>hello world!</div>

Please read the Lodash Template documentation for details.

EJS

When the suffix of the template is .ejs, Builder will use the EJS template engine to compile it. EJS is a simple templating language that lets you generate HTML markup with plain JavaScript.

For example, you can first refer to a .ejs template through the html.template config:

export default {
  html: {
    template: './static/index.ejs',
  },
};

Then define a user parameter in the template with a value of { name: 'Jack' }. Builder will automatically replace <%= user.name %> with the value.

<!-- input -->
<% if (user) { %>
<h2><%= user.name %></h2>
<% } %>

<!-- output -->
<h2>Jack</h2>

Please read the EJS documentation for details.

Pug

When the suffix of the template is .pug, Builder will use the Pug template engine to compile it. Pug is a robust, elegant, feature rich template engine for Node.js.

Before using the Pug template, you need to enable the tools.pug config, and define the html.template config to reference a .pug template:

export default {
  html: {
    template: './static/index.pug',
  },
  tools: {
    pug: true,
  },
};

Then you can use Pug syntax in .pug templates:

<!-- input -->
p Hello #{text}!

<!-- output -->
<p>Hello World!</p>

Please read the Pug documentation for details.

Injecting Tags

The html.tags option can be configured to insert any tags into the final generated HTML product.

Usage Cases

The artifacts of the web application will eventually be referenced directly or indirectly by HTML entries, but most of the time injecting tags directly into HTML is not preferred.

All tags that need to be injected into HTML can be accessed in the template file via the variable htmlWebpackPlugin.tags.

<html>
  <head>
    <%= htmlWebpackPlugin.tags.headTags %>
  </head>
  <body>
    <%= htmlWebpackPlugin.tags.bodyTags %>
  </body>
</html>

The purpose of html.tags is to adjust these template variables and thus modify the HTML, as defined in API References.

Tag Object

export default {
  output: {
    assetPrefix: '//example.com/'
  },
  html: {
    tags: [
      { tag: 'script', attrs: { src: 'a.js' } },
      { tag: 'script', attrs: { src: 'b.js' }, append: false },
      { tag: 'link', attrs: { href: 'style.css', rel: 'stylesheet' }, append: true }
      { tag: 'link', attrs: { href: 'page.css', rel: 'stylesheet' }, publicPath: false }
      { tag: 'script', attrs: { src: 'c.js' }, head: false },
      { tag: 'meta', attrs: { name: 'referrer', content: 'origin' } },
    ],
  },
};

The final insertion position of the tag is determined by the head and append options, and two elements with the same configuration will be inserted into the same area and hold their relative positions to each other.

The publicPath configuration is enabled by default for tags, the value of output.assetPrefix will be stitched to the src property of the script tag that represents the path.

So the HTML output built with the above configuration will look like this.

<html>
  <head>
    <script src="//example.com/b.js"></script>
    <link href="//example.com/style.css" rel="stylesheet" />
    <link href="page.css" rel="stylesheet" />
    <!-- some other headTags... -->
    <script src="//example.com/a.js"></script>
    <meta name="referrer" content="origin" />
  </head>
  <body>
    <!-- some other bodyTags... -->
    <script src="//example.com/c.js"></script>
  </body>
</html>

Tags Handler

html.tags also accepts a callback function, which is often used to modify the list of tags or to ensure their relative position while inserting them.

export default {
  html: {
    tags: [
      tags => {
        tags.splice(0, 1);
      },
      { tag: 'script', attrs: { src: 'a.js' }, head: false },
      { tag: 'script', attrs: { src: 'b.js' }, append: false },
      { tag: 'script', attrs: { src: 'c.js' } },
      tags => [...tags, { tag: 'script', attrs: { src: 'd.js' } }],
    ],
  },
};

And you will get:

<html>
  <head>
    <!-- some other headTags... -->
    <script src="//example.com/c.js"></script>
    <script src="//example.com/d.js"></script>
  </head>
  <body>
    <!-- some other bodyTags... -->
    <script src="//example.com/a.js"></script>
  </body>
</html>