Skip to content

Commit

Permalink
docs: refine entries docs (#6505)
Browse files Browse the repository at this point in the history
  • Loading branch information
Asuka109 authored Nov 6, 2024
1 parent 4131423 commit 268d2a4
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 9 deletions.
63 changes: 58 additions & 5 deletions packages/document/main-doc/docs/en/guides/concept/entries.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ In this chapter, you will learn about the entry convention in Modern.js and how

In a Modern.js project, each entry corresponds to an independent page and a server-side route. By default, Modern.js automatically determines the entry of a page based on directory conventions, but also supports customizing the entry through configuration options.

Many configuration options provided by Modern.js are divided by entry, such as page title, HTML template, page meta information, whether to enable SSR/SSG, server-side routing rules, etc.
Many configuration options provided by Modern.js are divided by entry, such as page title, HTML template, page meta information, whether to enable SSR/SSG, server-side routing rules, etc. If you want to learn more about the technical details of entries, please refer to the [In-Depth](#in-depth) section.

## Single Entry and Multiple Entries

Expand Down Expand Up @@ -169,7 +169,7 @@ const ModernRoot = createRoot();
render(<ModernRoot />);
```

In the code above, the component returned by the `createRoot` function is either the component generated from the `routes/` directory or the component exported by `App.tsx`.
In the code above, the component returned by the `createRoot` function is either the component generated from the `routes/` directory or the component exported by `App.tsx`.

The `render` function is used to handle rendering and mounting of the component. For example, if you want to execute some asynchronous tasks before rendering, you can achieve it like this:

Expand Down Expand Up @@ -245,10 +245,63 @@ export default defineConfig({
});
```

It is worth noting that, by default, Modern.js considers entries specified through the configuration as **framework mode entries** and will automatically generate the actual compilation entry.
It is worth noting that, by default, Modern.js considers entries specified through the configuration as **framework mode entries** and will automatically generate the actual compilation entry.

If your application is migrating from build tools like Webpack or Vite to the Modern.js framework, you typically need to enable the `disableMount` option in the entry configuration. In this case, Modern.js will treat the entry as a **build mode entry**.

## In-Depth

The concept of page entry is derived from the concept of [Entrypoint](https://webpack.js.org/concepts/entry-points/) in webpack. It is mainly used to configure the JavaScript or any other modules to be executed during the application startup. Webpack usually corresponds each entry to an HTML file in the output. The modules imported by the entry will be bundled and split into multiple chunks in the output. For a JavaScript module, it might be compiled into several chunks like `dist/static/js/index.ea39u8.js`.

Here's a summary of the differences between the concepts of entry and route:

- **Entry**:Contains multiple modules to be executed during application startup.
- **Client Router**:In Modern.js, it is usually implemented by `react-router`, determining which React component to load and render based on the browser's current URL using the History API.
- **Server Router**:The server can mimic the behavior of [devServer](https://webpack.js.org/configuration/dev-server/#devserverhistoryapifallback), replacing all 404 responses with the index.html page to implement client-side routing, or implement any routing logic as needed.

Their relationships are as follows:

- Each webpack website project can contain multiple entries.
- Each entry contains several modules (source files).
- Each entry usually corresponds to an HTML file in the output.
- Each HTML file can contain multiple client-side routing solutions (for example, using `react-router` and `@tanstack/react-router` in the same page).
- Each HTML file can be mapped to multiple server-side routes.
- Each HTML file can contain multiple client-side routing solutions, and when accessing different routes of a single-entry application, the same HTML file is actually used.

## Troubleshooting

1. **Does each `react-router` defined client route generate a separate HTML file?**

No. Each entry usually only generates one HTML file, and if a single entry contains multiple client routing systems, it will share the same HTML file.

2. **Does the convention routing project in the `routes/` directory generate multiple HTML files?**

No. Modern.js will scan the `routes/` directory during startup and automatically generate client-side routes based on the file conventions. The HTML file generated corresponds to the `routes/` directory.

3. **Does the Server Side Rendering (SSR) project generate multiple HTML files in the output?**

A Server Side Rendering (SSR) project does not necessarily need to generate an HTML file in the output. It can only include the server-side JavaScript output. At this point, the `react-router` routing will be executed on the server side, and the HTML content will be rendered and responded while a request is triggered.

At the same time, Modern.js will also generate a complete client-side HTML file for each entry in the output, which can be used to fallback to client-side rendering when the SSR fails.

Another special case is a Single Entry Static Site Generation (SSG) project, even if it is built with a convention routing, Modern.js will also generate an HTML file for each `page.tsx` file.

Note that even if SSR is used, React still needs to go through the hydration phase, so the routing defined by `react-router` will still be executed on the client side.

4. **What are the exceptions to generating multiple HTML files?**

You can configure [html-rspack-plugin](https://rspack.dev/plugins/rspack/html-rspack-plugin#generate-multiple-html-files) to generate multiple HTML files for each entry, or let multiple entries share the same HTML file.

5. **What is a Multi-Page Application (MPA)?**

The "page" in a Multi-Page Application (MPA) refers to a static HTML file.

Generally, any application that outputs multiple entries and multiple HTML files can be called a Multi-Page Application.

Narrowly speaking, a Multi-Page Application does not contain client-side routing, and navigation between pages is usually achieved through elements like `<a>` tags. But in practice, Multi-Page Applications also often need to configure client-side routing to meet different needs.

Conversely, a application with `react-router` defined routes that generates only one HTML file is called a Single-Page Application (SPA).

## Deprecated

Currently, if the entry directory meets the following conditions, it will also be considered an application entry:
Expand All @@ -262,7 +315,7 @@ The `index.[jt]sx?` file supported **Custom Bootstrap** and **Build Mode Entry**

### Custom Bootstrap

When there is an `index.[jt]sx` file in the entry, and the file's default export is a function, Modern.js will pass the default `bootstrap` function as an argument and use the exported function to replace the default `bootstrap`.
When there is an `index.[jt]sx` file in the entry, and the file's default export is a function, Modern.js will pass the default `bootstrap` function as an argument and use the exported function to replace the default `bootstrap`.

This allows developers to customize mounting components to DOM or add custom behaviors before mounting. For example:

Expand All @@ -277,4 +330,4 @@ export default (App: React.ComponentType, bootstrap: () => void) => {

### Build Mode Entry

When an `index.[jt]sx` file exists in the entry directory and does not export a function via export default, this entry will also be considered a build mode entry.
When an `index.[jt]sx` file exists in the entry directory and does not export a function via export default, this entry will also be considered a build mode entry.
56 changes: 52 additions & 4 deletions packages/document/main-doc/docs/zh/guides/concept/entries.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ sidebar_position: 1

在 Modern.js 应用中,每一个入口对应一个独立的页面,也对应一条服务端路由。默认情况下,Modern.js 会基于目录约定来自动确定页面的入口,同时也支持通过配置项来自定义入口。

Modern.js 提供的很多配置项都是以入口为维度进行划分的,比如页面标题、HTML 模板、页面 Meta 信息、是否开启 SSR/SSG、服务端路由规则等。
Modern.js 提供的很多配置项都是以入口为维度进行划分的,比如页面标题、HTML 模板、页面 Meta 信息、是否开启 SSR/SSG、服务端路由规则等。如果你希望了解更多关于入口的技术细节,请参考[深入了解](#深入了解)章节的内容。

## 单入口与多入口

Expand Down Expand Up @@ -239,6 +239,57 @@ export default defineConfig({
值得注意的是,默认情况下,Modern.js 认为通过配置指定的入口是**框架模式入口**,将自动生成真正的编译入口。如果你的应用是从 Webpack 或 Vite 等构建工具迁移到 Modern.js 框架时,你通常需要在入口配置中开启 `disableMount` 选项,此时 Modern.js 认为该入口是**构建模式入口**


## 深入了解

页面入口的概念衍生自 webpack 的入口(Entrypoint)概念,其主要用于配置 JavaScript 或其他模块在应用启动时加载和执行。webpack 对于网页应用的 [最佳实践](https://webpack.docschina.org/concepts/entry-points/#multi-page-application) 通常将入口与 HTML 产物对应,即每增加一个入口最终就会在产物中生成一份对应的 HTML 文件。入口引入的模块会在编译打包后生成多个 Chunk 产物,例如对于 JavaScript 模块最终可能会生成数个类似 `dist/static/js/index.ea39u8.js` 的文件产物。

需要注意区分入口、路由等概念之间的关系:

- **入口**:包含多个用于启动时执行的模块。
- **客户端路由**:在 Modern.js 中通常由 `react-router` 实现,通过 History API 判断浏览器当前 URL 决定加载和显示哪个 React 组件。
- **服务端路由**:服务端可以模仿 [devServer 的行为](https://webpack.docschina.org/configuration/dev-server/#devserverhistoryapifallback),将 index.html 页面代替所有 404 响应被返回以实现客户端路由,也可以自行实现任何路由逻辑。

它们的对应关系如下:

- 每个 webpack 网站项目可以包含多个入口
- 每个入口包含若干个模块(源码文件)
- 每个入口通常对应一个 HTML 文件产物和若干其它产物。
- 每个 HTML 文件可以包含多个客户端路由方案(比如在页面中同时使用 `react-router``@tanstack/react-router`)。
- 每个 HTML 文件可以被多个服务端路由对应。
- 每个 HTML 文件可以包含多个客户端路由,当访问单入口应用的不同路由时实际使用的是同一个 HTML 文件。

## 常见问题

1. **`react-router` 定义的每个客户端路由会分别生成一个 HTML 文件吗?**

不会。每个入口通常只会生成一个 HTML 文件,单个入口中如果定义多个客户端路由系统会共用这一个 HTML 文件。

2. **约定式路由的 `routes/` 目录下每个 `page.tsx` 文件都会生成一个 HTML 文件吗?**

不是。约定式路由是基于 `react-router` 实现的客户端路由方案,其约定 `routes/` 目录下每个 `page.tsx` 文件都会对应生成一个 `react-router` 的客户端路由。`routes/` 本身作为一个页面入口,对应最终产物中的一个 HTML 文件。

3. **服务端渲染(SSR)的项目是否会构建多份 HTML 产物?**

在使用服务端渲染应用时并不必须在编译时生成一份 HTML 产物,它可以只包含用于渲染的服务端 JavaScript 产物。此时 `react-router` 将在服务端运行和调度路由,并在每次请求时渲染并响应 HTML 内容。

而 Modern.js 在编译时仍会为每个入口生成包含 HTML 文件的完整的客户端产物,用于在服务端渲染失败时降级为客户端渲染使用。

另一个特殊情况是使用静态站点生成(SSG)的项目,即使是使用约定式路由搭建的单入口 SSG 应用,Modern.js 也会在 webpack 的流程外为每个 `page.tsx` 文件生成一份单独的 HTML 文件。

需要注意的是即使开启服务端渲染,React 通常仍需要执行水合阶段并在前端执行 `react-router` 的路由。

4. **单入口应用是否存在输出多个 HTML 文件的例外情况?**

你可以自行配置 [html-rspack-plugin](https://rspack.dev/zh/plugins/rspack/html-rspack-plugin#%E7%94%9F%E6%88%90%E5%A4%9A%E4%B8%AA-html-%E6%96%87%E4%BB%B6) 为每个入口生成多个 HTML 产物,或使多个入口共用一个 HTML 产物。

5. **什么叫多页应用(Multi-Page Application)?**

多页应用的 “页面” 指的是静态的 HTML 文件。
一般可以将任何包含多个入口、多个 HTML 文件产物的网页应用称为多页应用。
狭义的多页应用可能不包含客户端路由、仅通过 `<a>` 之类的标签元素进行 HTML 静态页面之间的跳转,但实践中上多页应用也经常需要为其入口配置客户端路由以满足不同需求。

相反地,通过 `react-router` 定义多个路由的单入口应用因为只生成一个 HTML 文件产物,所以被称为单页应用(Single Page Application)。

## 弃用功能

目前,如果入口所在的目录满足以下条件,也会成为应用入口。
Expand Down Expand Up @@ -267,6 +318,3 @@ export default (App: React.ComponentType, bootstrap: () => void) => {
### 构建模式入口

当入口目录中存在 `index.[jt]sx`(即将废弃) 并且没有通过 `export default` 导出函数时,该入口也将被认为是构建模式入口。



0 comments on commit 268d2a4

Please sign in to comment.