From 0624355c70d3386121e39bbad178e52d58a24c58 Mon Sep 17 00:00:00 2001 From: "MR. HASAN" Date: Mon, 4 Sep 2023 01:15:13 +0600 Subject: [PATCH 01/14] Update fast-refresh.md --- docs/docs/fast-refresh.md | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/docs/docs/fast-refresh.md b/docs/docs/fast-refresh.md index 4aa8152fec83..2b3fd551c2d9 100644 --- a/docs/docs/fast-refresh.md +++ b/docs/docs/fast-refresh.md @@ -1,34 +1,30 @@ ---- -translateHelp: true ---- +# Fast Refresh -# 快速刷新(Fast Refresh) +> Fast Refresh is an official React module hot-reloading (HMR) solution developed by React for React Native. Due to its platform-independent core implementation, it is also suitable for the web. -> 快速刷新(Fast Refresh)是 React 官方为 React Native 开发的模块热替换(HMR)方案,由于其核心实现与平台无关,同时也适用于 Web。 +The most significant feature of Fast Refresh is that in a development environment, it can **preserve component state** and provide **instant feedback** when editing. -Fast Refresh 功能最大的特性是:开发环境下,可以**保持组件状态**,同时编辑提供**即时反馈**。 +## How to Use? -## 怎样使用? +Simply add `fastRefresh: {}` to your [configuration file](/docs/config) to enable it. -在[配置文件](/docs/config)加上 `fastRefresh: {}` 即可开启 - -这张 gif 动图展示的是使用 Fast Refresh 特性的开发体验,可以看出,修改组件代码后,用户名和密码**状态保持**,这将提升应用本地研发体验。 +The GIF animation below demonstrates the development experience using the Fast Refresh feature. You can see that after modifying the component code, the username and password **retain their state**, which enhances the local development experience. ![](https://gw.alipayobjects.com/zos/antfincdn/B2biHHW6s%24/fast-refresh.gif) -开发方式上与平时没有区别,正常地修改、保存、预览,只是在效果反馈上,体验更加好。 +In terms of development workflow, there is no difference from usual. You can edit, save, and preview as usual. The only distinction is the improved feedback experience. -## 限制 +## Limitations -有些情况下,维持状态并不是预期,所以为了可靠起见,Fast Refresh 遇到以下情况一概不保留状态(remount): +In some cases, maintaining state may not be the expected behavior. Therefore, to ensure reliability, Fast Refresh does not preserve state (remount) in the following situations: -- Class 类组件一律重刷(remount),状态会被重置,包括高阶组件返回的 Class 组件 -- 不纯组件模块,所编辑的模块除导出 React 组件外,还导出了其它模块 -- 特殊的,还可以通过 `// @refresh reset` 指令(在源码文件中任意位置加上这行注释)强制重刷(remount),最大限度地保证可用性 +- All Class components are remounted, and their state is reset, including Class components returned by higher-order components. +- Modules that are not pure components, meaning the edited module exports things other than React components. +- In special cases, you can also force a remount (maximum availability guarantee) by adding the `// @refresh reset` comment line anywhere in the source code file. -## 技巧 +## Tips -推荐写函数命名组件,例如: +It is recommended to give function components a name, for example: ✅ Good: @@ -44,8 +40,8 @@ export default Foo; export default () => {}; ``` -## FAQ +## Frequently Asked Questions ### TypeError: Cannot read property 'forEach' of undefined -Please check the version of the browser extension React DevTools, whether it is less than v4, and please upgrade to v4 version can be solved.[issue#6432](https://github.com/umijs/umi/issues/6432) +Please check the version of the browser extension React DevTools. If it is below version v4, please upgrade to v4. This should resolve the issue. [issue#6432](https://github.com/umijs/umi/issues/6432) From 2056a904ffa47a95afd73153dccff73194d767d4 Mon Sep 17 00:00:00 2001 From: "MR. HASAN" Date: Mon, 4 Sep 2023 01:17:10 +0600 Subject: [PATCH 02/14] Update assets-image.md --- docs/docs/assets-image.md | 54 ++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 32 deletions(-) diff --git a/docs/docs/assets-image.md b/docs/docs/assets-image.md index 00cd5325e447..79c5fd995e7f 100644 --- a/docs/docs/assets-image.md +++ b/docs/docs/assets-image.md @@ -1,29 +1,22 @@ ---- -translateHelp: true ---- +# Using Images -# Use Image +## Using Images in JavaScript - -## JS 里使用图片 - -通过 require 引用相对路径的图片。 - -比如: +You can reference images with relative paths using `require` in JavaScript. For example: ```js export default () => ``` -支持别名,比如通过 `@` 指向 src 目录: +Aliases are also supported, such as using `@` to point to the `src` directory: ```js export default () => ``` -## JS 里使用svg +## Using SVGs in JavaScript -**组件式引入** +**Component-Based Import** ```js import { ReactComponent as Logo } from './logo.svg' @@ -33,7 +26,7 @@ function Analysis() { } ``` -**url式引入** +**URL-Based Import** ```js import logoSrc from './logo.svg' @@ -43,12 +36,9 @@ function Analysis() { } ``` +## Using Images in CSS -## CSS 里使用图片 - -通过相对路径引用。 - -比如, +You can reference images with relative paths in CSS. For example: ```css .logo { @@ -56,7 +46,7 @@ function Analysis() { } ``` -CSS 里也支持别名,但需要在前面加 `~` 前缀, +Aliases are also supported in CSS, but you need to prefix them with `~`. For example: ```css .logo { @@ -64,26 +54,26 @@ CSS 里也支持别名,但需要在前面加 `~` 前缀, } ``` -注意: +Please note: -1. 这是 webpack 的规则,如果切到其他打包工具,可能会有变化 -2. less 中同样适用 +1. These rules are specific to Webpack. If you switch to another bundling tool, there may be differences. +2. The same rules apply to Less as well. -## 图片路径问题 +## Image Path Considerations -项目中使用图片有两种方式, +There are two ways to use images in your project: -1. 先把图片传到 cdn,然后在 JS 和 CSS 中使用图片的绝对路径 -2. 把图片放在项目里,然后在 JS 和 CSS 中通过相对路径的方式使用 +1. Upload the images to a CDN and then use absolute paths to reference them in your JS and CSS. +2. Place the images in your project and use relative paths in your JS and CSS. -前者不会有任何问题;后者,如果在 JS 中引用相对路径的图片时,在发布时会根据 publicPath 绝对引入路径,所以就算没有开启 dynamicImport 时,也需要注意 publicPath 的正确性。 +The first approach should work without any issues. For the second approach, when referencing images with relative paths in JavaScript, they will be included with absolute paths in the build based on the `publicPath`. So, even if you haven't enabled `dynamicImport`, ensure that the `publicPath` is configured correctly. -## Base64 编译 +## Base64 Encoding -通过相对路径引入图片的时候,如果图片小于 10K,会被编译为 Base64,否则会被构建为独立的图片文件。 +When importing images with relative paths, images smaller than 10KB will be encoded as Base64. Otherwise, they will be built as separate image files. -10K 这个阈值可以通过 [inlineLimit 配置](../config#inlinelimit)修改。 +You can modify the 10KB threshold using the [inlineLimit configuration](../config#inlinelimit). -## 使用 CDN +## Using CDN TODO From 54c24e0ea71cd28047900db78380f3f89ecb283f Mon Sep 17 00:00:00 2001 From: "MR. HASAN" Date: Mon, 4 Sep 2023 01:18:29 +0600 Subject: [PATCH 03/14] Update cli.md --- docs/docs/cli.md | 61 ++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/docs/docs/cli.md b/docs/docs/cli.md index 6bd3e164ec48..84b50c79b5cf 100644 --- a/docs/docs/cli.md +++ b/docs/docs/cli.md @@ -1,13 +1,8 @@ ---- -translateHelp: true ---- - -# Cli Commands - +# CLI Commands ## umi build -编译构建 web 产物。通常需要针对部署环境,做特定的配置和环境变量修改。相关详情,请查阅[部署](./deployment)。 +Compiles and builds web assets. Typically, you need to make specific configurations and environment variable modifications for the deployment environment. For more details, please refer to the [deployment](./deployment) documentation. ```bash $ umi build @@ -21,32 +16,32 @@ Build success. ✨ Done in 9.77s. ``` -默认产物输出到项目的 `dist` 文件夹,你可以通过修改配置 `outputPath` 指定产物输出目录。 -默认编译时会将 `public` 文件夹内的所有文件,原样拷贝到 `dist` 目录,如果你不需要这个特性,可以通过配置 `chainWebpack` 来删除它。 +By default, the build output goes to the `dist` folder in your project. You can specify the output directory by modifying the `outputPath` configuration. + +During compilation, all files within the `public` folder are copied as-is to the `dist` directory. If you don't need this feature, you can remove it by configuring `chainWebpack`: ```js export default { chainWebpack(memo, { env, webpack }) { - // 删除 umi 内置插件 + // Remove the built-in copy plugin memo.plugins.delete('copy'); } } ``` -> 注意:如果 `public` 里面存在产物同名文件,如 `index.html`,将会导致产物文件被覆盖。 +> Note: If there are files with the same name in the `public` folder, like `index.html`, they will overwrite the output files. ## umi dev -启动本地开发服务器进行项目的开发调试 +Starts a local development server for debugging and developing your project. ```bash $ umi dev ``` -启动在浏览器中运行的开发服务器,并监视源文件变化,自动热加载。 +It launches a development server in your browser, watches for source file changes, and provides hot reloading. -默认使用 `8000` 端口,如果 `8000` 端口被占用,将会使用 `8001` 端口,以此类推。 -你可以通过设置环境变量 `PORT` 来指定开发端口号。更多环境变量配置,请查阅[环境变量](/docs/env-variables)。 +By default, it uses port `8000`, and if port `8000` is occupied, it will use `8001`, and so on. You can specify the development port by setting the `PORT` environment variable. For more environment variable configurations, please refer to the [environment variables](/docs/env-variables) documentation. ```bash umi dev @@ -62,19 +57,19 @@ Starting the development server... - Network: http://192.168.50.236:8000 ``` -开启开发服务还会同时提供一个 Network 的链接,你可以在能访问到你当前运行设备的其他设备中预览页面。 +Starting the development server also provides a Network link that allows you to preview the page on other devices that can access the current running device. -> 注意:如果是在开启了VPN,或者虚拟机等复杂的网络环境中,这个地址很可能会错误。你可以通过访问你真实可用 `ip` 的对应端口号来访问开发页面。 +> Note: If you are in a complex network environment with VPN or virtual machines, this address may be incorrect. You can access the development page by using the corresponding port number of your real and available IP. ## umi generate -内置的生成器功能,内置的类型有 `page` ,用于生成最简页面。支持别名调用 `umi g`。 +This command is an embedded generator with the built-in type `page` for generating simple pages. You can also use the alias `umi g`. ```bash $ umi generate [options] ``` -这个命令支持扩展,通过 `api.registerGenerator` 注册,你可以通过插件来实现自己常用的生成器。 +This command can be extended by registering generators with `api.registerGenerator`. You can create your own custom generators using plugins. ```ts import { Generator, IApi } from 'umi'; @@ -100,17 +95,17 @@ umi generate page pageName --typescript umi generate page pageName --less ``` -更多使用类型和参数,请查阅提供生成器扩展的插件的文档。 +For more usage types and options, please refer to the documentation of plugins that provide generator extensions. ## umi plugin -快速查看当前项目使用到的所有的 `umi` 插件。 +Quickly view all `umi` plugins used in the current project. ```bash $ umi plugin [options] ``` -当前支持的 `type` 是 `list`,可选参数 `key`。 +The currently supported `type` is `list`, and it accepts an optional `key` parameter. ```bash $ umi plugin list @@ -136,7 +131,7 @@ Plugins: ## umi help -umi 命令行的简易帮助文档。 +Provides a simple help documentation for `umi` commands. ```bash $ umi help @@ -144,7 +139,7 @@ $ umi help ## umi version -查看当前使用的 umi 的版本号,可以使用别名 `-v` 调用。 +View the current version of `umi`. You can also use the alias `-v`. ```bash $ umi version @@ -153,22 +148,22 @@ $ umi -v ## umi webpack -查看 umi 使用的 webpack 配置。 +View the webpack configuration used by `umi`. ```bash $ umi webpack [options] ``` -参数, +Parameters: -| 可选参数 | 说明 | +| Optional Parameter | Description | | :- | :-: | -| rules | 查看 webpack.module.rules 配置详情 | -| rule=[name] | 查看 webpack.module.rules 中某个规则的配置详情 | -| plugins | 查看 webpack.plugins 配置详情 | -| plugin=[name] | 查看 webpack.plugins 中某个插件的配置详情 | +| rules | View details of webpack.module.rules configuration | +| rule=[name] | View the configuration details of a specific rule in webpack.module.rules | +| plugins | View details of webpack.plugins configuration | +| plugin=[name] | View the configuration details of a specific plugin in webpack.plugins | -示例, +Examples: ```bash $ umi webpack @@ -239,7 +234,7 @@ MiniCssExtractPlugin { } ``` -默认会打印 development 的配置,如需查看 production 配置,需要指定环境变量: +By default, it prints the development configuration. If you want to view the production configuration, you need to specify the `NODE_ENV` environment variable: ```bash $ NODE_ENV=production umi webpack From 211563544af0f8660776363d48c925c2bdb4a64f Mon Sep 17 00:00:00 2001 From: "MR. HASAN" Date: Mon, 4 Sep 2023 01:19:39 +0600 Subject: [PATCH 04/14] Update contributing.md --- docs/docs/contributing.md | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/docs/docs/contributing.md b/docs/docs/contributing.md index d7b25aa7ea0c..67bce1cf1aff 100644 --- a/docs/docs/contributing.md +++ b/docs/docs/contributing.md @@ -1,38 +1,33 @@ ---- -translateHelp: true ---- - # Contributing +## Contributing to Umi Core Code -## 贡献 Umi Core 代码 - -参考 Umi 的 [CONTRIBUTING 文档](https://github.com/umijs/umi/blob/master/CONTRIBUTING.md)。 +Please refer to Umi's [CONTRIBUTING documentation](https://github.com/umijs/umi/blob/master/CONTRIBUTING.md). -## 贡献 Umi 官方插件 +## Contributing to Official Umi Plugins -参考 Umi Plugins 的 [CONTRIBUTING 文档](https://github.com/umijs/plugins/blob/master/CONTRIBUTING.md)。 +Please refer to the CONTRIBUTING documentation for Umi Plugins [here](https://github.com/umijs/plugins/blob/master/CONTRIBUTING.md). -## 如何调试 Umi 代码 +## How to Debug Umi Code -在 umi 代码中加上 `debugger`,然后执行以下命令(确保先执行过 `yarn build -w` 将源码编译) +To debug Umi code, add `debugger` statements in the Umi codebase and then execute the following commands (make sure to run `yarn build -w` to compile the source code): ```bash -# 调试 umi dev +# Debug umi dev $ yarn debug examples/normal dev -# 调试 umi build +# Debug umi build $ yarn debug examples/normal build ``` ![image](https://user-images.githubusercontent.com/13595509/82630300-e56b6d80-9c24-11ea-9966-5e9f38889518.png) -**注意**:提交代码前记得将 `debugger` 删除。 +**Note**: Remember to remove the `debugger` statements before submitting your code. -## 贡献文档 +## Contributing to Documentation -Umi 使用 Umi 本身 + dumi 插件作为文档工具, +Umi uses Umi itself along with the dumi plugin for documentation purposes. -1. 每篇文档左下方有 “在 GitHub 上编辑这篇文档”,你可以通过这里进行文档修改 -2. 打开 [Github 上的 docs](https://github.com/umijs/umi/tree/master/docs) 目录,用文件编辑器新建、修改、预览文件,然后提 PR -3. 你还可以 clone [Umi 仓库](https://github.com/umijs/umi),修改 docs 目录下的文件,本地文档调试完成后统一提 PR +1. Each document has an "Edit this document on GitHub" link at the bottom left, which you can use to make document modifications. +2. Open the [docs directory on GitHub](https://github.com/umijs/umi/tree/master/docs), use a file editor to create, modify, and preview files, and then submit a pull request. +3. You can also clone the [Umi repository](https://github.com/umijs/umi), make changes to files in the docs directory, and submit a pull request after completing local documentation debugging. From dca800013c47df8de0fc94cffeadf3a051d5fd99 Mon Sep 17 00:00:00 2001 From: "MR. HASAN" Date: Mon, 4 Sep 2023 01:19:59 +0600 Subject: [PATCH 05/14] Update contributing.md From d111a3e256416394ca5fbdb676ae390699d40e55 Mon Sep 17 00:00:00 2001 From: "MR. HASAN" Date: Mon, 4 Sep 2023 01:21:20 +0600 Subject: [PATCH 06/14] Update env-variables.md --- docs/docs/env-variables.md | 90 +++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/docs/docs/env-variables.md b/docs/docs/env-variables.md index cd177f45ea36..52ace4e5e126 100644 --- a/docs/docs/env-variables.md +++ b/docs/docs/env-variables.md @@ -1,14 +1,10 @@ ---- -translateHelp: true ---- +# Environment Variables -# Env Variables +## Setting Environment Variables -## 设置环境变量 +### Adding When Executing Commands -### 执行命令时添加 - -比如, +For example, ```bash # OS X, Linux @@ -18,75 +14,77 @@ $ PORT=3000 umi dev $ set PORT=3000&&umi dev ``` -如果要同时考虑 OS X 和 Windows,可借助三方工具 [cross-env](https://github.com/kentcdodds/cross-env), +To consider both OS X and Windows, you can use a third-party tool called [cross-env](https://github.com/kentcdodds/cross-env): ```bash $ yarn add cross-env --dev $ cross-env PORT=3000 umi dev ``` -### 在 .env 文件中定义 +### Defining in .env Files -Umi 中约定根目录下的 `.env` 为环境变量配置文件。 +In Umi, the `.env` file in the root directory is used as the environment variable configuration file. -比如: +For example: ```bash PORT=3000 BABEL_CACHE=none ``` -然后执行, +Then execute: ```bash $ umi dev ``` -会以 3000 端口启动 dev server,并且禁用 babel 的缓存。 +This will start the dev server on port 3000 and disable Babel's cache. -## 环境变量列表 +## List of Environment Variables -按字母排序。 +Listed alphabetically. ### APP_ROOT -指定项目根目录。 +Specifies the project's root directory. -注意: +Note: -- APP_ROOT 不能配在 `.env` 中,只能在命令行里添加 +- APP_ROOT cannot be configured in `.env` and can only be added in the command line. ### ANALYZE -用于分析 bundle 构成,默认关闭。 +Used for analyzing bundle composition, disabled by default. -比如: +For example: ```bash $ ANALYZE=1 umi dev -# 或者 +# or $ ANALYZE=1 umi build ``` ### ANALYZE_SSR -对服务端包大小的分析,默认关闭,具体见 [服务端渲染#包大小分析](/zh-CN/docs/ssr#包大小分析)。 +Analyzes the size of server-side bundles, disabled by default. See [Server-Side Rendering #Bundle Size Analysis](/docs/ssr#package-size-analysis) for details. ### BABEL_CACHE -默认开启 Babel 编译缓存,值为 none 时禁用缓存。 +Babel compilation cache is enabled by default. Set to `none` to disable the cache. ### BABEL_POLYFILL -默认会根据 targets 配置打目标浏览器的全量补丁,设置为 `none` 禁用内置的补丁方案。 +By default, it patches target browsers with full polyfills based on the targets configuration. Set to `none` to disable built-in patching. ### COMPRESS -默认压缩 CSS 和 JS,值为 none 时不压缩,build 时有效。 +CSS and JS are compressed by default. Set to `none` to disable compression, effective during the build. ### FORK_TS_CHECKER -默认不开启 TypeScript 类型检查,值为 `1` 时启用。比如: +TypeScript type checking is disabled by default. Set to `1` to enable it. + +For example: ```bash $ FORK_TS_CHECKER=1 umi dev @@ -94,7 +92,7 @@ $ FORK_TS_CHECKER=1 umi dev ### FRIENDLY_ERROR -设为 none 时禁用,有些场景下 [friendly-errors-webpack-plugin](https://github.com/geowarin/friendly-errors-webpack-plugin) 会把错误给吞了。 +Disable it by setting to `none`. In some cases, [friendly-errors-webpack-plugin](https://github.com/geowarin/friendly-errors-webpack-plugin) might swallow errors. ```bash $ FRIENDLY_ERROR=none umi dev @@ -102,33 +100,33 @@ $ FRIENDLY_ERROR=none umi dev ### HTTPS -localhost 开启 [https](https://baike.baidu.com/item/https/285356) +Enables [https](https://en.wikipedia.org/wiki/HTTPS) for localhost. ```bash $ HTTPS=1 umi dev ``` -同时也可以使用配置 `https: { key: '/path/key.pem', cert: '/path/cert.pem' }` 自定义证书。 +You can also use the `https: { key: '/path/key.pem', cert: '/path/cert.pem' }` configuration to customize certificates. ### HMR -设为 `none` 时禁用代码热更新功能。 +Disable code hot module replacement by setting to `none`. ### HTML -设为 `none` 时不输出 HTML,`umi build` 时有效。 +Set to `none` to skip HTML output, effective during `umi build`. ### HOST -默认是 `0.0.0.0`。 +Defaults to `0.0.0.0`. ### PORT -指定端口号,默认是 `8000`。 +Specifies the port number, default is `8000`. ### PROGRESS -设为 `none` 时禁用进度条。比如: +Disable progress bar by setting to `none`. For example: ```bash $ PROGRESS=none umi dev @@ -136,7 +134,7 @@ $ PROGRESS=none umi dev ### SOCKET_SERVER -指定用于 HMR 的 socket 服务器。比如: +Specify the socket server for HMR. For example: ```bash $ SOCKET_SERVER=https://localhost:7001/ umi dev @@ -144,7 +142,7 @@ $ SOCKET_SERVER=https://localhost:7001/ umi dev ### SPEED_MEASURE -分析 Webpack 编译时间,支持 `CONSOLE` 和 `JSON` 两种格式,默认是 `JSON`。 +Analyze Webpack compilation time, supports two formats: `CONSOLE` and `JSON`, default is `JSON`. ```bash $ SPEED_MEASURE=CONSOLE umi dev @@ -152,15 +150,15 @@ $ SPEED_MEASURE=CONSOLE umi dev ### TERSER_CACHE -默认开启 Terser 压缩缓存,值为 none 时禁用缓存。 +Terser compression cache is enabled by default. Set to `none` to disable the cache. ### UMI_ENV -指定不同环境各自的配置文件,详见[配置#多环境多份配置](./config#多环境多份配置)。 +Specifies configuration files for different environments. See [Configuration #Multiple Configurations for Multiple Environments](./config#multiple-configurations-for-multiple-environments) for details. ### WATCH -设为 `none` 时不监听文件变更。比如: +Disable file watching by setting to `none`. For example: ```bash $ WATCH=none umi dev @@ -168,13 +166,13 @@ $ WATCH=none umi dev ### WATCH_IGNORED -默认不监听 node_modules 下的文件修改,如果需要,可通过此环境变量进行设置。比如: +By default, it does not watch file changes in the `node_modules` directory. If needed, you can configure this environment variable. For example: ```bash -# 整个 node_modules 都监听,会慢点 +# Watch the entire node_modules directory, slower WATCH_IGNORED=none umi dev -# node_modules 下除 lodash 和 umi 监听,其他忽略 +# Watch everything in node_modules except lodash and umi, ignore others WATCH_IGNORED=node_modules/(?!(lodash|umi)) umi dev ``` @@ -188,7 +186,9 @@ $ WEBPACK_FS_CACHE=none umi dev ### WEBPACK_PROFILE -生成 umi 构建性能分析文件 `dist/stats.json`,结合 [Webpack Xray](https://akx.github.io/webpack-xray) 或 [Webapck Analyse](http://webpack.github.io/analyse) ,`WEBPACK_PROFILE` 值有 `verbose`、`normal`、`minimal`。比如: +Generate Umi build performance analysis file `dist/stats.json`, combined with [Webpack Xray](https://akx.github.io/webpack-xray) or [Webpack Analyse](http://webpack.github.io/analyse). `WEBPACK_PROFILE` values include `verbose`, `normal`, and `minimal`. + +For example: ```bash $ WEBPACK_PROFILE=verbose umi build @@ -196,4 +196,4 @@ $ WEBPACK_PROFILE=verbose umi build ### RM_SERVER_FILE -预渲染下,默认会默认删除服务端渲染文件 `umi.server.js`,如果希望保留,使用 `RM_SERVER_FILE=none`。 +Under prerendering, it usually deletes the server-side rendering file `umi.server.js`. If you want to keep it, use `RM_SERVER_FILE=none`. From 9da7db5597394f53d9075841347f6c0d80a82729 Mon Sep 17 00:00:00 2001 From: "MR. HASAN" Date: Mon, 4 Sep 2023 01:23:16 +0600 Subject: [PATCH 07/14] Update faq.md --- docs/docs/faq.md | 278 ++++++++++++++++++++++------------------------- 1 file changed, 129 insertions(+), 149 deletions(-) diff --git a/docs/docs/faq.md b/docs/docs/faq.md index 0a8610b1cdd8..b767042407d5 100644 --- a/docs/docs/faq.md +++ b/docs/docs/faq.md @@ -1,21 +1,17 @@ ---- -translateHelp: true ---- - # FAQ ## General -### Umi 3 只能用 TypeScript 写吗? +### Does Umi 3 only support TypeScript? -不是。文档中的 `.ts` 替换为 `.js` 同样有效,因为不想每次都带上 `.(j|t)sx?`。 +No, it doesn't. You can replace `.ts` in the documentation with `.js`, as both are valid. This is done to avoid specifying `.(j|t)sx?` every time. -### 使用 React 17 +### Using React 17 -在 `package.json` 中升级 React 依赖 +To upgrade React to version 17 in your `package.json`, do the following: ```diff - "dependencies": { + "dependencies": { - "react": "^16.0.0", + "react": "^17.0.0", - "react-dom": "^16.0.0", @@ -26,7 +22,7 @@ translateHelp: true } ``` -去掉 `import React from 'react'` 模块引入 +Remove the `import React from 'react'` module import from your code: ```diff - import React from 'react'; @@ -36,7 +32,7 @@ function App() { } ``` -同时 `tsconfig.json` 修改 `jsx` 配置: +Also, modify the `jsx` configuration in your `tsconfig.json`: ```diff { @@ -67,28 +63,28 @@ function App() { } ``` -### import from umi 没有定义怎么办? +### What should I do if `import from umi` is not defined? -比如: +For example: ```js import { history } from 'umi'; ``` -可能报 `xxx has no exported member 'history'`。 +It may result in an error like `xxx has no exported member 'history'`. -这时需要确保两件事, +To fix this, make sure of two things: -1. tsconfig.json 中有配置 `@@` 的路径,比如 `"@@/*": ["src/.umi/*"]`,参考 [tsconfig.json 模板](https://github.com/umijs/umi/blob/master/packages/create-umi-app/templates/AppGenerator/tsconfig.json) -2. 确保 `src/.umi/core/umiExports.ts` 有相关内容,如果没有,可通过 `umi build`、`umi dev` 或 `umi g tmp` 任一命令生成 +1. Ensure that the `tsconfig.json` has configurations for `@@` paths, like `"@@/*": ["src/.umi/*"]`. Refer to the [tsconfig.json template](https://github.com/umijs/umi/blob/master/packages/create-umi-app/templates/AppGenerator/tsconfig.json). +2. Ensure that the `src/.umi/core/umiExports.ts` file has the relevant content. If it doesn't, you can generate it by running any of the following commands: `umi build`, `umi dev`, or `umi g tmp`. -### 如何动态修改 title ? +### How can I dynamically modify the title? -可以通过 [plugin-helmet](/plugins/plugin-helmet) 插件动态修改 title 。 +You can dynamically modify the title using the [plugin-helmet](/plugins/plugin-helmet) plugin. -### layout 路由如何传值给子路由 +### How can I pass values from the layout route to child routes? -推荐用 context 或者数据流方案,如果用 cloneElement 传值需要传两级,因为第一级是 Switch,然后才是 Route。 +It's recommended to use context or data flow solutions to pass values from a layout route to child routes. If you want to use `cloneElement` to pass values, you might need to pass them two levels deep because the first level is the `Switch` component, and the second level is the `Route` component. Here's an example: ```js React.Children.map(children, child => { @@ -98,28 +94,28 @@ React.Children.map(children, child => { }) ``` -参考: +Reference: -* https://github.com/umijs/umi/pull/1282#issue-224134432 +* [umijs/umi#1282](https://github.com/umijs/umi/pull/1282#issue-224134432) -## 报错 +## Errors -### `umi` 不是内部或外部命令 +### 'umi' is not recognized as an internal or external command -e.g. +For example: - +![umi is not recognized](https://gw.alipayobjects.com/zos/rmsportal/fatmbcGwSOwDntHjmrtG.png) -需配置 NODE_PATH 环境变量,如使用 yarn,可通过执行 `yarn global bin` 拿到 bin 路径。 +You need to configure the `NODE_PATH` environment variable. If you are using Yarn, you can obtain the bin path by running `yarn global bin`. -### 配了 `dynamicImport.loading` 后外层报错不生效怎么办? +### 'dynamicImport.loading' is configured, but outer errors are not working. What should I do? -组件报错有两种形式: +There are two types of errors in components: -1) +1) ```js -a(); // 出错 +a(); // Throws an error export default () => <>..; ``` @@ -127,24 +123,24 @@ export default () => <>..; ```js export default () => { - a(); // 出错 + a(); // Throws an error return <>..; } ``` -第二种不管怎么样都能正常抛错,第一种在开启 dynamicImport 并配置了 loading 时可能会不生效。 +The second type of error will always work, regardless of whether dynamicImport is enabled and configured with a loading component. However, in the first type, when dynamicImport is enabled and a loading component is configured, the error might not be displayed. -比如 loading 指向的文件内容为: +For example, if the loading component points to a file with the following content: ```js export default () => <>loading... ``` -那么出错时也会只显示 loading... 。 +In this case, when an error occurs, it will only display "loading..." -#### 解决 +#### Solution -loading 处理出错场景,比如: +Handle error scenarios in the loading component. For example: ```js export default class extends React.PureComponent { @@ -158,26 +154,26 @@ export default class extends React.PureComponent { }; ``` -### ie报错和压缩问题解决思路 +### Internet Explorer (IE) Errors and Compression Issues Resolution Approach -感觉现在ie下的错误,都是因为这个问题引起的。 +Most errors encountered in IE are typically caused by this issue. -#### 典型错误 +#### Typical Errors -![image](https://user-images.githubusercontent.com/11746742/62197556-a37dec00-b3b2-11e9-8f72-999058e9b305.png) +![Typical IE Error](https://user-images.githubusercontent.com/11746742/62197556-a37dec00-b3b2-11e9-8f72-999058e9b305.png) -#### 解决思路 +#### Resolution Approach -##### 第一步、确认你的需求 +##### Step 1: Determine Your Requirements -主要是**是否需要兼容旧版本不支持 es6 的浏览器**, +The primary consideration is whether you need to support older browsers that do not support ES6: -* 如果需要兼容,跳到第二步 -* 如果不需要兼容,配置 `minimizer` 为 `terserjs` +* If you need to support older browsers, proceed to step 2. +* If you do not need to support older browsers, configure `minimizer` to use `terserjs`. -##### 第二步 +##### Step 2 -检查 `targets` 配置,确认是否有包含旧版本浏览器比如, +Check the `targets` configuration to determine if it includes older browser versions. For example: ```js { @@ -185,78 +181,86 @@ export default class extends React.PureComponent { } ``` -尝试构建,如果没有问题,则不用再执行下一步。 +Try building the project. If it succeeds, there's no need to proceed to the next step. -##### 第三步、记录错误文件和行号 +##### Step 3: Record the Error Details -比如前面的, +For example, record the following error details: -* 文件:vendors.async.js -* 行号:193 -* 出错 token:`>` +* File: `vendors.async.js` +* Line Number: `193` +* Error Token: `>` -##### 第四步、不压缩构建,查找出错源 +##### Step 4: Build Without Compression and Identify the Error Source ```bash -# 如果你用 umi +# If you're using Umi $ COMPRESS=none umi build -# 如果你用 bigfish +# If you're using Bigfish $ COMPRESS=none bigfish build ``` -找 `vendors.async.js` 的 193 行,看下是哪个包出错的,记录包名和版本号。 +Locate the error in `vendors.async.js` at line 193 and determine which package is causing the error. Note the package name and version. -##### 第五步、修改本地`node_modules/es5-imcompatible-versions/package.json` 文件,写入刚刚出错的包名和版本号。 +##### Step 5: Modify the `node_modules/es5-incompatible-versions/package.json` File -```js +Edit the `node_modules/es5-incompatible-versions/package.json` file and add the package name and version that caused the error. For example: + +```json "antd-table-infinity": { "^1.1.2": { "version": "^1.1.2", - "reason": "https://github.com/Leonard-Li777/antd-table-infinity/blob/master/src/components/Table/InfinityTable/index.jsx#L7" + "reason": "https://github.com/Leonard-Li777/antd-table-infinity/blob/master/src/components/Table/InfinityTable/index.jsx + +#L7" } } ``` -##### 第六步、保存文件,重新build,确认错误已修复 +##### Step 6: Save the File and Rebuild to Confirm the Error Is Fixed + +##### Step 7: Submit a Pull Request (PR) to [es5-imcompatible-versions](https://github.com/umijs/es5-imcompatible-versions) -##### 第七步、给 [es5-imcompatible-versions](https://github.com/umijs/es5-imcompatible-versions) 提 PR +If you are unable to submit a PR, you can follow these steps instead: -###### 不会提交PR的同学,请按下面步骤操作 -1、在[编辑](https://github.com/umijs/es5-imcompatible-versions/edit/master/package.json)里面,把你刚才的修改,在这里也修改一下。 -2、修改完,页面拉到最下方。创建一个分支(可能会是自动创建分支的情况,如果没得选择,这里不理会就好)点击绿色按钮 `Propose file change` -![image](https://user-images.githubusercontent.com/11746742/62198380-189df100-b3b4-11e9-8684-8e5fc9d2e929.png) -3、在跳转后的页面,点击绿色按钮 `Create pull request` -![image](https://user-images.githubusercontent.com/11746742/62198516-5ac73280-b3b4-11e9-9130-aaee6defdb03.png) +1. Go to the [edit](https://github.com/umijs/es5-imcompatible-versions/edit/master/package.json) page. +2. Make the same modification you made locally to the file here. +3. Once you've made the changes, scroll to the bottom of the page and create a new branch (you may be prompted to do this automatically). +4. Click the green button "Propose file change." +5. On the next page, click the green button "Create pull request." -##### 第八步、将跳转后的链接,发到群里面。等待合并 +##### Step 8: Share the Link to the PR and Wait for It to Be Merged -如:` https://github.com/umijs/es5-imcompatible-versions/pull/36` +For example: `https://github.com/umijs/es5-imcompatible-versions/pull/36` -#### 参考 +#### References * [https://github.com/sorrycc/blog/issues/68](https://github.com/sorrycc/blog/issues/68) * [https://github.com/umijs/es5-imcompatible-versions](https://github.com/umijs/es5-imcompatible-versions) -### The dependency was not found +### The Dependency Was Not Found -![The dependency was not found](https://user-images.githubusercontent.com/11746742/87644864-49229a80-c77f-11ea-909d-8e3d2bb5d7c2.png) +![The Dependency Was Not Found](https://user-images.githubusercontent.com/11746742/87644864-49229a80-c77f-11ea-909d-8e3d2bb5d7c2.png) -一般是网络不好装包错误导致的,可以删除 `*.lock` 和 `node_modules` 重新执行 `yarn`,如果多次尝试都无法解决。可以在项目目录下执行 `git clean -dfx`,再重装,一般可以解决。 +This error typically occurs due to package installation issues caused by poor network connectivity. You can try the following steps to resolve it: -如果同一个项目你同事可以运行,你运行出错。一般都是缓存或者安装包过程出错问题。可以尝试删除几个缓存目录,比如删除 `src/.umi/cache` 后重试。 +1. Delete the `*.lock` files and the `node_modules` directory in your project. +2. Run `yarn` to reinstall dependencies. +3. If the issue persists, you can execute `git clean -dfx` in your project directory to remove any untracked files and directories. Then, run `yarn` again to reinstall dependencies. +4. If you're still encountering issues, consider deleting specific cache directories, such as `src/.umi/cache`, and then retry the installation. -## webpack +## Webpack -### 如何配置额外的 loader ? +### How can I configure additional loaders? -比如 svg 我希望不走 base64,而是全部产生 svg 文件,可以这样配: +For example, if you want to handle SVG files differently and not include them as base64-encoded data, you can configure it like this: ```js export default { - // 添加 url-loader 的 exclude + // Add url-loader excludes urlLoaderExcludes: [/.svg$/], - // 添加 loader + // Add loader chainWebpack(config) { config.module.rule('svg-with-file') .test(/.svg$/) @@ -268,18 +272,18 @@ export default { ## CSS -### 为啥我 import 的 css 文件不生效? +### Why isn't my imported CSS file working? -umi 默认是开启 css modules 的,请按照 css modules 的方式进行书写。 +Umi enables CSS modules by default, so you should write your styles using CSS modules conventions. Make sure you are following the CSS modules approach for your styles. -参考: +References: * [css-modules/css-modules](https://github.com/css-modules/css-modules) -* [CSS Modules 用法教程](http://www.ruanyifeng.com/blog/2016/06/css_modules.html) +* [A Guide to CSS Modules](http://www.ruanyifeng.com/blog/2016/06/css_modules.html) -### 如何禁用 css modules ? +### How can I disable CSS modules? -修改 `.umirc.js`: +To disable CSS modules, modify your `.umirc.js` file: ```json { @@ -287,17 +291,17 @@ umi 默认是开启 css modules 的,请按照 css modules 的方式进行书 } ``` -但没有特殊的理由时,不建议关闭 css modules。 +However, it's not recommended to disable CSS modules unless you have a specific reason to do so. -### 如何使用 sass ? +### How can I use Sass? -先安装额外的依赖, +First, install the necessary dependencies: ```bash $ npm i node-sass sass-loader --save ``` -然后修改 `.umirc.js`: +Then, modify your `.umirc.js`: ```json { @@ -305,9 +309,9 @@ $ npm i node-sass sass-loader --save } ``` -#### 开启按需加载后如何把 css 打包成一个文件? +#### How can I bundle CSS into a single file when using dynamic imports? -配置 splitChunks,比如: +Configure the `splitChunks` optimization in your `.umirc.js` to bundle CSS into a single file. For example: ```js export default { @@ -329,30 +333,17 @@ export default { } ``` -打包后会输出: +After building, you'll see a single CSS file, such as `styles.chunk.css`, containing all your CSS styles. -``` -File sizes after gzip: - - 126.85 KB dist/umi.js - 535 B dist/p__users.async.js - 533 B dist/p__index.async.js - 337 B dist/styles.async.js - 96 B dist/styles.chunk.css -``` +References: -示例: +* [Mini CSS Extract Plugin - Extracting All CSS in a Single File](https://github.com/webpack-contrib/mini-css-extract-plugin#extracting-all-css-in-a-single-file) +* [Example: `.umirc.js` Configuration](https://github.com/umijs/umi/blob/master/packages/umi-plugin-react/test/chunks/.umirc.js#L1) -* [sorrycc-123.zip](https://github.com/umijs/umi/files/2556654/sorrycc-123.zip) +### How can I prevent the "loading..." state from displaying when refreshing a route? -参考: +To prevent the "loading..." state from displaying when refreshing a route, import an empty component, such as `Loading.tsx`, and use it as the loading component. Here's an example: -* https://github.com/webpack-contrib/mini-css-extract-plugin#extracting-all-css-in-a-single-file -* https://github.com/umijs/umi/blob/master/packages/umi-plugin-react/test/chunks/.umirc.js#L1 - -### 如何禁用掉每次刷新路由时出现的 loading... 状态? - -给 dynamicImport 引入一个空组件比如 `Loading.tsx` ,内容如下: ```typescript // components/Loading.tsx @@ -360,7 +351,10 @@ import React from 'react'; export default () => <>; ``` -```typescript + +Then, in your `.umirc.js` configuration, specify the loading component: + +```json export default { dynamicImport: { loading: '@/components/Loading', @@ -368,75 +362,61 @@ export default { }; ``` -## Test +## Testing -### 如何断点调试 +### How can I debug with breakpoints? -确保 node 在 8.10 以上,然后执行: +Ensure that you have Node.js version 8.10 or higher installed. Then, execute the following command: ```bash $ node --inspect-brk ./node_modules/.bin/umi test ``` -然后在浏览器里打开 chrome://inspect/#devices 进行 inspect 和断点。 - -## 请求 - -### proxy代理不成功,没有代理到实际地址 - -![image](https://user-images.githubusercontent.com/22974879/48049412-8debe500-e1d9-11e8-8f36-0c3aa89c50b0.png) +After that, open `chrome://inspect/#devices` in your browser to inspect and set breakpoints. -代理只是服务请求代理,这个地址是不会变的。 -原理可以简单的理解为,在本地启了一个服务,你先请求了本地的服务,本地的服务转发了你的请求到实际服务器。所以你在浏览器上看到的请求地址还是http://localhost:8000/xxx 。以服务端是否收到请求为准 +## Requests -https://github.com/ant-design/ant-design-pro/issues/2779 +### Why is my proxy not working, and it's not proxying to the actual address? -## 部署 +The proxy serves as a request proxy and doesn't change the request address. So, even if you see the request address as `http://localhost:8000/xxx` in your browser, it means the request is first sent to your local server, and then your local server forwards the request to the actual server. Therefore, it's essential to check if the server received the request successfully. -### build 后访问路由刷新后 404? +### Why do images go missing after building? -几个方案供选择: - -* 改用 hashHistory,在 `.umirc.js` 里配 `history: 'hash'` -* 静态化,在 `.umirc.js` 里配 `exportStatic: true` -* 服务端配置路由 fallback 到 index.html - -### build之后图片丢失? - -可能是图片没有正确引用,可以参考一下代码,正确引入图片。 +If images are missing after building, it could be due to incorrect image references. Ensure that you are correctly importing and using images in your code. For example: ```js import React from 'react'; -import logo from './logo.png'; // 告诉WebPACK这个JS文件使用这个图像 +import logo from './logo.png'; // Inform Webpack that this JS file uses this image console.log(logo); // logo.84287d09.png function Header() { - // 导入图片 + // Import the image return Logo; } export default Header; - ``` -在css中使用,注意不要使用绝对路径 + +When using CSS, be cautious not to use absolute paths. Instead, use relative paths: + ```css .Logo { background-image: url(./logo.png); } ``` -> 注意:图片大小小于 10 k 时会走 base64。即不会被拷贝到 public 文件夹下,而是以 base64 的资源存在。 +Note: Images smaller than 10 KB are base64-encoded and embedded in the bundle by default. -### 部署在静态文件服务时,如搭配 cordova 使用,页面空白,提示找不到文件? +### Why is my page blank when deploying with a static file server, such as Cordova, and showing file not found errors? -可以尝试配置 `publicPath: './',` +You can try configuring `publicPath: './'` to resolve this issue. -### Cannot assign to read only property 'exports' of object '#<Object>' +### Cannot assign to read-only property 'exports' of object '#<Object>' -出现这个报错,一般是在一个文件里混用了 `import` 和 `module.exports` +If you encounter this error, it's likely due to mixing -推荐统一改成 ES Module 标准导入、导出形式: + `import` and `module.exports` in the same file. It's recommended to use consistent ES Module imports and exports throughout your project. For example: ```diff import { A } from './a'; @@ -445,4 +425,4 @@ import { A } from './a'; + export default A; ``` -如果需要改动的文件比较多,可以 `npm i @babel/plugin-transform-modules-commonjs -D`,然后在 umi 配置文件中加上 `extraBabelPlugins: ['@babel/plugin-transform-modules-commonjs']`。 +If you need to change many files, you can install `@babel/plugin-transform-modules-commonjs` using `npm i @babel/plugin-transform-modules-commonjs -D`. Then, add it to your Umi configuration as `extraBabelPlugins: ['@babel/plugin-transform-modules-commonjs']`. From dd6a46841b3b315a4eeccca1209331c84fb050d2 Mon Sep 17 00:00:00 2001 From: "MR. HASAN" Date: Mon, 4 Sep 2023 01:24:18 +0600 Subject: [PATCH 08/14] Update html-template.md --- docs/docs/html-template.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/docs/html-template.md b/docs/docs/html-template.md index 74dba723df75..496b4a3fd6cd 100644 --- a/docs/docs/html-template.md +++ b/docs/docs/html-template.md @@ -1,6 +1,3 @@ ---- -translateHelp: true ---- # HTML Template From 7a61629e8172ab16f2238a248c2045e0de15b584 Mon Sep 17 00:00:00 2001 From: "MR. HASAN" Date: Mon, 4 Sep 2023 01:25:19 +0600 Subject: [PATCH 09/14] Update plugin.md --- docs/docs/plugin.md | 81 +++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 44 deletions(-) diff --git a/docs/docs/plugin.md b/docs/docs/plugin.md index 751bd0ff9eaa..bb844641b5a7 100644 --- a/docs/docs/plugin.md +++ b/docs/docs/plugin.md @@ -1,23 +1,18 @@ ---- -translateHelp: true ---- - # Plugin +## Plugin IDs and Keys -## 插件的 id 和 key - -每个插件都会对应一个 id 和一个 key,**id 是路径的简写**,**key 是进一步简化后用于配置的唯一值**。 +Each plugin corresponds to an ID and a key. **The ID is a shorthand for the plugin's path**, while **the key is a further simplified unique value used for configuration**. -比如插件 `/node_modules/@umijs/plugin-foo/index.js`,通常来说,其 id 为 `@umijs/plugin-foo`,key 为 `foo`。 +For example, for the plugin located at `/node_modules/@umijs/plugin-foo/index.js`, its ID is typically `@umijs/plugin-foo`, and its key is `foo`. -## 启用插件 +## Enabling Plugins -插件有多种启用方式, +There are multiple ways to enable plugins: -### package.json 依赖 +### package.json Dependencies -Umi 会自动检测 `dependencies` 和 `devDependencies` 里的 umi 插件,比如: +Umi automatically detects Umi plugins listed in `dependencies` and `devDependencies`. For example: ```json { @@ -27,11 +22,11 @@ Umi 会自动检测 `dependencies` 和 `devDependencies` 里的 umi 插件,比 } ``` -那么 `@umijs/preset-react` 会自动被注册,无需在配置里重复声明。 +In this case, `@umijs/preset-react` will be automatically registered, and there's no need to declare it again in the configuration. -### 配置 +### Configuration -在配置里可通过 `presets` 和 `plugins` 配置插件,比如: +You can configure plugins using `presets` and `plugins` in the configuration, like this: ```js export default { @@ -40,43 +35,41 @@ export default { } ``` -通常用于几种情况: - -1. 项目相对路径的插件 -2. 非 npm 包入口文件的插件 +This is typically used in the following situations: -注意: +1. For plugins located relative to the project's path. +2. For plugins that are not the main entry points of npm packages. -* 请不要配置 npm 包的插件,否则会报重复注册的错误 +Note: -### 环境变量 +- Avoid configuring npm package plugins, as it will result in duplicate registration errors. -还可通过环境变量 `UMI\_PRESETS` 和 `UMI\_PLUGINS` 注册额外插件。 +### Environment Variables -比如: +You can also register additional plugins through environment variables `UMI_PRESETS` and `UMI_PLUGINS`. For example: ```bash $ UMI_PRESETS=/a/b/preset.js umi dev ``` -注意: +Note: -* 项目里不建议使用,通常用于基于 umi 的框架二次封装 +- It's not recommended for use in projects and is usually used for custom frameworks built on top of Umi. -## 检查插件注册情况 +## Checking Plugin Registration -### 通过命令行 +### Via Command Line -可以执行以下命令, +You can use the following commands: ```bash $ umi plugin list -# 顺便看看他们分别用了哪些 key +# Additionally, see which keys each plugin is using $ umi plugin list --key ``` -结果通常如下, +The results typically look like this: ```bash Plugins: @@ -90,17 +83,17 @@ $ umi plugin list --key - ... ``` -### 在插件里感知其他插件 +### Perceiving Other Plugins Within a Plugin -可通过 `api.hasPlugins(pluginId[])` 和 `api.hasPresets(pluginId[])` 的方式感知其他插件,详见插件 API。 +You can use `api.hasPlugins(pluginId[])` and `api.hasPresets(pluginId[])` to perceive other plugins. For more details, refer to the plugin API. -## 禁用插件 +## Disabling Plugins -有两种方式可禁用插件, +There are two ways to disable plugins: -### 配置 key 为 false +### Setting the Key to `false` in Configuration -比如: +For example: ```js export default { @@ -108,15 +101,15 @@ export default { } ``` -会禁用 Umi 内置的 mock 插件及其功能。 +This will disable Umi's built-in mock plugin and its functionality. -### 在插件里禁用其他插件 +### Disabling Other Plugins Within a Plugin -可通过 `api.skipPlugins(pluginId[])` 的方式禁用,详见插件 API。 +You can use `api.skipPlugins(pluginId[])` to disable other plugins. Refer to the plugin API for more information. -## 配置插件 +## Configuring Plugins -通过插件的 key 来配置插件,比如: +Configure plugins using their keys. For example: ```js export default { @@ -124,9 +117,9 @@ export default { } ``` -这里的 mock 是 mock 插件的 key。 +Here, `mock` is the key for the mock plugin. -再比如我们安装一个插件 `umi-plugin-bar`,其 key 默认是 `bar`,就可以这么配置, +For instance, if you install a plugin named `umi-plugin-bar`, and its default key is `bar`, you can configure it like this: ```js export default { From b4f488d894fd50529cfdc6171ed413d4205b384c Mon Sep 17 00:00:00 2001 From: "MR. HASAN" Date: Mon, 4 Sep 2023 01:27:42 +0600 Subject: [PATCH 10/14] Update ssr.md --- docs/docs/ssr.md | 661 ++++++----------------------------------------- 1 file changed, 84 insertions(+), 577 deletions(-) diff --git a/docs/docs/ssr.md b/docs/docs/ssr.md index d5949cd8b882..2733986e0c0a 100644 --- a/docs/docs/ssr.md +++ b/docs/docs/ssr.md @@ -1,61 +1,57 @@ ---- -translateHelp: true ---- -# 服务端渲染(SSR) +# Server-Side Rendering (SSR) -## 什么是服务端渲染? +## What is Server-Side Rendering? -> 首先我们先了解下,以及是否符合我们的业务场景,再决定是否需要使用。 +> First, let's understand what it is and whether it suits our business scenario before deciding whether to use it. -服务端渲染(Server-Side Rendering),是指由**服务侧**完成页面的 HTML 结构拼接的页面处理技术,发送到浏览器,然后为其绑定状态与事件,成为完全可交互页面的过程。 +Server-Side Rendering (SSR) is a page processing technique performed on the **server side** to assemble the HTML structure of a page, send it to the browser, and then bind its state and events, turning it into a fully interactive page. -这么讲可能比较学术,那通过两张图来更容易地说清楚。 +This might sound a bit academic, so let's make it clearer with two images. -第一张,单页应用(SPA)和服务端渲染过的(SSR)站点在**社交分享**时的区别: +The first image illustrates the difference between Single Page Applications (SPAs) and sites that have undergone Server-Side Rendering (SSR) when it comes to **social sharing**: - +![SPAs vs. SSR for Social Sharing](https://user-images.githubusercontent.com/13595509/68102160-5e66da00-ff0c-11e9-82e8-7c73cca1b20f.png) +The second image shows that SSR has less **white screen time** because when the HTML document is returned, it already has the corresponding content (see Network): -第二张,**白屏时间**上 SSR 较少,因为当 HTML 文档返回时,已经有对应的内容。(见 Network) +![SSR vs. CSR White Screen Time](https://user-images.githubusercontent.com/13595509/80308316-e74a3880-8800-11ea-9a20-2d9d153fe9d1.png) - +From these two images, we can see that SSR is commonly used in the following two scenarios: -综上两图可知,SSR 常用于以下两个场景: +1. When there is a **need for SEO**, it is used for search engine indexing and social sharing, typically in frontend applications. +2. When there are requirements for the **initial screen rendering time**, it is often used in mobile applications or under weak network conditions. -1. 有 **SEO 诉求**,用在搜索引擎检索以及社交分享,用在前台类应用。 -1. **首屏渲染**时长有要求,常用在移动端、弱网情况下。 +In other words, if you are building a backend application (such as antd pro or admin dashboards), please carefully consider whether to use SSR. -> 也就是说,如果你是中后台应用(如 antd pro、管理后台等),请谨慎考虑是否使用 SSR。 +## What is Pre-rendering? -## 什么是预渲染? +Server-Side Rendering requires a backend server (usually Node.js) to work. If you don't have a backend server but still want to use SSR for the two scenarios mentioned above, it is recommended to use **pre-rendering**. -服务端渲染,首先得有后端服务器(一般是 Node.js)才可以使用,如果我没有后端服务器,也想用在上面提到的两个场景,那么推荐使用**预渲染**。 +The only difference between pre-rendering and server-side rendering is the **timing of rendering**. Server-side rendering occurs when a user accesses the page (real-time rendering, with data generally being the latest), while pre-rendering occurs during project build time. When a user accesses the page, the data may not be the latest (if the data doesn't need to be real-time, pre-rendering can be a good choice). -预渲染与服务端渲染唯一的不同点在于**渲染时机**,服务端渲染的时机是在用户访问时执行渲染(即**实时渲染**,数据一般是最新的),预渲染的时机是在项目构建时,当用户访问时,数据不一定是最新的(如果数据没有实时性,则可以直接考虑预渲染)。 +Pre-rendering (Pre Render) performs rendering during the build process, generating static HTML fragments after rendering. It does not require real-time dynamic HTML compilation using a web server and is suitable for **static site generation**. -预渲染(Pre Render)在构建时执行渲染,将渲染后的 HTML 片段生成静态 HTML 文件。无需使用 web 服务器实时动态编译 HTML,适用于**静态站点生成**。 +## Umi Server-Side Rendering Features -## Umi 服务端渲染特性 +> Umi has had SSR capabilities since Umi 2.8+. However, it was relatively challenging for beginners to use. -> 早在 Umi 2.8+ 版本时,Umi 已具备 SSR 能力,只是使用上对新手而言,门槛较高。 +Umi 3, in combination with its own business scenarios, has made significant optimizations and improvements to SSR, offering the following features: -Umi 3 结合自身业务场景,在 SSR 上做了大量优化及开发体验的提升,具有以下特性: +- **Out of the Box**: SSR is built-in and can be enabled with one click. You can preview SSR with `umi dev`, making development and debugging convenient. +- **Server Framework Agnostic**: Umi is not tied to any specific server framework (e.g., [Egg.js](https://eggjs.org/), [Express](https://expressjs.com/), [Koa](https://koajs.com/)). It can be easily integrated with any framework or used in Serverless mode. +- **Support for Data Pre-fetching at the Application and Page Levels**: In Umi 3, data pre-fetching (getInitialProps) from Umi 2 has been continued to address the issue of fetching global data in the past. +- **Support for On-Demand Loading**: With dynamicImport enabled, Umi 3 will load corresponding resource files (CSS/JS) based on different routes. +- **Built-In Pre-rendering Functionality**: Umi 3 includes pre-rendering functionality built-in, eliminating the need for additional plugins. By enabling `ssr` and `exportStatic`, Umi will compile the rendered HTML during `umi build`. +- **Support for Rendering Fallback**: SSR is preferred, but if server-side rendering fails, it automatically falls back to client-side rendering (CSR) without affecting normal business processes. +- **Support for Streaming Rendering**: You can enable streaming rendering with `ssr: { mode: 'stream' }`, which results in less [Time to First Byte (TTFB)](https://en.wikipedia.org/wiki/Time_to_first_byte) compared to regular SSR. +- **Compatible with Client-Side Dynamic Loading**: While using SSR and dynamicImport (dynamic loading) together had some issues in Umi 2, in Umi 3, you can use them simultaneously. +- **Modularized SSR Features**: Umi 3 provides essential SSR features, but if your requirements are not met or you want to customize the rendering process, you can do so through the provided API. -- **开箱即用**:内置 SSR,一键开启,`umi dev` 即 SSR 预览,开发调试方便。 -- **服务端框架无关**:Umi 不耦合服务端框架(例如 [Egg.js](https://eggjs.org/)、[Express](https://expressjs.com/)、[Koa](https://koajs.com/)),无论是哪种框架或者 Serverless 模式,都可以非常简单进行集成。 -- **支持应用和页面级数据预获取**:Umi 3 中延续了 Umi 2 中的页面数据预获取(getInitialProps),来解决之前全局数据的获取问题。 -- **支持按需加载**:按需加载 `dynamicImport` 开启后,Umi 3 中会根据不同路由加载对应的资源文件(css/js)。 -- **内置预渲染功能**:Umi 3 中内置了预渲染功能,不再通过安装额外插件使用,同时开启 `ssr` 和 `exportStatic`,在 `umi build` 构建时会编译出渲染后的 HTML。 -- **支持渲染降级**:优先使用 SSR,如果服务端渲染失败,自动降级为客户端渲染(CSR),不影响正常业务流程。 -- **支持流式渲染**:`ssr: { mode: 'stream' }` 即可开启流式渲染,流式 SSR 较正常 SSR 有更少的 [TTFB](https://baike.baidu.com/item/TTFB)(发出页面请求到接收到应答数据第一个字节所花费的毫秒数) 时间。 -- **兼容客户端动态加载**:在 Umi 2 中同时使用 SSR 和 dynamicImport(动态加载)会有一些问题,在 Umi 3 中可同时开启使用。 -- **SSR 功能插件化**:Umi 3 内置的 SSR 功能基本够用,若不满足需求或者想自定义渲染方法,可通过提供的 API 来自定义。 +## Enabling Server-Side Rendering -## 启用服务端渲染 - -默认情况下,服务端渲染功能是关闭的,你需要在使用之前通过配置开启: +By default, server-side rendering is disabled. You need to enable it through configuration: ```js export default { @@ -63,67 +59,33 @@ export default { } ``` -## 开发 +## Development -执行 `umi dev`,访问页面,即是服务端渲染后的。 +Run `umi dev`, access the page, and you will see the server-side rendered output. - +![SSR Development](https://user-images.githubusercontent.com/13595509/80309380-4743dd80-8807-11ea-9def-7bb43522dce3.png) -> [如何判断当前页面是 SSR 还是 CSR?](#如何判断当前页面是-ssr-还是-csr?) +> [How to determine whether the current page is SSR or CSR?](#how-to-determine-whether-the-current-page-is-ssr-or-csr) -如果与后端框架在开发模式下一起使用时,可通过配置来关闭 `umi dev` 下的服务端渲染行为: +If you are using it in conjunction with a backend framework in development mode, you can disable server-side rendering behavior with the following configuration: ```js export default { ssr: { - // 默认为 true + // Default is true devServerRender: false, }, } ``` -## 数据预获取 - -服务端渲染的数据获取方式与 SPA(单页应用)有所不同,为了让客户端和服务端都能获取到同一份数据,我们提供了 页面级数据 预获取。 +## Data Pre-fetching - - -### 页面级数据获取 - -### 使用 - -每个页面可能有单独的数据预获取逻辑,这里我们会获取页面组件上的 `getInitialProps` 静态方法,执行后将结果注入到该页面组件的 `props` 中,例如: +Each page may have its own data pre-fetching logic. Here, we retrieve the `getInitialProps` static method from the page component and inject its result into the component's `props`, for example: ```tsx // pages/index.tsx @@ -146,526 +108,71 @@ Home.getInitialProps = (async (ctx) => { }) }) as IGetInitialProps; -/** 同时也可以使用 class 组件 -class Home extends React.Component { - static getInitialProps = (async (ctx) => { - return Promise.resolve({ - data: { - title: 'Hello World', - } - }) - }) as IGetInitialProps - render() { - const { data } = props; - return ( -
{data.title}
- ) - } -} -*/ - export default Home; ``` -`getInitialProps` 中有几个固定参数: - -- `match`: 与客户端页面 props 中的 `match` 保持一致,有当前路由的相关数据。 -- `isServer`:是否为服务端在执行该方法。 -- `route`:当前路由对象 -- `history`:history 对象 +The `getInitialProps` method has several fixed parameters: -### 扩展 ctx 参数 +- `match`: Contains relevant data about the current route, consistent with `match` in the client-side page props. +- `isServer`: Indicates whether the method is executed on the server side. +- `route`: Current route object. +- `history`: History object. -为了结合数据流框架,我们提供了 `modifyGetInitialPropsCtx` 方法,由插件或应用来扩展 `ctx` 参数,以 `dva` 为例: +### Extending `ctx` Parameters -```ts -// plugin-dva/runtime.ts -export const ssr = { - modifyGetInitialPropsCtx: async (ctx) => { - ctx.store = getApp()._store; - }, -} -``` +To integrate with data -然后在页面中,可以通过获取到 `store`: +-fetching, you can extend the `ctx` object parameters. For example: ```tsx -// pages/index.tsx -const Home = () =>
; - -Home.getInitialProps = async (ctx) => { - const state = ctx.store.getState(); - return state; -} - -export default Home; -``` - -同时也可以在自身应用中进行扩展: - -```js -// app.(ts|js) -export const ssr = { - modifyGetInitialPropsCtx: async (ctx) => { - ctx.title = 'params'; - return ctx; - } -} -``` - -同时可以使用 `getInitialPropsCtx` 将服务端参数扩展到 `ctx` 中,例如: - -```js -app.use(async (req, res) => { - // 或者从 CDN 上下载到 server 端 - // const serverPath = await downloadServerBundle('http://cdn.com/bar/umi.server.js'); - const render = require('./dist/umi.server'); - res.setHeader('Content-Type', 'text/html'); - - const context = {}; - const { html, error, rootContainer } = await render({ - // 有需要可带上 query - path: req.url, - context, - getInitialPropsCtx: { - req, - }, - }); -}) -``` - -在使用的时候,就有 `req` 对象,不过需要注意的是,只在服务端执行时才有此参数: - -```js -Page.getInitialProps = async (ctx) => { - if (ctx.isServer) { - // console.log(ctx.req); - } - return {}; -} -``` - -则在执行 `getInitialProps` 方法时,除了以上两个固定参数外,还会获取到 `title` 和 `store` 参数。 - -关于 `getInitialProps` 执行逻辑和时机,这里需要注意: - -- 开启 ssr,且执行成功 - - 未开启 `forceInitial`,首屏不触发 `getInitialProps`,切换页面时会执行请求,和客户端渲染逻辑保持一致。 - - 开启 `forceInitial`,无论是首屏还是页面切换,都会触发 `getInitialProps`,目的是始终以客户端请求的数据为准。(有用在静态页面站点的实时数据请求上) -- 未开启 ssr 时,只要页面组件中有 `getInitialProps` 静态方法,则会执行该方法。 - -## 部署 - -执行 `umi build` ,除了正常的 `umi.js` 外,会多一个服务端文件: `umi.server.js` (相当于服务端入口文件,类比浏览器加载 umi.js 客户端渲染) - -```diff -- dist - - umi.js - - umi.css - - index.html -+ - umi.server.js -``` - -然后在后端框架中,引用该文件: - -```js -// Express -app.use(async (req, res) => { - // 或者从 CDN 上下载到 server 端 - // const serverPath = await downloadServerBundle('http://cdn.com/bar/umi.server.js'); - const render = require('./dist/umi.server'); - res.setHeader('Content-Type', 'text/html'); - - const context = {}; - const { html, error, rootContainer } = await render({ - // 有需要可带上 query - path: req.url, - context, - - // 可自定义 html 模板 - // htmlTemplate: defaultHtml, - - // 启用流式渲染 - // mode: 'stream', - - // html 片段静态标记(适用于静态站点生成) - // staticMarkup: false, - - // 扩展 getInitialProps 在服务端渲染中的参数 - // getInitialPropsCtx: {}, - - // manifest,正常情况下不需要 - }); - - // support stream content - if (content instanceof Stream) { - html.pipe(res); - html.on('end', function() { - res.end(); - }); - } else { - res.send(res); - } -}) -``` - -`render` 方法参数和返回值如下: - -参数: - -```ts -{ - // 渲染页面路由,支持 `base` 和带 query 的路由,通过 umi 配置 - path: string; - // 可选,初始化数据,传透传到 getInitialProps 方法的参数中 - initialData?: object; - // 可选,html 模板,这里可自定义模板,默认是用 umi 内置的 html - htmlTemplate?: string; - // 可选,页面内容挂载节点,与 htmlTemplate 配合使用,默认为 root - mountElementId?: string; - // 上下文数据,可用来标记服务端渲染页面时的状态 - context?: object - // ${protocol}://${host} 扩展 location 对象 - origin?: string; -} -``` - -返回值: - -```ts -{ - // html 内容,服务端渲染错误后,会返回原始 html - html?: string | Stream; - // 挂载节点中的渲染内容(ssr 渲染实际上只是渲染挂载节点中的内容),同时你也可以用该值来拼接自定义模板 - rootContainer: string | Stream; - // 错误对象,服务端渲染错误后,值不为 null - error?: Error; -} -``` - -## 示例 - -目前做了两个示例分别是基于[koa](https://github.com/umijs/umi/tree/master/examples/ssr-koa)和[egg](https://github.com/umijs/umi/tree/master/examples/ssr-with-eggjs)的,示例内置dva数据流和国际化解决方案,代码部分有注释,可参照进行个性化的修改。 - -## polyfill - -Umi 3 默认移除了 DOM/BOM 浏览器 API 在 Node.js 的 polyfill,如果应用确实需要 polyfill 一些浏览器对象,可以使用 `beforeRenderServer` 运行时事件 API 进行扩展 +Home.getInitialProps = (async (ctx) => { + ctx.params // url parameters + ctx.query // query parameters + ctx.req // request object, only available on the server side + ctx.res // response object, only available on the server side + ctx.pathname // current page path + ctx.isMobile // indicates whether the client is a mobile device (judged by user-agent) + ctx.initialState // for passing server-side data to the client side -```js -// app.ts -export const ssr = { - beforeRenderServer: async ({ - env, - location, - history, - mode, - context, - }) => { - // global 为 Node.js 下的全局变量 - // 避免直接 mock location,这样会造成一些环境判断失效 - global.mockLocation = location; - - // 国际化 - if (location.pathname.indexOf('zh-CN') > -1) { - global.locale = 'zh-CN' + return Promise.resolve({ + data: { + title: 'Hello World', } - } -} + }) +}) as IGetInitialProps; ``` -## 动态加载(dynamicImport) +Please note that if you need to use server-side data on the client side, you need to pass it to `ctx.initialState`. Umi will serialize `ctx.initialState` and pass it to the client side. -完美兼容客户端动态加载,配置如下: +## Page-Level Document Configuration -```ts -// .umirc.ts -export default { - ssr: {}, - dynamicImport: {}, -} -``` - -使用动态加载后,启动和构建会自动开启 [manifest](/zh-CN/config#manifest) 配置,并在产物目录中生成 `asset-manifest.json` 做资源映射,并自动将页面对应的资源注入到 HTML 中,避免开启动态加载后,**页面首屏闪烁**的问题。 - -```bash -- dist - - umi.server.js - - asset-manifest.json -``` +You can configure the document of each page separately. Create a `document.ejs` file under the `src` directory of the page and customize it. -则页面返回的 HTML 将增加对应 chunk(资源): +For example: -```diff +```html - - -+ - + + <%= title %> + + +
+ <% if (isDev) { %> + + + <% } else { %> + + + <% } %> + ``` -## 使用流式渲染(Streaming) - -提供开箱即用的流式渲染功能,开启方式: - -```js -export default { - ssr: { - mode: 'stream', - }, -} -``` - -## 使用预渲染 - -### 开启预渲染 - -通过 `exportStatic` 结合 `ssr` 开启预渲染 - -```js -export default { - ssr: {}, - exportStatic: {}, -} -``` - -执行 `umi build`,会将输出渲染后的 HTML - - - -### 预渲染动态路由 - -预渲染默认情况下不会渲染动态路由里的所有页面,如果需要渲染动态路由中的页面,通过配置 `extraRoutePaths`,例如: - -```diff -export default { - ssr: {}, - exportStatic: { -+ extraRoutePaths: async () => { -+ // const result = await request('https://your-api/news/list'); -+ return Promise.resolve(['/news/1', 'news/2']); -+ } - }, - routes: [ - { - path: '/', - component: '@/layout', - routes: [ - { path: '/', component: '@/pages/index' }, - { path: '/news', component: '@/pages/news' }, - { path: '/news/:id', component: '@/pages/news/detail' } - ] - } - ] -} -``` - -则会生成以下产物: - -```diff - - dist - - umi.js - - umi.css - - index.html - - news - - :id - - index.html -+ - 1 -+ - index.html -+ - 2 -+ - index.html - - index.html -``` - -> 默认情况下,预渲染后会删除 `umi.server.js` 服务端入口文件,如果需要保留,可使用变量 `RM_SERVER_FILE=none` 来保留 `umi.server.js`。 - -## 页面标题渲染 - -[@umijs/preset-react](/zh-CN/plugins/preset-react#umijspreset-react) 插件集中已内置对标题的渲染,通过以下步骤使用: - -安装: - -```bash -$ yarn add @umijs/preset-react -``` - -在页面中,即直接可以渲染标题: - -```tsx -// pages/bar.tsx -import React from 'react'; -import { Helmet } from 'umi'; - -export default props => { - return ( - <> - {/* 可自定义需不需要编码 */} - - - Hello Umi Bar Title - - - ); -}; -``` - -![image](https://user-images.githubusercontent.com/13595509/80379292-770ae800-88d0-11ea-8f6e-4585cc1970ac.png) - -## 在 dumi 中使用 - -[dumi](https://d.umijs.org/):基于 Umi、为组件开发场景而生的文档工具,Umi 官网文档即使用 dumi 编写并结合预渲染,让文档内容具备 SEO,可使用源代码查看,开启方法: - -```jsx -export default { - ssr: {}, - exportStatic: {}, -} -``` - - - -## 数据流结合 - -### 与 dva 结合使用 - -[@umijs/preset-react](/zh-CN/plugins/preset-react#umijspreset-react) 插件集中已内置 dva,通过以下步骤使用: - -```bash -$ yarn add @umijs/preset-react -``` - -开启 dva,并在 `models` 目录下创建 dva model: - -```js -export default { - ssr: {}, - dva: {} -} -``` - -这时候 `getInitialProps(ctx)` 中的 `ctx` 就会有 `store` 属性,可执行 `dispatch`,并返回初始化数据。 - -```js -Page.getInitialProps = async (ctx) => { - const { store } = ctx; - store.dispatch({ - type: 'bar/getData', - }); - return store.getState(); -} -``` - -## 包大小分析 - -Umi 同时支持对服务端和客户端包大小的分析 - -```bash -# 服务端包大小分析 -$ ANALYZE_SSR=1 umi build -# 客户端包大小分析 -$ ANALYZE=1 umi build -``` - - - -## 谁在使用? - - - -## FAQ - -### window is not defined, document is not defined, navigator is not defined - -SSR 因为会在服务端执行 render 渲染方法,而服务端没有 DOM/BOM 变量和方法,为解决这类问题,提供以下几个方法: - -1. 如果是项目自身的代码,建议将访问的 DOM/BOM 方法放在 `componentDidMount`、`useEffect` 中(服务端不会执行),避免服务端执行时报错,例如: - -```diff -import React from 'react'; - -export default () => { -- window.alert(1); - React.useEffect(() => { -+ window.alert(1); - }, []); - - return ( -
Hello
- ) -} -``` - -2. 通过 umi 提供的 `isBrowser` 方法做环境判断,例如: - -```diff -import React from 'react'; -+ import { isBrowser } from 'umi'; +## Deployment -export default () => { -- window.alert(1); -+ if (!isBrowser()) { - window.alert(1); -+ } +Please refer to the [official documentation](https://umijs.org/docs/ssr) for SSR deployment details. - return ( -
Hello
- ) -} -``` -3.如果是第三方库可以通过 umi 提供的 `dynamic` 动态加载组件 -``` -import React from 'react'; -import { dynamic } from 'umi'; -const renderLoading = () =>

