---
sidebar_position: 9
---

# HTML Template

Modern.js provides **JSX syntax** and **HTML(EJS) syntax** to customize the HTML template.

## JSX Syntax

According to Modern.js conventions, you can create a `Document.[jt]sx` file under `src/` or the entry directory and default export a component". The rendering result of this component can be used as the HTML template of the entry.

For example, consider the following directory structure:

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

`entry-a` will use the `Docoument.[jt]sx` file under the current entry as the template. If there is no `Document.[jt]sx` file under the current entry, like `entry-b`, it will look for the `Document.[jt]sx` file under the root directory.

If not found, default template will be used.

### HTML Components

Modern.js provides some components for rendering pages to help developers generate templates. These components can be used from `@modern-js/runtime/document`:

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

- `Html`: provide the ability of native HTML Element and and render necessary components that the developer did not add by default. `<Head>` and `<Body>` must exist, and other components can be assembled as needed.

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

- `Root`: the root node `<div id='root'></div>` to be rendered. The default id of the root node is `id = 'root'`. You can set `props.rootId` to change the id attribute. Child components can be added and will be rendered in the HTML template. After React rendering is complete, it will be overwritten and is generally used to implement global Loading.

- `Head`: provide the ability of native Head Element and automatically fills in `<meta>` and `<Scripts>` components.

- `Scripts`: Used to control the placement of the `<script>` tags generated by the build. By default, they are placed within the `<Head>` component.

- `Comment`: retain user-written comments like `<!-- gateway -->` and outputs them to the rendered HTML.

### Template Parameters

Because it is in JSX format, various variables can be used freely in the component to assign values to various custom components in `Document.[jt]sx`.

Modern.js also provides `DocumentContext` to provide some configuration and environment parameters for easy access. The main parameters are:

- `processEnv`: provides the `process.env` during the build.
- `config`: the configuration of the Modern.js project. Currently, only the output configuration is exposed.
- `entryName`: the current entry name.
- `templateParams`: parameters of HTML template (compatible with traditional templates, so it's not recommended for use).

### Basic Example

```tsx
import React, { useContext } from 'react';
import {
  Html,
  Root,
  Head,
  Body,
  Comment,
  DocumentContext,
} 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 components 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 defer src="/static/js/main.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: main</h2>
      <h2>title：</h2>
      <h2>rootId: root</h2>
    </div>
    <h1>bottom</h1>
    <!--<?- chunksMap.js ?>-->
    <!--<?- SSRDataScript ?>-->
  </body>
</html>
```

### Scripts Component Example

You can use the `<Scripts>` component to insert the `<script>` tags generated by the build inside the `<body>` tag:

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

export default function Document(): React.ReactElement {
  return (
    <Html>
      <Head></Head>
      <Body>
        <Root rootId="root"></Root>
        <Scripts />
      </Body>
    </Html>
  );
}
```

## HTML Syntax

Modern.js also supports generating HTML files using HTML (EJS) syntax.

By default, Modern.js projects come with a built-in HTML template for generating HTML code. If you need to customize the HTML template, you can use two methods: **Custom HTML Fragments** and **Fully Custom HTML Templates**.

### Custom HTML Fragments

Under the application root directory, create the `config/html/` directory, which supports the creation of four types of HTML fragments:

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

**These fragments will be injected into the default HTML template according to their positions.**

```xml
<!DOCTYPE html>
<html>
  <head>
    <%= 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 of [Lodash template](https://lodash.com/docs/4.17.15#template).

For example, to insert an external script in `body.html`:

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

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

:::

### Custom the entire HTML Template

In some cases, HTML fragments may be is not better meet the customization requirements. Modern.js provides a fully customized way.

:::caution Note
It is generally not recommended to directly override the default HTML template, as some functional options may be lost. If it is truly necessary to customize the entire HTML template, it is recommended to modify based on the built-in template as needed.

:::

Under the `config/html/` directory, create an `index.html` file that will replace the default HTML template.

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

:::

### Template Parameters

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

### Config By Entry

The HTML fragments in the `config/html/` directory take effect for all entries in the application. If you want to customize HTML fragments by entry, you can create a directory named after the **entry name** under the `config/html/` directory, and then customize the HTML fragments in this directory.

For example, the following HTML fragments are only effective for the `entry1` entry:

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