---
title: HTML Template
sidebar_position: 9
---
# HTML Template

Modern.js provides **JSX syntax** and **HTML(EJS) syntax** for customizing HTML template.

## JSX syntax

Modern.js convention, in the `src/`, or in the entry directory, you can create `Document.[jt]sx` and export a component by default. The rendering result of this component can be used as an HTML template for the entry.

For example the following directory structure:

```bash
.
└── src
    ├── Document.tsx
    ├── entry-a
    │   ├── Document.tsx
    │   └── routes
    ├── entry-b
    │    └── routes
    └── modern-app-env.d.ts
```

`entry-a` will take precedence over the `Docoument.[jt]sx` file under the current entry. If the current entry does not have a `Document.[jt]sx` file, such as `entry-b`, it will look for the `Document.[jt]sx` file in the root directory.

If not, it will go to the the logic of traditional templates.

### HTML Component

Modern.js provides a list of components for rendering pages to help developers generate templates, which can be exported from `@modern-js/runtime/document`:

```tsx
import { Html, Body, Root, Head, Scripts } from '@modern-js/runtime/document';
```

These components are rendered:

- `Html`: Provide the ability of native HTML Elements, and render necessary components that the developer did not add by default. `<Head>` and `<Body>` must exist, and other components can be assembled by selecting appropriate components on demand.

- `Body`: Provide the ability of native Body Element, which needs to contain the `<Root>` component internally, and also supports other elements as child elements at the same time, such as adding footers.

- `Root`: React root element `<div id='root'></div>`. the default element id is `id = 'root'`, can set `props.rootId` to change the id.Child components can be added, and will also be rendered into HTML templates, which will be overwritten when React rendering is complete, generally used to implement global Loading.

- `Head`: Provides native Head Element capabilities and automatically populates `<meta>`, as well as the `<Scripts>` component.

- `Scripts`: The script content generated by the webpack, which can be used to adjust the position of the bundle result, is placed in the `<Head>` component by default.

- `Comment`: Make the comment like `<!-- gateway -->`, could be stay to the html that final render.

### Template Params

Because it is in the form of JSX, in `Document.[jt]sx`, you can use various variables in the component to assign values to various custom components more freely.

At the same time, Modern.js provides `DocumentContext` to provide some configuration and environment parameters, The main parameters as follow:

- `processEnv`: Provide build-time env vars.
- `config`: The configuration of the project, only `output` are exposed.
- `entryName`: current entry name.
- `templateParams`: HTML template params(in order to be compatible with traditional templates, it is not recommended to use).

### Examples

```tsx
import React, { useContext } from 'react';
import {
  Html,
  Root,
  Head,
  Body,
  DocumentContext,
  Comment,
} from '@modern-js/runtime/document';

export default function Document(): React.ReactElement {
  // the params provide by DocumentContext
  const {
    config: { output: htmlConfig },
    entryName,
    templateParams,
  } = useContext(DocumentContext);

  return (
    <Html>
      <Head>
        <link href="https://modernjs.dev" />
        <Comment>{'<!-- Need a Comment -->'}</Comment>
      </Head>
      <Body>
        <Root rootId="root">
          <h1 style={{ color: 'red' }}>Some Params: </h1>
          <h2> entryName：{entryName}</h2>
          <h2> title：{htmlConfig.title}</h2>
          <h2> rootId: {templateParams.mountId}</h2>
        </Root>
        <h1>bottom</h1>
      </Body>
    </Html>
  );
}
```

The above JSX component will generate the following HTML template:

```html
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport"
        content="width=device-width, initial-scale=1.0, shrink-to-fit=no, viewport-fit=cover, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta name="renderer" content="webkit">
    <meta name="layoutmode" content="standard">
    <meta name="imagemode" content="force">
    <meta name="wap-font-scale" content="no">
    <meta name="format-detection" content="telephone=no">
    <link rel="icon" href="/a.icon">
    <script defer src="/static/js/builder-runtime.js"></script>
    <script defer src="/static/js/lib-react.js"></script>
    <script defer src="/static/js/lib-polyfill.js"></script>
    <script defer src="/static/js/lib-router.js"></script>

    <script>
      ...
    </script>
    <script defer src="/static/js/sub.js"></script>
    <link href="https://modernjs.dev" />
    <!-- Need a Comment -->
</head>

<body>
    <div id="root">
        <!--<?- html ?>-->
        <h1 style="color:red">Some Params: </h1>
        <h2> entryName：sub</h2>
        <h2> title：</h2>
        <h2> rootId: root</h2>
    </div>
    <h1>bottom</h1>
    <!--<?- chunksMap.js ?>-->
    <!--<?- SSRDataScript ?>-->
</body>

</html>

```

## Html Synxtax

Modern.js also supports HTML syntax. By default, an HTML template is built into the Modern.js application project to generate HTML code.

Based on HTML syntax templates, Modern.js provides **Custom HTML Fragments** and **Fully Custom HTML Templates** two ways to customize templates.

### Custom HTML Fragments

In the application root directory, create the `config/html/` directory, which supports the creation of four kinds of HTML fragments.

- `top.html`
- `head.html`
- `body.html`
- `bottom.html`

**These fragments will be injected into the default HTML template.**

```html
<!DOCTYPE html>
<html>
  <head>
    <%= meta %>
    <title><%= title %></title>
    <%= topTemplate %>
    <%= headTemplate %>
    {/* webpack inject css  */}
  </head>
  <body>
    <noscript>
      We're sorry but react app doesn't work properly without JavaScript
      enabled. Please enable it to continue.
    </noscript>
    <div id="<%= mountId %>"></div>
    <%= bodyTemplate %>
    {/* webpack inject js  */}
    {/* <?- bottomTemplate ?> */}
  </body>
</html>
```

HTML Fragments support the use [Lodash template](https://lodash.com/docs/4.17.15#template).

For example, insert a script in `body.html`:

```html title="config/html/body.html"
<script src="//example.com/assets/a.js"></script>
```

:::info
The implementation of the custom HTML fragment is to merge the fragment with the built-in template of the frame. Since `<title>` already exists in the default template of the frame, the `<title>` in the custom HTML template cannot take effect. Please pass [html.title](/configure/app/html/title) to modify the page title.

:::

### Fully Custom HTML Templates

In some cases, HTML snippets do not meet the customization requirements, Modern.js provide a fully customized way.

:::caution
It is not recommended to override the default HTML template directly, and some features may be lost. Even if it needs to be replaced, it is recommended to build on the built-in template and modify it as needed.

:::

In the `config/html/` directory, create a index.html file that will override the default HTML template.

:::info
The internal default HTML template can be viewed in `node_modules/.modern-js/${entryName}/index.html`.

:::

### Template Params

The parameters used in the template can be defined by the [html.templateParameters](/configure/app/html/template-parameters).

### Config By Entry

The fragment in the `config/html/` directory are valid for all entries in the application. If you want to customize the HTML by entry, you can create a new directory named with the **entry name** in the `config/html/` directory, and then customize the HTML snippets in this directory.

For example, the following HTML fragment is only valid for `entry1`:

```bash
.
├── config/
│   └── html/
│       └── entry1
│           ├── head.html
│           └── body.html
└── src/
    ├── entry1/
    │   └── routes
    └── entry2/
        └── routes
```