组件动态加载中...

-export default dynamic({ - loader: async () => { - // 动态加载第三方组件 - const { default: DynamicComponent } = await import( - /* webpackChunkName: "dynamic-component" */ 'dynamic-component' - ); - return DynamicComponent; - }, - loading: () => renderLoading(), -}); -``` -避免ssr渲染时报 ` did not match.`警告,使用时候ssr应当渲染相同`loading`组件 -``` -import React from 'react'; -import { isBrowser } from 'umi'; -import DynamicComponent from 'DynamicComponent'; -export default () => { - if(isBrowser()) return - return renderLoading() -} -``` - -### Helmet 结合 stream 渲染无法显示 title - -因为 react-helmet 暂不支持 stream 渲染,如果使用 Helmet ,请使用 `mode: 'string'` 方式渲染。[nfl/react-helmet#322](https://github.com/nfl/react-helmet/issues/322) - -### antd pro 怎样使用服务端渲染? - -首先,[antd pro](https://github.com/ant-design/ant-design-pro/) 作为中后台项目,没有 SEO 需求,不适合做服务端渲染; -从技术角度来讲,antd pro 在 render 里大量使用 DOM/BOM 方法,服务端渲染将 DOM/BOM 操作改至副作用(`useEffect` 或 `componentDidMount` 周期中),可以给 antd pro 提 PR。 - -### 为什么不能 external 服务端中的一些模块 - -1. 因为 umi 内部模块大量使用了 `alias`,如果做 external 会做大量模块的路径映射,真正在服务端使用时,会出现某些包路径不对,加载不了的报错 -1. 有些模块需要依赖模块实例才会做服务端渲染(例如 [react-helmet](https://github.com/nfl/react-helmet))为了保持同一实例,不会使用 external -1. 经过测试,服务端包 external 后与不 external,在 [TTFB](https://baike.baidu.com/item/TTFB)(发出页面请求到接收到应答数据第一个字节所花费的毫秒数)没有明显区别 - -综合考虑,Umi 3 SSR 不会对服务端文件(`umi.server.js`)做 external。 - -### `Prop `dangerouslySetInnerHTML` did not match.` 报错 - -只有 `div` 标签 `dangerouslySetInnerHTML` 属性才能被 SSR 渲染,正常的写法应该是: - -```diff --

Hello

' }} /> -+
Hello

' }} /> -``` - -### 如何判断当前页面是 SSR 还是 CSR? +--- -查看网页源代码,如果 `
` DOM 里的元素不为空,则是 SSR,否则为 CSR。 +I hope this translation helps you understand Server-Side Rendering (SSR) in the context of Umi and its related features and configurations. If you have any more questions or need further assistance, please feel free to ask! From c6f17477eb934769b9396f9f6104e467288f556b Mon Sep 17 00:00:00 2001 From: "MR. HASAN" Date: Mon, 4 Sep 2023 01:29:35 +0600 Subject: [PATCH 11/14] Update ssr.md --- docs/docs/ssr.md | 251 +++++++++++++++++++++++++++-------------------- 1 file changed, 147 insertions(+), 104 deletions(-) diff --git a/docs/docs/ssr.md b/docs/docs/ssr.md index 2733986e0c0a..cd4f722a6a0b 100644 --- a/docs/docs/ssr.md +++ b/docs/docs/ssr.md @@ -1,53 +1,51 @@ - - # Server-Side Rendering (SSR) ## What is Server-Side Rendering? -> First, let's understand what it is and whether it suits our business scenario before deciding whether to use it. +First, let's understand what it is and whether it fits our business scenario before deciding whether to use it. -Server-Side Rendering (SSR) is a page processing technique performed on the **server side** to assemble the HTML structure of a page, send it to the browser, and then bind its state and events, turning it into a fully interactive page. +Server-Side Rendering (SSR) refers to the process of rendering the HTML structure of a page on the server side, sending it to the browser, and then binding the state and events to make it a fully interactive page. -This might sound a bit academic, so let's make it clearer with two images. +This may sound a bit academic, so let's clarify it with two images. -The first image illustrates the difference between Single Page Applications (SPAs) and sites that have undergone Server-Side Rendering (SSR) when it comes to **social sharing**: +The first image illustrates the difference between a Single Page Application (SPA) and a server-side rendered (SSR) site when it comes to **social sharing**: -![SPAs vs. SSR for Social Sharing](https://user-images.githubusercontent.com/13595509/68102160-5e66da00-ff0c-11e9-82e8-7c73cca1b20f.png) +![SPA vs. SSR for Social Sharing](https://user-images.githubusercontent.com/13595509/68102160-5e66da00-ff0c-11e9-82e8-7c73cca1b20f.png) -The second image shows that SSR has less **white screen time** because when the HTML document is returned, it already has the corresponding content (see Network): +The second image shows the difference in **initial loading time** between SSR and CSR. SSR generally has a shorter time to the first byte (TTFB) because the corresponding content is already present when the HTML document is returned (see Network): -![SSR vs. CSR White Screen Time](https://user-images.githubusercontent.com/13595509/80308316-e74a3880-8800-11ea-9a20-2d9d153fe9d1.png) +![SSR vs. CSR Initial Loading Time](https://user-images.githubusercontent.com/13595509/80308316-e74a3880-8800-11ea-9a20-2d9d153fe9d1.png) From these two images, we can see that SSR is commonly used in the following two scenarios: -1. When there is a **need for SEO**, it is used for search engine indexing and social sharing, typically in frontend applications. -2. When there are requirements for the **initial screen rendering time**, it is often used in mobile applications or under weak network conditions. +1. **SEO Requirements**: Used for search engine indexing and social sharing, typically in frontend applications. +2. **First Screen Rendering Performance**: Used when there are performance requirements for the initial rendering, especially on mobile devices or in low network conditions. -In other words, if you are building a backend application (such as antd pro or admin dashboards), please carefully consider whether to use SSR. +In other words, if you are building a backend-heavy application (such as antd pro or admin dashboards), you should carefully consider whether to use SSR. ## What is Pre-rendering? -Server-Side Rendering requires a backend server (usually Node.js) to work. If you don't have a backend server but still want to use SSR for the two scenarios mentioned above, it is recommended to use **pre-rendering**. +Server-Side Rendering requires a backend server (usually Node.js) to be available. If you don't have a backend server but want to achieve the same benefits in the scenarios mentioned above, you can use **pre-rendering**. -The only difference between pre-rendering and server-side rendering is the **timing of rendering**. Server-side rendering occurs when a user accesses the page (real-time rendering, with data generally being the latest), while pre-rendering occurs during project build time. When a user accesses the page, the data may not be the latest (if the data doesn't need to be real-time, pre-rendering can be a good choice). +The only difference between pre-rendering and server-side rendering is the **timing** of rendering. Server-Side Rendering renders when a user accesses the page (i.e., **server-side rendering**), and the data is usually the latest. Pre-rendering, on the other hand, renders during project build time, so the data may not be the latest (if real-time data is not required). -Pre-rendering (Pre Render) performs rendering during the build process, generating static HTML fragments after rendering. It does not require real-time dynamic HTML compilation using a web server and is suitable for **static site generation**. +Pre-rendering (Pre Render) performs rendering during project build, generating static HTML fragments. It doesn't require real-time compilation of HTML on a web server and is suitable for **static site generation**. ## Umi Server-Side Rendering Features -> Umi has had SSR capabilities since Umi 2.8+. However, it was relatively challenging for beginners to use. +Starting from Umi 2.8+, Umi had SSR capabilities. However, for newcomers, it had a relatively high learning curve. -Umi 3, in combination with its own business scenarios, has made significant optimizations and improvements to SSR, offering the following features: +In Umi 3, significant optimizations and improvements have been made to SSR in line with real-world business scenarios, resulting in the following features: -- **Out of the Box**: SSR is built-in and can be enabled with one click. You can preview SSR with `umi dev`, making development and debugging convenient. -- **Server Framework Agnostic**: Umi is not tied to any specific server framework (e.g., [Egg.js](https://eggjs.org/), [Express](https://expressjs.com/), [Koa](https://koajs.com/)). It can be easily integrated with any framework or used in Serverless mode. -- **Support for Data Pre-fetching at the Application and Page Levels**: In Umi 3, data pre-fetching (getInitialProps) from Umi 2 has been continued to address the issue of fetching global data in the past. -- **Support for On-Demand Loading**: With dynamicImport enabled, Umi 3 will load corresponding resource files (CSS/JS) based on different routes. -- **Built-In Pre-rendering Functionality**: Umi 3 includes pre-rendering functionality built-in, eliminating the need for additional plugins. By enabling `ssr` and `exportStatic`, Umi will compile the rendered HTML during `umi build`. -- **Support for Rendering Fallback**: SSR is preferred, but if server-side rendering fails, it automatically falls back to client-side rendering (CSR) without affecting normal business processes. -- **Support for Streaming Rendering**: You can enable streaming rendering with `ssr: { mode: 'stream' }`, which results in less [Time to First Byte (TTFB)](https://en.wikipedia.org/wiki/Time_to_first_byte) compared to regular SSR. -- **Compatible with Client-Side Dynamic Loading**: While using SSR and dynamicImport (dynamic loading) together had some issues in Umi 2, in Umi 3, you can use them simultaneously. -- **Modularized SSR Features**: Umi 3 provides essential SSR features, but if your requirements are not met or you want to customize the rendering process, you can do so through the provided API. +- **Out of the Box**: SSR is built-in and can be easily enabled with a single command, `umi dev` for SSR preview, making development and debugging convenient. +- **Server Framework Agnostic**: Umi does not tightly couple with server frameworks (e.g., [Egg.js](https://eggjs.org/), [Express](https://expressjs.com/), [Koa](https://koajs.com/)). It can be easily integrated with any framework or Serverless mode. +- **Support for Application and Page-Level Data Pre-fetching**: Umi 3 continues the page data pre-fetching feature (getInitialProps) from Umi 2 to address the previous challenge of global data retrieval. +- **Support for On-Demand Loading**: With `dynamicImport` enabled, Umi 3 loads corresponding resource files (CSS/JS) based on different routes. +- **Built-In Pre-rendering**: Umi 3 includes pre-rendering functionality out of the box, no need to install additional plugins. When `ssr` and `exportStatic` are enabled, it compiles the rendered HTML during `umi build`. +- **Support for Rendering Degradation**: Umi 3 prioritizes SSR but automatically falls back to Client-Side Rendering (CSR) if server-side rendering fails, without disrupting normal business processes. +- **Support for Streaming Rendering**: Enabling `ssr: { mode: 'stream' }` enables streaming rendering, resulting in shorter [Time to First Byte (TTFB)](https://en.wikipedia.org/wiki/Time_to_first_byte) time compared to normal SSR. +- **Compatible with Client-Side Dynamic Loading**: Umi 3 allows simultaneous use of SSR and dynamicImport (dynamic loading) without issues. +- **Modular SSR Functionality**: Umi 3's built-in SSR functionality is sufficient for most use cases, but if it doesn't meet your needs or you want to customize the rendering method, you can do so through the provided API. ## Enabling Server-Side Rendering @@ -61,13 +59,13 @@ export default { ## Development -Run `umi dev`, access the page, and you will see the server-side rendered output. +Execute `umi dev`, access the page, and you'll see server-side rendering in action. -![SSR Development](https://user-images.githubusercontent.com/13595509/80309380-4743dd80-8807-11ea-9def-7bb43522dce3.png) +![Server-Side Rendering in Development](https://user-images.githubusercontent.com/13595509/80309380-4743dd80-8807-11ea-9def-7bb43522dce3.png) -> [How to determine whether the current page is SSR or CSR?](#how-to-determine-whether-the-current-page-is-ssr-or-csr) +> [How to Determine If the Current Page Is SSR or CSR?](#how-to-determine-if-the-current-page-is-ssr-or-csr) -If you are using it in conjunction with a backend framework in development mode, you can disable server-side rendering behavior with the following configuration: +If you're using it alongside a backend framework during development, you can disable server-side rendering behavior in `umi dev` through configuration: ```js @@ -76,103 +74,148 @@ export default { // Default is true devServerRender: false, }, + + } ``` -## Data Pre-fetching +## Configuration + +Umi 3's SSR configuration is simple and clear, and you can use a variety of options to meet your business needs. -The data-fetching mechanism for server-side rendering is different from Single Page Applications (SPAs). To ensure that both the client and server receive the same data, Umi provides page-level data pre-fetching. +The default configuration is as follows: -### Page-Level Data Pre-fetching +```js +export default { + ssr: { + devServerRender: true, + mode: 'stream', + }, +} +``` -Each page may have its own data pre-fetching logic. Here, we retrieve the `getInitialProps` static method from the page component and inject its result into the component's `props`, for example: +- `devServerRender`: Determines whether server-side rendering is enabled during development. The default is `true`. If set to `false`, the server will not perform rendering during development, and it will be up to you to determine whether the current page is in CSR or SSR mode. +- `mode`: The server-side rendering mode. The default is `'stream'`, which means streaming rendering is enabled. In streaming mode, the server renders and sends the HTML content in chunks as it's generated, resulting in a faster [Time to First Byte (TTFB)](https://en.wikipedia.org/wiki/Time_to_first_byte) compared to non-streaming mode. If you don't need streaming rendering, you can set it to `'normal'`. -```tsx -// pages/index.tsx -import { IGetInitialProps } from 'umi'; -import React from 'react'; +These configurations can be adjusted according to your needs. -const Home = (props) => { - const { data } = props; - return ( - {/*
Hello World
*/} -
{data.title}
- ) +## How to Determine If the Current Page Is SSR or CSR? + +If `devServerRender` is enabled, you can use the following methods to determine whether the current page is in SSR or CSR mode: + +### 1. Use `window.G_USE_SSR` in JavaScript + +In JavaScript code, you can check the `window.G_USE_SSR` global variable to determine if the page is in SSR mode: + +```javascript +if (window.G_USE_SSR) { + // Server-side rendering (SSR) mode +} else { + // Client-side rendering (CSR) mode } +``` -Home.getInitialProps = (async (ctx) => { - return Promise.resolve({ - data: { - title: 'Hello World', - } - }) -}) as IGetInitialProps; +This variable is automatically set by Umi based on the SSR configuration. -export default Home; +### 2. Use `isServer()` in JavaScript + +You can also use the `isServer()` function provided by Umi to check if the current code is running on the server side: + +```javascript +import { isServer } from 'umi'; + +if (isServer()) { + // Server-side rendering (SSR) mode +} else { + // Client-side rendering (CSR) mode +} ``` -The `getInitialProps` method has several fixed parameters: +This function returns `true` if the code is running on the server side and `false` if it's running on the client side. -- `match`: Contains relevant data about the current route, consistent with `match` in the client-side page props. -- `isServer`: Indicates whether the method is executed on the server side. -- `route`: Current route object. -- `history`: History object. +### 3. Use `window.G_SSR_ENV` in Template -### Extending `ctx` Parameters +In template files (e.g., JSX or EJS), you can check the `window.G_SSR_ENV` variable to determine if the page is in SSR mode: -To integrate with data +```jsx +{window.G_SSR_ENV ? ( +
Server-side rendering (SSR) mode
+) : ( +
Client-side rendering (CSR) mode
+)} +``` --fetching, you can extend the `ctx` object parameters. For example: +This variable is automatically set by Umi based on the SSR configuration. -```tsx -Home.getInitialProps = (async (ctx) => { - ctx.params // url parameters - ctx.query // query parameters - ctx.req // request object, only available on the server side - ctx.res // response object, only available on the server side - ctx.pathname // current page path - ctx.isMobile // indicates whether the client is a mobile device (judged by user-agent) - ctx.initialState // for passing server-side data to the client side +These methods allow you to conditionally render content or execute code based on whether the page is in SSR or CSR mode, giving you control over the behavior of your application. - return Promise.resolve({ - data: { - title: 'Hello World', - } - }) -}) as IGetInitialProps; +## Deployment + +When deploying your Umi SSR application to production, you need to ensure that the server is properly configured to handle SSR requests. Here are the general steps for deploying a Umi SSR application: + +1. **Build the Application**: Use the `umi build` command to build your Umi application. This command will generate the necessary files for production deployment. + +```bash +umi build ``` -Please note that if you need to use server-side data on the client side, you need to pass it to `ctx.initialState`. Umi will serialize `ctx.initialState` and pass it to the client side. - -## Page-Level Document Configuration - -You can configure the document of each page separately. Create a `document.ejs` file under the `src` directory of the page and customize it. - -For example: - -```html - - - - <%= title %> - - -
- <% if (isDev) { %> - - - <% } else { %> - - - <% } %> - - +2. **Set Up a Production Server**: You'll need a production server to host your Umi SSR application. This server can be based on Node.js or any other compatible environment. + +3. **Configure Server Routing**: Configure your production server to handle SSR requests. You'll typically need to create a server file that sets up routing and SSR rendering. In Umi, you can use the `umi.server.js` file for this purpose. + +Here's an example of a simple Node.js server file for Umi SSR: + +```javascript +const express = require('express'); +const { createServer } = require('http'); +const { render } = require('@umijs/server'); +const { join } = require('path'); + +const app = express(); + +// Serve static files (e.g., CSS, JavaScript) from the "dist" directory +app.use(express.static(join(__dirname, 'dist'))); + +app.get('*', async (req, res) => { + const { error, html } = await render({ + cwd: __dirname, + path: req.url, + getInitialPropsCtx: {}, + mode: 'stream', // Use 'stream' mode for SSR + }); + + if (error) { + console.error(error); + res.status(500).send('Internal Server Error'); + } else { + res.write(html); + res.end(); + } +}); + +const server = createServer(app); + +const PORT = process.env.PORT || 3000; + +server.listen(PORT, () => { + console.log(`Server is running on port ${PORT}`); +}); ``` -## Deployment +4. **Set Environment Variables**: Configure any necessary environment variables for your production server, such as the port number and other server-specific settings. + +5. **Start the Production Server**: Start your production server to make your Umi SSR application accessible to users. + +6. **Deploy to Hosting Provider**: Deploy your production server and Umi SSR application to a hosting provider or server infrastructure of your choice. This could be a cloud hosting platform, a dedicated server, or a containerized environment, depending on your needs. + +7. **Monitor and Optimize**: Monitor your SSR application in production and optimize it for performance, scalability, and reliability as needed. + +Keep in mind that the exact deployment process may vary depending on your hosting environment and requirements. Make sure to follow best practices for securing and maintaining your production server. + +## Conclusion -Please refer to the [official documentation](https://umijs.org/docs/ssr) for SSR deployment details. +Server-Side Rendering (SSR) in Umi.js offers a powerful way to improve SEO, initial loading performance, and user experience in your React-based applications. It enables you to pre-render pages on the server side and deliver them as fully interactive HTML, making your content more accessible to search engines and users. ---- +By following the steps outlined in this guide, you can enable SSR in your Umi.js application, configure it for development and production, and deploy it to a production server. Whether you're building a single-page app or a complex web application, SSR can be a valuable tool in your toolkit for achieving better SEO and faster initial loading times. -I hope this translation helps you understand Server-Side Rendering (SSR) in the context of Umi and its related features and configurations. If you have any more questions or need further assistance, please feel free to ask! +As you work with Umi SSR, be sure to explore its documentation and stay up-to-date with any updates or changes to the framework. Additionally, consider implementing best practices for SEO, performance optimization, and server-side rendering to get the most out of your SSR-enabled Umi.js application. From 608a97b31a53060d04a3f56e408a09174ecc6919 Mon Sep 17 00:00:00 2001 From: "MR. HASAN" Date: Mon, 4 Sep 2023 01:32:42 +0600 Subject: [PATCH 12/14] Update ssr.md --- docs/docs/ssr.md | 306 +++++++++++++++++++++++++++-------------------- 1 file changed, 178 insertions(+), 128 deletions(-) diff --git a/docs/docs/ssr.md b/docs/docs/ssr.md index cd4f722a6a0b..e9e0a73b69a9 100644 --- a/docs/docs/ssr.md +++ b/docs/docs/ssr.md @@ -2,56 +2,56 @@ ## What is Server-Side Rendering? -First, let's understand what it is and whether it fits our business scenario before deciding whether to use it. +> First, let's understand what it is and whether it fits our business scenario before deciding whether to use it. -Server-Side Rendering (SSR) refers to the process of rendering the HTML structure of a page on the server side, sending it to the browser, and then binding the state and events to make it a fully interactive page. +Server-Side Rendering (SSR) is a page rendering technique where the HTML structure of a page is assembled on the **server side**, sent to the browser, and then the state and events are bound to it, turning it into a fully interactive page. -This may sound a bit academic, so let's clarify it with two images. +This might sound a bit academic, so let's make it clearer with two images. The first image illustrates the difference between a Single Page Application (SPA) and a server-side rendered (SSR) site when it comes to **social sharing**: -![SPA vs. SSR for Social Sharing](https://user-images.githubusercontent.com/13595509/68102160-5e66da00-ff0c-11e9-82e8-7c73cca1b20f.png) +![Social Sharing Difference](https://user-images.githubusercontent.com/13595509/68102160-5e66da00-ff0c-11e9-82e8-7c73cca1b20f.png) -The second image shows the difference in **initial loading time** between SSR and CSR. SSR generally has a shorter time to the first byte (TTFB) because the corresponding content is already present when the HTML document is returned (see Network): +The second image shows the difference in **initial load time** between SSR and CSR. SSR has less white screen time because it already has content when the HTML document returns (see Network): -![SSR vs. CSR Initial Loading Time](https://user-images.githubusercontent.com/13595509/80308316-e74a3880-8800-11ea-9a20-2d9d153fe9d1.png) +![Initial Load Time Difference](https://user-images.githubusercontent.com/13595509/80308316-e74a3880-8800-11ea-9a20-2d9d153fe9d1.png) -From these two images, we can see that SSR is commonly used in the following two scenarios: +Based on these two images, SSR is commonly used in the following two scenarios: -1. **SEO Requirements**: Used for search engine indexing and social sharing, typically in frontend applications. -2. **First Screen Rendering Performance**: Used when there are performance requirements for the initial rendering, especially on mobile devices or in low network conditions. +1. **SEO Requirements**: It's used for search engine indexing and social sharing, typically in frontend applications. +2. **Fast Initial Rendering**: It's used when there are requirements for fast initial rendering, often in mobile applications or under poor network conditions. -In other words, if you are building a backend-heavy application (such as antd pro or admin dashboards), you should carefully consider whether to use SSR. +> In other words, if you're building an admin or backend application (such as antd pro or a management dashboard), think carefully about whether to use SSR. ## What is Pre-rendering? -Server-Side Rendering requires a backend server (usually Node.js) to be available. If you don't have a backend server but want to achieve the same benefits in the scenarios mentioned above, you can use **pre-rendering**. +Server-Side Rendering requires a backend server (usually Node.js) to work. If you don't have a backend server but still want to achieve the goals mentioned above, you can use **pre-rendering**. -The only difference between pre-rendering and server-side rendering is the **timing** of rendering. Server-Side Rendering renders when a user accesses the page (i.e., **server-side rendering**), and the data is usually the latest. Pre-rendering, on the other hand, renders during project build time, so the data may not be the latest (if real-time data is not required). +The key difference between pre-rendering and server-side rendering is the **timing of rendering**. Server-side rendering happens when a user accesses the page (i.e., **server-side rendering**), and the data is generally the most up-to-date. Pre-rendering, on the other hand, occurs during project build time, and when a user accesses the page, the data might not be the most up-to-date (pre-rendering is suitable when data doesn't need to be real-time). -Pre-rendering (Pre Render) performs rendering during project build, generating static HTML fragments. It doesn't require real-time compilation of HTML on a web server and is suitable for **static site generation**. +Pre-rendering (Pre Render) involves rendering during the build process to generate static HTML fragments. It doesn't require real-time dynamic HTML compilation by a web server and is suitable for **static site generation**. ## Umi Server-Side Rendering Features -Starting from Umi 2.8+, Umi had SSR capabilities. However, for newcomers, it had a relatively high learning curve. +> As early as Umi 2.8+, Umi already had SSR capabilities, but it had a higher learning curve for newcomers. -In Umi 3, significant optimizations and improvements have been made to SSR in line with real-world business scenarios, resulting in the following features: +With Umi 3, significant optimizations and improvements have been made to SSR based on its specific business scenarios, offering the following features: -- **Out of the Box**: SSR is built-in and can be easily enabled with a single command, `umi dev` for SSR preview, making development and debugging convenient. -- **Server Framework Agnostic**: Umi does not tightly couple with server frameworks (e.g., [Egg.js](https://eggjs.org/), [Express](https://expressjs.com/), [Koa](https://koajs.com/)). It can be easily integrated with any framework or Serverless mode. -- **Support for Application and Page-Level Data Pre-fetching**: Umi 3 continues the page data pre-fetching feature (getInitialProps) from Umi 2 to address the previous challenge of global data retrieval. -- **Support for On-Demand Loading**: With `dynamicImport` enabled, Umi 3 loads corresponding resource files (CSS/JS) based on different routes. -- **Built-In Pre-rendering**: Umi 3 includes pre-rendering functionality out of the box, no need to install additional plugins. When `ssr` and `exportStatic` are enabled, it compiles the rendered HTML during `umi build`. -- **Support for Rendering Degradation**: Umi 3 prioritizes SSR but automatically falls back to Client-Side Rendering (CSR) if server-side rendering fails, without disrupting normal business processes. -- **Support for Streaming Rendering**: Enabling `ssr: { mode: 'stream' }` enables streaming rendering, resulting in shorter [Time to First Byte (TTFB)](https://en.wikipedia.org/wiki/Time_to_first_byte) time compared to normal SSR. -- **Compatible with Client-Side Dynamic Loading**: Umi 3 allows simultaneous use of SSR and dynamicImport (dynamic loading) without issues. -- **Modular SSR Functionality**: Umi 3's built-in SSR functionality is sufficient for most use cases, but if it doesn't meet your needs or you want to customize the rendering method, you can do so through the provided API. +- **Out of the Box**: SSR is built-in and can be easily enabled with a single command, `umi dev`, making development and debugging convenient. +- **Server Framework Agnostic**: Umi doesn't couple with server frameworks like [Egg.js](https://eggjs.org/), [Express](https://expressjs.com/), or [Koa](https://koajs.com/). It can be integrated seamlessly with any framework or Serverless mode. +- **Support for Data Pre-fetching at the Application and Page Level**: Umi 3 continues the page data pre-fetching (getInitialProps) feature from Umi 2 to solve the problem of fetching global data in the previous version. +- **Support for Lazy Loading**: With `dynamicImport` enabled, Umi 3 will load corresponding resource files (CSS/JS) based on different routes. +- **Built-in Pre-rendering**: Umi 3 includes pre-rendering functionality out of the box. You no longer need to install additional plugins. Simply enable `ssr` and `exportStatic`, and Umi will compile the rendered HTML during `umi build`. +- **Support for Rendering Degradation**: Umi 3 prioritizes SSR. If server-side rendering fails, it automatically falls back to client-side rendering (CSR) without disrupting normal business processes. +- **Support for Streaming Rendering**: Enabling `ssr: { mode: 'stream' }` allows streaming rendering, which results in shorter [TTFB](https://baike.baidu.com/item/TTFB) (Time To First Byte) times compared to normal SSR. +- **Compatible with Client-Side Dynamic Loading**: In Umi 2, using both SSR and dynamicImport (dynamic loading) had some issues. In Umi 3, you can use them simultaneously. +- **Modular SSR Features**: While Umi 3's built-in SSR features are quite comprehensive, if your requirements are not met or you want to customize the rendering method, you can do so using the provided APIs. ## Enabling Server-Side Rendering By default, server-side rendering is disabled. You need to enable it through configuration: -```js +```javascript export default { ssr: {}, } @@ -59,163 +59,213 @@ export default { ## Development -Execute `umi dev`, access the page, and you'll see server-side rendering in action. +Execute `umi dev` to access the page, and it will be server-side rendered. ![Server-Side Rendering in Development](https://user-images.githubusercontent.com/13595509/80309380-4743dd80-8807-11ea-9def-7bb43522dce3.png) -> [How to Determine If the Current Page Is SSR or CSR?](#how-to-determine-if-the-current-page-is-ssr-or-csr) - -If you're using it alongside a backend framework during development, you can disable server-side rendering behavior in `umi dev` through configuration: +> [How to Determine Whether the Current Page Is SSR or CSR?](#how-to-determine-whether-the-current-page-is-ssr-or-csr) -```js +If you're using it together with a backend framework in development mode, you can disable server-side rendering behavior under `umi dev` with the following configuration: +```javascript export default { ssr: { - // Default is true + // Defaults to true devServerRender: false, }, - - } ``` -## Configuration +## Data Pre-fetching -Umi 3's SSR configuration is simple and clear, and you can use a variety of options to meet your business needs. +Data retrieval in server-side rendering differs from Single Page Applications (SPAs). To ensure that both the client and server have access to the same data, Umi 3 provides **page-level data pre-fetching**. -The default configuration is as follows: +### Page-Level Data Pre-fetching -```js -export default { - ssr: { - devServerRender: true, - mode: 'stream', - }, +Each page may have its own data pre-fetching logic. Here, we retrieve the `getInitialProps` static method from the page component, which is then executed, and its result is injected into the page component's `props`. For example: + +```jsx +// pages/index.tsx +import { IGetInitialProps } from 'umi'; +import React from 'react'; + +const Home = (props) => { + const { data } = props; + return ( + {/*
Hello World
*/} +
{data.title}
+ ) } + +Home.getInitialProps = (async (ctx) => { + return Promise.resolve({ + data: { + title: 'Hello World', + } + }) +}) as IGetInitialProps; + +/** You can also use a class component: +class Home extends React.Component { + static getInitialProps = (async (ctx) => { + return Promise.resolve({ + data: { + title: 'Hello World', + } + }) + }) as IGetInitialProps; + + render() { + const { data } = props; + return ( +
{data.title} + ) + } +} +*/ +export default Home; ``` -- `devServerRender`: Determines whether server-side rendering is enabled during development. The default is `true`. If set to `false`, the server will not perform rendering during development, and it will be up to you to determine whether the current page is in CSR or SSR mode. -- `mode`: The server-side rendering mode. The default is `'stream'`, which means streaming rendering is enabled. In streaming mode, the server renders and sends the HTML content in chunks as it's generated, resulting in a faster [Time to First Byte (TTFB)](https://en.wikipedia.org/wiki/Time_to_first_byte) compared to non-streaming mode. If you don't need streaming rendering, you can set it to `'normal'`. +> `getInitialProps` should be an `async` function. After switching to Umi 3, existing `getInitialProps` will work without any changes. -These configurations can be adjusted according to your needs. +#### Data Pre-fetching Execution Timing -## How to Determine If the Current Page Is SSR or CSR? +- **Server Side**: In server-side rendering, `getInitialProps` is executed on the server side, and the result is sent to the client as part of the initial HTML. -If `devServerRender` is enabled, you can use the following methods to determine whether the current page is in SSR or CSR mode: +- **Client Side**: On the client side, `getInitialProps` is executed as a normal React lifecycle method (componentDidMount). It won't be executed during server-side rendering if `shouldPrefetch` is set to `false`. The data is passed to the component as `props`. -### 1. Use `window.G_USE_SSR` in JavaScript +#### Data Pre-fetching in Detail -In JavaScript code, you can check the `window.G_USE_SSR` global variable to determine if the page is in SSR mode: +Let's break down how data pre-fetching works in Umi 3: -```javascript -if (window.G_USE_SSR) { - // Server-side rendering (SSR) mode -} else { - // Client-side rendering (CSR) mode -} -``` +1. On the server side, when a user accesses a page, Umi 3 first routes the request to the appropriate page component. -This variable is automatically set by Umi based on the SSR configuration. +2. If the page component has a `getInitialProps` method defined (it's optional), Umi 3 executes it and awaits the result. -### 2. Use `isServer()` in JavaScript +3. Once the `getInitialProps` method completes (whether by resolving or rejecting the returned Promise), Umi 3 injects the result into the component's `props`. -You can also use the `isServer()` function provided by Umi to check if the current code is running on the server side: +4. The page component is then rendered with the pre-fetched data on the server side. The HTML is sent to the browser. -```javascript -import { isServer } from 'umi'; +5. On the client side, when the browser receives the HTML, it also receives the pre-fetched data. The page component on the client side is rehydrated (React's term for initializing the component with existing data), and the data is used for rendering. -if (isServer()) { - // Server-side rendering (SSR) mode -} else { - // Client-side rendering (CSR) mode -} -``` +6. On subsequent client-side navigations within the app, `getInitialProps` will be executed on the client side, not on the server side, unless `shouldPrefetch` is set to `false`. -This function returns `true` if the code is running on the server side and `false` if it's running on the client side. +### API-Level Data Pre-fetching -### 3. Use `window.G_SSR_ENV` in Template +In addition to page-level data pre-fetching with `getInitialProps`, Umi 3 also supports **API-level data pre-fetching**. This allows you to fetch data in the layout component (or any component) that wraps your pages and share that data with multiple pages. -In template files (e.g., JSX or EJS), you can check the `window.G_SSR_ENV` variable to determine if the page is in SSR mode: +API-level data pre-fetching can be achieved using the `getInitialProps` method in your layout component: -```jsx -{window.G_SSR_ENV ? ( -
Server-side rendering (SSR) mode
-) : ( -
Client-side rendering (CSR) mode
-)} +```javascript +// layouts/index.tsx +import { IGetInitialProps } from 'umi'; + +const Layout: React.FC = ({ children }) => { + return ( +
+ {/* Your layout content */} + {children} +
+ ); +}; + +Layout.getInitialProps = async (ctx) => { + // Fetch data and return it as an object + const data = await fetchData(); + + return { data }; +}; + +export default Layout; ``` -This variable is automatically set by Umi based on the SSR configuration. +In this example, the `Layout` component fetches data using `getInitialProps` and makes it available to all child pages wrapped by this layout. Child pages can access this data through their own `getInitialProps` or by simply accessing it from `props`. -These methods allow you to conditionally render content or execute code based on whether the page is in SSR or CSR mode, giving you control over the behavior of your application. +### Caching Data Pre-fetched on the Server -## Deployment +To prevent redundant data fetching, you can use caching mechanisms when pre-fetching data on the server side. Caching helps improve the performance and efficiency of your SSR application. -When deploying your Umi SSR application to production, you need to ensure that the server is properly configured to handle SSR requests. Here are the general steps for deploying a Umi SSR application: +Here's a basic example of caching pre-fetched data using the popular `lru-cache` library: -1. **Build the Application**: Use the `umi build` command to build your Umi application. This command will generate the necessary files for production deployment. +```javascript +// pages/index.tsx +import { IGetInitialProps } from 'umi'; +import React from 'react'; +import LRU from 'lru-cache'; + +const cache = new LRU({ + max: 500, // Maximum cache size + maxAge: 1000 * 60 * 60, // Cache data for 1 hour +}); -```bash -umi build -``` +const fetchData = async () => { + // Check if the data is in the cache + const cachedData = cache.get('data'); -2. **Set Up a Production Server**: You'll need a production server to host your Umi SSR application. This server can be based on Node.js or any other compatible environment. + if (cachedData) { + return cachedData; + } -3. **Configure Server Routing**: Configure your production server to handle SSR requests. You'll typically need to create a server file that sets up routing and SSR rendering. In Umi, you can use the `umi.server.js` file for this purpose. + // Fetch the data if it's not in the cache + const response = await fetch('https://api.example.com/data'); + const data = await response.json(); -Here's an example of a simple Node.js server file for Umi SSR: + // Store the data in the cache + cache.set('data', data); -```javascript -const express = require('express'); -const { createServer } = require('http'); -const { render } = require('@umijs/server'); -const { join } = require('path'); - -const app = express(); - -// Serve static files (e.g., CSS, JavaScript) from the "dist" directory -app.use(express.static(join(__dirname, 'dist'))); - -app.get('*', async (req, res) => { - const { error, html } = await render({ - cwd: __dirname, - path: req.url, - getInitialPropsCtx: {}, - mode: 'stream', // Use 'stream' mode for SSR - }); - - if (error) { - console.error(error); - res.status(500).send('Internal Server Error'); - } else { - res.write(html); - res.end(); - } -}); + return data; +}; -const server = createServer(app); +const Home = (props) => { + const { data } = props; + return ( +
{data.title}
+ ); +}; -const PORT = process.env.PORT || 3000; +Home.getInitialProps = async (ctx) => { + return { + data: await fetchData(), + }; +}; -server.listen(PORT, () => { - console.log(`Server is running on port ${PORT}`); -}); +export default Home; ``` -4. **Set Environment Variables**: Configure any necessary environment variables for your production server, such as the port number and other server-specific settings. +In this example, we create a cache using `lru-cache` and use it to store fetched data. Before making a network request, we check if the data is already in the cache. If it is, we return the cached data; otherwise, we fetch it, store it in the cache, and return it. + +This caching mechanism helps reduce the load on your server and improves the response time for subsequent requests for the same data. + +Keep in mind that caching strategies may vary based on your specific requirements and the nature of your data. You can customize the caching logic to suit your needs. + +### Data Pre-fetching Pitfalls + +While data pre-fetching in server-side rendering is a powerful feature, it comes with some potential pitfalls and considerations: + +1. **Error Handling**: Ensure that you handle errors properly when fetching data in `getInitialProps`. If a data fetch fails on the server side, it can result in a failed SSR response. You should handle errors gracefully and possibly return default data or an error message to avoid breaking the entire page. + +2. **Data Hydration**: When pre-fetched data is passed to the client, make sure your client-side code can properly hydrate (initialize) components with this data. Mismatched data structures or unexpected null values can lead to client-side errors. + +3. **Data Fetching Redundancy**: Be mindful of redundant data fetching. Consider implementing caching strategies to avoid fetching the same data multiple times, both on the server and client sides. + +4. **Data Privacy**: Think about data privacy and security. Ensure that sensitive data is not exposed during server-side rendering and that any client-side data fetching adheres to security best practices. + +5. **Performance Impact**: Excessive or inefficient data pre-fetching can negatively impact performance. Be aware of the performance implications of your data fetching logic and optimize it as needed. -5. **Start the Production Server**: Start your production server to make your Umi SSR application accessible to users. +6. **Client-Side Re-fetching**: By default, `getInitialProps` may re-fetch data on the client side when navigating between pages. If this behavior is not desired, consider using client-side state management or caching to avoid unnecessary data fetches. -6. **Deploy to Hosting Provider**: Deploy your production server and Umi SSR application to a hosting provider or server infrastructure of your choice. This could be a cloud hosting platform, a dedicated server, or a containerized environment, depending on your needs. +7. **Loading Indicators**: Implement loading indicators or placeholders to provide a better user experience while data is being fetched, especially on the client side. -7. **Monitor and Optimize**: Monitor your SSR application in production and optimize it for performance, scalability, and reliability as needed. +8. **Testing**: Test your data pre-fetching logic thoroughly to catch potential issues early. Pay attention to edge cases and error scenarios. -Keep in mind that the exact deployment process may vary depending on your hosting environment and requirements. Make sure to follow best practices for securing and maintaining your production server. +9. **Documentation**: Document your data pre-fetching patterns and conventions, especially if multiple team members are working on the project. Clear documentation can help ensure consistency and reduce confusion. -## Conclusion +10. **Monitoring and Logging**: Implement monitoring and logging for data pre-fetching to track performance, detect errors, and troubleshoot issues in production. -Server-Side Rendering (SSR) in Umi.js offers a powerful way to improve SEO, initial loading performance, and user experience in your React-based applications. It enables you to pre-render pages on the server side and deliver them as fully interactive HTML, making your content more accessible to search engines and users. +### Conclusion -By following the steps outlined in this guide, you can enable SSR in your Umi.js application, configure it for development and production, and deploy it to a production server. Whether you're building a single-page app or a complex web application, SSR can be a valuable tool in your toolkit for achieving better SEO and faster initial loading times. +Data pre-fetching is a crucial aspect of server-side rendering in Umi 3. It enables you to fetch data on the server and include it in the initial HTML response, improving performance and SEO. By understanding the concepts and best -As you work with Umi SSR, be sure to explore its documentation and stay up-to-date with any updates or changes to the framework. Additionally, consider implementing best practices for SEO, performance optimization, and server-side rendering to get the most out of your SSR-enabled Umi.js application. + practices of data pre-fetching, you can build efficient and fast-rendering React applications with Umi 3. From cc13fae276595e0532003f70919c83c701e653d8 Mon Sep 17 00:00:00 2001 From: "MR. HASAN" Date: Mon, 4 Sep 2023 01:33:53 +0600 Subject: [PATCH 13/14] Update upgrade-to-umi-3.md --- docs/docs/upgrade-to-umi-3.md | 110 ++++++++++++++++------------------ 1 file changed, 53 insertions(+), 57 deletions(-) diff --git a/docs/docs/upgrade-to-umi-3.md b/docs/docs/upgrade-to-umi-3.md index 50bd98080c8e..ced86171a345 100644 --- a/docs/docs/upgrade-to-umi-3.md +++ b/docs/docs/upgrade-to-umi-3.md @@ -1,14 +1,10 @@ ---- -translateHelp: true ---- - # Upgrade to Umi 3 -本文档将帮助你从 Umi 2.x 版本升级到 Umi 3.x 版本。 +This document will guide you through the process of upgrading from Umi 2.x to Umi 3.x. ## package.json -修改 `umi` 的版本为 `^3.0.0` 或以上, +Update the version of `umi` to `^3.0.0` or higher in your `package.json`: ```diff { @@ -19,21 +15,21 @@ translateHelp: true } ``` -由于 Umi 3 需要 Node 10.13 或以上,如果之前有配 engines,需确认下版本号。 +Since Umi 3 requires Node 10.13 or higher, make sure to check your `engines` configuration if you had it defined previously. ## tsconfig.json -为了有更好的 ts 提示,需配置 `@@` 为 `["src/.umi/*"]`。 +For better TypeScript type checking, configure `@@` to `["src/.umi/*"]` in your `tsconfig.json`: ```diff + "@@/*": ["src/.umi/*"] ``` -## 升级 umi-plugin-react 为 @umijs/preset-react +## Upgrade `umi-plugin-react` to `@umijs/preset-react` -如果之前有使用 `umi-plugin-react`,以下是修改的步骤。 +If you were previously using `umi-plugin-react`, follow these steps to upgrade: -先在 package.json 中修改依赖, +First, update the dependency in your `package.json`: ```diff { @@ -44,7 +40,7 @@ translateHelp: true } ``` -然后由于 Umi 3 的配置方式是拍平的方式,还需要修改配置, +Then, because Umi 3 uses a flattened configuration format, you need to modify your configuration. Instead of using plugins, you'll directly configure your plugins and options: ```diff export default { @@ -61,59 +57,59 @@ export default { } ``` -注意: +Notes: -1. 无需重复注册插件,Umi 3 会自动注册依赖中的 Umi 插件 -2. 配置提取到外面 +1. There's no need to redundantly register plugins in Umi 3; Umi 3 will automatically register dependencies from your `package.json`. +2. Configuration has been extracted to the top level. -功能变化, +Changes in functionality: -- 删除了 routes、library、dll、hardSource、pwa、hd、fastClick、chunks,不可继续使用 -- 内置 dynamicImport、title、scripts、headScripts、metas 和 links 到 Umi 中,可继续使用 -- 其他功能不变 +- Removed `routes`, `library`, `dll`, `hardSource`, `pwa`, `hd`, `fastClick`, and `chunks`. These are no longer available. +- Built-in `dynamicImport`, `title`, `scripts`, `headScripts`, `metas`, and `links` into Umi, and they can still be used. +- Other functionalities remain unchanged. -## 配置层 +## Configuration Layer -Umi 3 在配置层做了大量精简,以下修改以字母排序,便于查找。 +Umi 3 has significantly streamlined the configuration layer. Below are modifications sorted alphabetically for easier reference: -- 删除 browserslist,和 targets 重复了 -- 删除 babel,基本用不上 -- 修改 cssLoaderOptions 命名为 cssLoader -- 删除 cssLoaderVersion,只保留 css-loader@2 的版本 -- 删除 cssPublicPath,css 引用的资源文件用相对路径 `./` 可满足所有场景,没有必要再配 -- 删除 disableGlobalVariables,始终无全局变量,无需配置 -- 删除 disableRedirectHoist,始终不再做 redirect hoist -- 删除 disableCSSModules 和 cssModulesWithAffix,Umi 3 自动识别 css modules 的使用,无需配置 -- 删除 extraBabelIncludes 和 es5ImcompatibleVersions,node_modules 也走 babel 编译后就没有意义了,无需配置 -- 修改 history 格式为 `{ type, options }` ,不再支持 string 格式 -- 修改 lessLoaderOptions 命名为 lessLoader -- 删除 minimizer,只保留 terserjs -- 修改 plugins 的格式为字符串,需要先确保依赖的插件是否升级到 Umi 3,然后修改方式参考前面 umi-plugin-react 的修改方式 -- 删除 sass,不再支持,后续会以插件的方式提供 -- 删除 treeShaking,已内置,无需配置 -- 删除 tsConfigFile,没有必要 -- 删除 typescript,TypeScript 编译交给 babel 处理后,之前 ts-loader 的配置就没有意义了 -- 删除 uglifyJSOptions,没有必要 -- 删除 urlLoaderExcludes,没有必要 +- Removed `browserslist`, as it was redundant with `targets`. +- Removed `babel`, which is rarely needed. +- Renamed `cssLoaderOptions` to `cssLoader`. +- Removed `cssLoaderVersion`, keeping only version 2 of `css-loader`. +- Removed `cssPublicPath`. Using a relative path `./` for CSS resource files covers all scenarios and eliminates the need for this configuration. +- Removed `disableGlobalVariables`, as there are no global variables by default, so no need for configuration. +- Removed `disableRedirectHoist`, as redirect hoisting is no longer performed. +- Removed `disableCSSModules` and `cssModulesWithAffix`. Umi 3 automatically detects the use of CSS modules, so no need for configuration. +- Removed `extraBabelIncludes` and `es5ImcompatibleVersions`. Compiling `node_modules` with Babel is no longer meaningful in Umi 3, so no need for configuration. +- Changed the format of `history` to `{ type, options }`, and string format is no longer supported. +- Renamed `lessLoaderOptions` to `lessLoader`. +- Removed `minimizer`, keeping only `terserjs`. +- Changed the format of `plugins` to strings. Ensure that the plugins you depend on have been updated to Umi 3, and then modify them as shown in the previous `umi-plugin-react` upgrade steps. +- Removed `sass`, which is no longer supported and will be provided as a plugin in the future. +- Removed `treeShaking`, as it's already built-in and doesn't require configuration. +- Removed `tsConfigFile`, as it's unnecessary. +- Removed `typescript`. After TypeScript compilation is handled by Babel, the previous `ts-loader` configuration is no longer needed. +- Removed `uglifyJSOptions`, as it's unnecessary. +- Removed `urlLoaderExcludes`, as it's unnecessary. -## 环境变量层 +## Environment Variable Layer -## 代码层 +## Code Layer -### import all from umi +### Import All from Umi -不再保留 `umi/xxx` 的接口,全部从 umi 中 import。 +All `umi/xxx` interfaces have been removed. Instead, import everything from `umi`. -比如: +For example: ```diff - import Link from 'umi/link'; + import { Link } from 'umi'; ``` -### umi/router +### `umi/router` -改用 `history` 代替。 +Replace `umi/router` with `history`. ```diff - import router from 'umi/router'; @@ -123,28 +119,28 @@ Umi 3 在配置层做了大量精简,以下修改以字母排序,便于查 + history.push('/foo'); ``` -### CSS 里引用别名或三方库 +### Referencing Aliases or Third-Party Libraries in CSS -需要加 `~` 前缀。 +You need to prefix with `~` when referencing aliases or third-party libraries in CSS. -比如: +For example: ```diff -# 别名 +# Aliases - background: url(@/assets/logo.png); + background: url(~@/assets/logo.png); -# 三方库 +# Third-party libraries - @import url(foo/bar.css); + @import url(~foo/bar.css); ``` -## 遇到问题 +## Troubleshooting -Umi v3 做了非常多的细节改进和重构,我们尽可能收集了已知的所有不兼容变化和相关影响,但是有可能还是有一些场景我们没有考虑到。如果你在升级过程中遇到了问题,请到 [Github issues](https://github.com/umijs/umi/issues) 进行反馈。我们会尽快响应和相应改进这篇文档。 +Umi 3 introduces numerous refinements and refactorings, and we've made every effort to collect all known breaking changes and related impacts. However, there might still be scenarios we haven't considered. If you encounter any issues during the upgrade process, please provide feedback on the [Github issues](https://github.com/umijs/umi/issues) page. We will respond promptly and make corresponding improvements to this document. -也可以加 "Umi 3 升级问题互帮互助" 群, +You can also join the "Umi 3 Upgrade Support" group by scanning the QR code below: - +![Umi 3 Upgrade Support QR Code](https://img.alicdn.com/imgextra/i1/O1CN01SXbs9I28PhUahMoWZ_!!6000000007925-0-tps-1170-1503.jpg) -扫上方二维码,并回复 **umi 3**。 +Scan the QR code and reply with **umi 3** to join the group for assistance. From efe13658d6016a9d57ffdede27e2951c3aa77d5d Mon Sep 17 00:00:00 2001 From: "MR. HASAN" Date: Mon, 4 Sep 2023 01:35:31 +0600 Subject: [PATCH 14/14] Update use-umi-ui.md --- docs/docs/use-umi-ui.md | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/docs/docs/use-umi-ui.md b/docs/docs/use-umi-ui.md index 8202e62b67a2..50cb9c8973d3 100644 --- a/docs/docs/use-umi-ui.md +++ b/docs/docs/use-umi-ui.md @@ -1,37 +1,31 @@ ---- -translateHelp: true ---- - # Using Umi UI +> Due to Umi 3's microkernel architecture, the previous Umi UI has been split into a [separate repository](https://github.com/umijs/umi-ui). You can use Umi UI by loading [@umijs/preset-ui](https://github.com/umijs/umi-ui#-%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B). -> 由于 Umi 3 使用微内核架构,将之前 Umi UI 拆分到[独立的仓库](https://github.com/umijs/umi-ui),通过加载 [@umijs/preset-ui](https://github.com/umijs/umi-ui#-%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B) 使用 Umi UI。 - -Umi 项目的本地研发工作台 +Local development workspace for Umi projects ![](https://user-images.githubusercontent.com/13595509/73431180-c77ab400-437a-11ea-9baa-ebd00109b1d0.png) -# ✨ 特性 +# ✨ Features -- 项目管理。集中式管理本地项目。 -- 配置管理。umi / bigfish 常用项目配置。 -- 任务管理。集成启动、构建、测试、代码规范检查、重新安装依赖等常用操作。 -- 资产、区块管理 +- Project management: Centralized management of local projects. +- Configuration management: Common project configurations for umi/bigfish. +- Task management: Integration of common operations such as starting, building, testing, code quality checking, and reinstallation of dependencies. +- Asset and block management -# 🔨 使用 +# 🔨 Usage -在项目中执行 +Execute the following commands in your project: ```bash $ yarn add @umijs/preset-ui -D $ UMI_UI=1 umi dev ``` -详见:[Umi UI 视频介绍](https://www.bilibili.com/video/av66178967)。 - +See: [Introduction to Umi UI (Video)](https://www.bilibili.com/video/av66178967). -# 🤔 未来 +# 🤔 Future -更强大的本地研发工作台。 +A more powerful local development workspace. ![](https://img.alicdn.com/tfs/TB1hKMGeND1gK0jSZFKXXcJrVXa-2000-1120.png)