### Initialize and Run UmiJS Project Source: https://v3.umijs.org/ Commands to create a directory, install dependencies, generate a page, and start the development server. ```bash # Create directory $ mkdir myapp && cd myapp # Install dependency $ yarn add umi # Create page $ npx umi g page index --typescript --less # Start development $ npx umi dev ``` -------------------------------- ### Install Dependencies Source: https://v3.umijs.org/docs/getting-started Install the project dependencies defined in package.json. ```bash $ yarn ``` -------------------------------- ### Start Development Server Source: https://v3.umijs.org/docs/getting-started Launch the local development server to preview the application. ```bash $ yarn start ``` -------------------------------- ### Environment Configuration Source: https://v3.umijs.org/docs/directory-structure Example of environment variable definitions in the .env file. ```text PORT=8888 COMPRESS=none ``` -------------------------------- ### Install Yarn Source: https://v3.umijs.org/docs/getting-started Install Yarn globally to manage project dependencies. ```bash # install yarn globally $ npm i yarn -g # confirm yarn version $ yarn -v ``` -------------------------------- ### Define multi-language files Source: https://v3.umijs.org/plugins/plugin-locale Example directory structure for internationalization files. ```text + src + locales -zh-CN.ts -en-US.ts + pages ``` -------------------------------- ### Dynamic Routing File Structure Source: https://v3.umijs.org/docs/convention-routing Example file structure for standard dynamic routing. ```text . └── pages └── [post] ├── index.tsx └── comments.tsx └── users └── [id].tsx └── index.tsx ``` -------------------------------- ### Install Yarn for Users in China Source: https://v3.umijs.org/docs/getting-started Use tyarn or ali-yarn to improve package installation performance in China. ```bash # install tyarn globally $ npm i yarn tyarn -g # confirm tyarn version $ tyarn -v # install yarn and @ali/yarn globally $ tnpm i yarn @ali/yarn -g # confirm ali yarn version $ ayarn -v ``` -------------------------------- ### Global Layout Directory Structure Source: https://v3.umijs.org/docs/convention-routing Example directory structure for a global layout using src/layouts/index.tsx. ```text . └── src ├── layouts │   └── index.tsx └── pages ├── index.tsx └── users.tsx ``` -------------------------------- ### Example File Structure for Convention Routing Source: https://v3.umijs.org/docs/convention-routing A sample directory structure showing how index.tsx and users.tsx files are organized within the pages directory. ```text . └── pages ├── index.tsx └── users.tsx ``` -------------------------------- ### Define Internationalization Keys Source: https://v3.umijs.org/plugins/plugin-locale Example locale files defining keys for site and page titles. ```javascript // src/locales/zh-CN.js export default { 'site.title': 'Site-Title', 'about.title': 'About-Title', }; // src/locales/en-US.js export default { 'site.title': 'English Title', 'about.title': 'About-Title', }; ``` -------------------------------- ### Dynamic Optional Routing File Structure Source: https://v3.umijs.org/docs/convention-routing Example file structure for optional dynamic routing using the [ $] syntax. ```text . └── pages └── [post$] └── comments.tsx └── users └── [id$].tsx └── index.tsx ``` -------------------------------- ### Enable esbuild compression Source: https://v3.umijs.org/guide Replace the default compressor with esbuild to improve build speed. Requires installing the @umijs/plugin-esbuild dependency. ```bash $ yarn add @umijs/plugin-esbuild ``` ```javascript export default { esbuild: {}, } ``` -------------------------------- ### Basic UmiJS Configuration Source: https://v3.umijs.org/docs/config A standard configuration example using ES6 syntax in .umirc.ts or config/config.ts. ```typescript export default { base: '/docs/', publicPath: '/static/', hash: true, history: { type: 'hash', }, } ``` -------------------------------- ### Verify Node.js Version Source: https://v3.umijs.org/docs/getting-started Check the installed Node.js version to ensure it meets the minimum requirement of 10.13. ```bash $ node -v v10.13.0 ``` -------------------------------- ### Override browser targets for size reduction Source: https://v3.umijs.org/guide Example configuration to reduce bundle size by setting specific browser targets to false. ```javascript export default { targets: { chrome: 79, firefox: false, safari: false, edge: false, ios: false, }, } ``` -------------------------------- ### Identify React Multi-instance Issues Source: https://v3.umijs.org/docs/mfsu Examples of import patterns that may cause React multi-instance problems when MFSU fails to recognize specific syntax. ```javascript // file 1 import React from 'react'; // compiled const { default: React } = await import('react'); // file 2 var React = _interopRequireDefault('react'); // mfsu cannot recognize ``` -------------------------------- ### Nested Routing Directory Structure Source: https://v3.umijs.org/docs/convention-routing Example directory structure for nested routing using _layout.tsx. ```text . └── pages └── users ├── _layout.tsx ├── index.tsx └── list.tsx ``` -------------------------------- ### Generated Routing Configuration Source: https://v3.umijs.org/docs/convention-routing The resulting routing configuration object derived from the example file structure. ```json [ { exact: true, path: '/', component: '@/pages/index' }, { exact: true, path: '/users', component: '@/pages/users' }, ] ``` -------------------------------- ### Verify Build Locally Source: https://v3.umijs.org/docs/getting-started Use the serve package to verify the production build before deployment. ```bash $ yarn global add serve $ serve ./dist ``` -------------------------------- ### Get current locale Source: https://v3.umijs.org/plugins/plugin-locale Returns the currently active language code. ```javascript import { getLocale } from 'umi'; console.log(getLocale()); // en-US | zh-CN ``` -------------------------------- ### Create Project Directory Source: https://v3.umijs.org/docs/getting-started Initialize a new directory for the UmiJS application. ```bash $ mkdir myapp && cd myapp ``` -------------------------------- ### Build Project for Production Source: https://v3.umijs.org/docs/getting-started Compile the project into static assets located in the ./dist directory. ```bash $ yarn build ``` -------------------------------- ### Inspect Build Output Source: https://v3.umijs.org/docs/getting-started View the file structure of the generated production build. ```bash tree ./dist ``` -------------------------------- ### Configure static output with dynamic root Source: https://v3.umijs.org/docs/deployment Enable dynamicRoot alongside htmlSuffix for flexible static path generation. ```javascript export default { exportStatic: { htmlSuffix: true, dynamicRoot: true, }, } ``` -------------------------------- ### Define Convention-based Mock Directory Structure Source: https://v3.umijs.org/docs/mock Umi automatically treats all files under the /mock directory as mock definitions. ```text . ├── mock ├── api.ts └── users.ts └── src └── pages └── index.tsx ``` -------------------------------- ### Register and apply runtime plugins Source: https://v3.umijs.org/api Manage runtime plugins by registering them and applying them with specific execution types. Primarily for plugin development. ```javascript import { Plugin, ApplyPluginsType } from 'umi'; // 注册插件 Plugin.register({ apply: { dva: { foo: 1 } }, path: 'foo', }); Plugin.register({ apply: { dva: { bar: 1 } }, path: 'bar', }); // 执行插件 // 得到 { foo: 1, bar: 1 } Plugin.applyPlugins({ key: 'dva', type: ApplyPluginsType.modify, initialValue: {}, args: {}, async: false, }); ``` -------------------------------- ### TypeScript IntelliSense Configuration Source: https://v3.umijs.org/docs/config Use defineConfig from 'umi' to enable TypeScript IntelliSense for configuration files. ```typescript import { defineConfig } from 'umi'; export default defineConfig({ routes: [ { path: '/', component: '@/pages/index' }, ], }); ``` -------------------------------- ### useIntl() Source: https://v3.umijs.org/plugins/plugin-locale Hook to access internationalization utilities like formatMessage. ```APIDOC ## useIntl() ### Description Returns an intl object containing methods like formatMessage for binding values to translated strings. ### Example ```javascript import { useIntl } from 'umi'; const intl = useIntl(); intl.formatMessage({ id: 'name' }, { name: 'Traveler' }); ``` ``` -------------------------------- ### Enable HTML suffix Source: https://v3.umijs.org/docs/deployment Use htmlSuffix to generate files with .html extensions instead of directory-based index.html files. ```javascript export default { exportStatic: { htmlSuffix: true, }, } ``` -------------------------------- ### Define Basic Routes Source: https://v3.umijs.org/docs/routing Configure the routes array in the UmiJS configuration file to map paths to components. ```javascript export default { routes: [ { exact: true, path: '/', component: 'index' }, { exact: true, path: '/user', component: 'user' }, ], } ``` -------------------------------- ### Link Source: https://v3.umijs.org/api Provides declarative, accessible navigation around your application. ```APIDOC ## Link ### Description Provides declarative, accessible navigation around your application. ### Props - **to** (string | object | function) - Required - The location to link to. - **replace** (boolean) - Optional - When true, clicking the link will replace the current entry in the history stack instead of adding a new one. - **innerRef** (function) - Optional - A callback to access the underlying DOM element. ``` -------------------------------- ### getAllLocales() Source: https://v3.umijs.org/plugins/plugin-locale Retrieves a list of all currently configured internationalization files. ```APIDOC ## getAllLocales() ### Description Returns an array of all internationalized language keys currently obtained from the locales folder. ### Example ```javascript import { getAllLocales } from 'umi'; console.log(getAllLocales()); // [en-US, zh-CN, ...] ``` ``` -------------------------------- ### Enable static site generation Source: https://v3.umijs.org/docs/deployment Configure exportStatic to generate an index.html file for every route. ```javascript export default { exportStatic: {}, } ``` -------------------------------- ### Splitting Configuration into Modules Source: https://v3.umijs.org/docs/config Organize complex configurations by splitting them into separate files like routes.ts. ```typescript // config/routes.ts export default [ { exact: true, path: '/', component: 'index' }, ]; ``` ```typescript // config/config.ts import { defineConfig } from 'umi'; import routes from './routes'; export default defineConfig({ routes: routes, }); ``` -------------------------------- ### Retrieve all locales Source: https://v3.umijs.org/plugins/plugin-locale Returns a list of all detected internationalization files. ```javascript import { getAllLocales } from 'umi'; console.log(getAllLocales()); // [en-US,zh-CN,...] ``` -------------------------------- ### Build-time Configuration Source: https://v3.umijs.org/plugins/plugin-locale Configuration options defined in .umirc.js or config/config.js to enable and customize internationalization behavior. ```APIDOC ## Build-time Configuration ### Description Configure the locale plugin behavior at build time. ### Configuration Object - **default** (string) - Default: 'zh-CN' - The default language used when no specific language is detected. - **antd** (boolean) - Default: false - Whether to enable Ant Design internationalization support. - **title** (boolean) - Default: false - Whether to enable title internationalization using locale keys. - **baseNavigator** (boolean) - Default: true - Whether to enable browser language detection. - **baseSeparator** (string) - Default: '-' - The separator used between country and language codes. ``` -------------------------------- ### View .umi directory structure Source: https://v3.umijs.org/docs/how-umi-works Displays the typical contents of the .umi temporary directory, which contains core files and plugin-generated assets. ```text + .umi + core # umi core + pluginA # plugin A + presetB # preset B + umi.ts # main umi file ``` -------------------------------- ### Configure static resource path Source: https://v3.umijs.org/docs/deployment Set the publicPath to point to a CDN or a non-root directory for static assets. ```javascript export default { publicPath: "http://yourcdn/path/to/static/" } ``` -------------------------------- ### Enable dynamic loading Source: https://v3.umijs.org/docs/deployment Configure dynamic import to enable on-demand loading of application chunks. ```javascript export default { dynamicImport: {}, }; ``` -------------------------------- ### Runtime Configuration Source: https://v3.umijs.org/plugins/plugin-locale Runtime hooks defined in src/app.js to customize language detection and switching logic. ```APIDOC ## Runtime Configuration ### getLocale() Customizes the logic for identifying the current language. ### setLocale({ lang, realReload, updater }) Customizes the logic for switching languages. - **lang** (string) - The target language code. - **realReload** (boolean) - Whether the page should be refreshed. - **updater** (function) - Callback to force update the internationalization status of the current component. ``` -------------------------------- ### Configure runtime publicPath Source: https://v3.umijs.org/docs/deployment Enable runtime publicPath to manage asset paths dynamically within the HTML template. ```javascript export default { runtimePublicPath: true, }; ``` ```html ``` -------------------------------- ### Environment-Specific Configuration Source: https://v3.umijs.org/docs/config Use the UMI_ENV variable to load specific configuration files for different environments. ```javascript // .umirc.js or config/config.js export default { a: 1, b: 2 }; // .umirc.cloud.js or config/config.cloud.js export default { b: 'cloud', c: 'cloud' }; // .umirc.local.js or config/config.local.js export default { c: 'local' }; ``` ```json { a: 1, b: 2, c: 'local', } ``` ```json { a: 1, b: 'cloud', c: 'local', } ``` -------------------------------- ### Configure Layout at Build-Time Source: https://v3.umijs.org/plugins/plugin-layout Define layout settings in config/config.ts. These settings must not require DOM access. ```typescript Import {defineConfig} from'umi'; Export const config = defineConfig({ layout:{ //Support anything that does not require dom // https://procomponents.ant.design/components/layout#prolayout Name: "Ant Design", Region: correct, Layout: "side", }, }); ``` -------------------------------- ### Create dynamic component with UmiJS Source: https://v3.umijs.org/api Use dynamic to split large components into separate bundles to reduce initial load time. Requires dynamic import syntax. ```javascript import { dynamic } from 'umi'; export default dynamic({ loader: async function () { // webpackChunkName tells webpack create separate bundle for HugeA const { default: HugeA } = await import( /* webpackChunkName: "external_A" */ './HugeA' ); return HugeA; }, }); ``` -------------------------------- ### Enable MFSU in ANTD-Pro Source: https://v3.umijs.org/docs/mfsu Add the mfsu configuration object to your project configuration file. ```javascript mfsu: {}, ``` -------------------------------- ### Default Build-time Configuration Source: https://v3.umijs.org/plugins/plugin-locale The default configuration object for the locale plugin when enabled in the project. ```javascript export default { locale: { default: 'zh-CN', antd: false, title: false, baseNavigator: true, baseSeparator: '-', }, }; ``` -------------------------------- ### Configure Route Redirects Source: https://v3.umijs.org/docs/routing Use the redirect property to automatically navigate from one path to another. ```javascript export default { routes: [ { exact: true, path: '/', redirect: '/list' }, { exact: true, path: '/list', component: 'list' }, ], } ``` -------------------------------- ### Project Directory Structure Source: https://v3.umijs.org/docs/directory-structure The standard file hierarchy for a UmiJS project. ```text . ├── package.json ├── .umirc.ts ├── .env ├── dist ├── mock ├── public └── src    ├── .umi    ├── layouts/index.tsx    ├── pages    ├── index.less    └── index.tsx    └── app.ts ``` -------------------------------- ### Import CSS Modules vs Standard CSS Source: https://v3.umijs.org/docs/assets-css Use default imports for CSS Modules or standard imports for global/non-module CSS files. ```javascript // CSS Modules import styles from './foo.css'; // Non-CSS Modules import './foo.css'; ``` -------------------------------- ### Use Dynamic Component Source: https://v3.umijs.org/docs/load-on-demand Import and use the asynchronously loaded component as a standard React component. ```javascript import React from 'react'; import AsyncHugeA from './AsyncHugeA'; // import as normal component // with below benefits out of box: // 1. download bundle automatically // 2. give a loading splash while downloading (customizable) // 3. display HugeA whenever component downloaded export default () => { return ; } ``` -------------------------------- ### Define Global CSS Styles Source: https://v3.umijs.org/docs/assets-css Place global styles in src/global.css to have them applied automatically across the application. ```css .ant-select-selection { max-height: 51px; overflow: auto; } ``` -------------------------------- ### Dynamic Optional Routing Configuration Source: https://v3.umijs.org/docs/convention-routing Resulting route configuration generated from the optional dynamic file structure. ```javascript routes: [ { exact: true, path: '/', component: '@/pages/index' }, { exact: true, path: '/users/:id?', component: '@/pages/users/[id$]' }, { exact: true, path: '/:post?/comments', component: '@/pages/[post$]/comments', }, ]; ``` -------------------------------- ### Demonstrate flatMenu transformation Source: https://v3.umijs.org/plugins/plugin-layout Visual representation of how the flatMenu property flattens nested menu structures. ```javascript const before = [{ name: '111' }, { name: '222', children: [{ name: '333' }] }]; // flatMenu = true const after = [{ name: '111' }, { name: '222' }, { name: '333' }]; ``` -------------------------------- ### useParams Source: https://v3.umijs.org/api A hook that returns URL parameters. ```APIDOC ## useParams ### Description Returns an object of key/value pairs of URL parameters. ### Usage ```javascript import { useParams } from 'umi'; const params = useParams(); ``` ``` -------------------------------- ### Scaffold UmiJS Project Source: https://v3.umijs.org/docs/getting-started Generate a new project structure using the UmiJS template. ```bash $ yarn create @umijs/umi-app // if use yarn $ npx @umijs/create-umi-app // if use npm ``` -------------------------------- ### Configure base path Source: https://v3.umijs.org/docs/deployment Set the base path when deploying the application to a non-root directory to ensure correct route matching. ```javascript export default { base: '/path/to/your/app/root', }; ``` -------------------------------- ### Implement Route Wrappers Source: https://v3.umijs.org/docs/routing Use wrappers to apply Higher-Order Components (HOCs) to routes, commonly used for authorization checks. ```javascript export default { routes: [ { path: '/user', component: 'user', wrappers: [ '@/wrappers/auth', ], }, { path: '/login', component: 'login' }, ] } ``` ```javascript import { Redirect } from 'umi' export default (props) => { const { isLogin } = useAuth(); if (isLogin) { return
{ props.children }
; } else { return ; } } ``` -------------------------------- ### Prompt Source: https://v3.umijs.org/api Used to prompt the user before navigating away from a page. ```APIDOC ## Prompt ### Description Used to prompt the user before navigating away from a page. When your application enters a state that should prevent the user from navigating away, render a . ### Props - **message** (string | function) - Required - The message to prompt the user with when they try to navigate away. - **when** (boolean) - Optional - When true, the prompt is active; when false, navigation is allowed without a prompt. ``` -------------------------------- ### Dynamic Routing Configuration Source: https://v3.umijs.org/docs/convention-routing Resulting route configuration generated from the dynamic file structure. ```javascript routes: [ { exact: true, path: '/', component: '@/pages/index' }, { exact: true, path: '/users/:id', component: '@/pages/users/[id]' }, { exact: true, path: '/:post/', component: '@/pages/[post]/index' }, { exact: true, path: '/:post/comments', component: '@/pages/[post]/comments', }, ]; ``` -------------------------------- ### Integrate Mock.js for Dynamic Data Source: https://v3.umijs.org/docs/mock Use the mockjs library to generate complex or randomized mock data structures. ```javascript import mockjs from 'mockjs'; export default { // use mockjs 'GET /api/tags': mockjs.mock({ 'list|100': [{ name: '@city', 'value|1-100': 50, 'type|0-2': 1 }], }), }; ``` -------------------------------- ### Enable Dynamic Import Source: https://v3.umijs.org/docs/load-on-demand Configure the dynamicImport property in your UmiJS configuration file to enable code splitting. ```javascript export default { dynamicImport: {}, } ``` -------------------------------- ### Configure Route Titles Source: https://v3.umijs.org/plugins/plugin-locale Mapping route titles to internationalization keys in the project configuration. ```javascript // .umirc.js export default { title: 'site.title', routes: [ { path: '/', component: 'Index', }, { path: '/about', component: 'About', title: 'about.title', }, ], }; ``` -------------------------------- ### Configure Exact Route Matching Source: https://v3.umijs.org/docs/routing Use the exact property to control whether a route requires a strict match against the URL. ```javascript export default { routes: [ // Matching fails when url is /one/two { path: '/one', exact: true }, // Matching is successful when url is /one/two { path: '/one' }, { path: '/one', exact: false }, ], } ``` -------------------------------- ### Perform route navigation Source: https://v3.umijs.org/api Navigate between routes using push or goBack methods with support for query parameters. ```javascript import { history } from 'umi'; // 跳转到指定路由 history.push('/list'); // 带参数跳转到指定路由 history.push('/list?a=b'); history.push({ pathname: '/list', query: { a: 'b', }, }); // 跳转到上一个路由 history.goBack(); ``` -------------------------------- ### 404 Page Configuration Source: https://v3.umijs.org/docs/convention-routing Umi automatically uses src/pages/404.tsx as the fallback route when no other paths match. ```text . └── pages ├── 404.tsx ├── index.tsx └── users.tsx ``` ```javascript routes: [ { exact: true, path: '/', component: '@/pages/index' }, { exact: true, path: '/users', component: '@/pages/users' }, { component: '@/pages/404' }, ] ``` -------------------------------- ### render(oldRender: Function) Source: https://v3.umijs.org/docs/runtime-config Overrides the default application render process, useful for authentication checks. ```APIDOC ## render(oldRender: Function) ### Description Overwrites the default render process. This is typically used to perform asynchronous tasks like authentication checks before the application mounts. ### Signature export function render(oldRender: Function) ### Parameters - **oldRender** (Function) - The original render function that must be called to proceed with application mounting. ### Example ```javascript import { history } from 'umi'; export function render(oldRender) { fetch('/api/auth').then(auth => { if (auth.isLogin) { oldRender() } else { history.push('/login'); } }); } ``` ``` -------------------------------- ### Customize Language Switching Source: https://v3.umijs.org/plugins/plugin-locale Implementing custom logic to handle language switching via URL navigation. ```javascript // src/app.js export const locale = { setLocale({ lang, realReload, updater }) { history.push(`/?locale=${lang}`); updater(); }, }; ``` -------------------------------- ### Configure default browser targets Source: https://v3.umijs.org/guide Defines the default browser versions supported by Umi for polyfill inclusion. ```javascript chrome: 49, firefox: 64, safari: 10, edge: 13, ios: 10, ``` -------------------------------- ### Debug Umi commands Source: https://v3.umijs.org/docs/contributing Commands to debug Umi development and build processes using yarn. Ensure yarn build -w is executed first to compile the source code. ```bash # 调试 umi dev $ yarn debug examples/normal dev # 调试 umi build $ yarn debug examples/normal build ``` -------------------------------- ### Navigate with useHistory hook Source: https://v3.umijs.org/api Provides access to the history instance for programmatic navigation. ```javascript import { useHistory } from 'umi'; export default () => { const history = useHistory(); return (
  • history: {history.action}
); }; ``` -------------------------------- ### Configure monaco-editor-webpack-plugin Source: https://v3.umijs.org/guide Use this configuration to integrate monaco-editor and prevent build errors. ```javascript import MonacoWebpackPlugin from'monaco-editor-webpack-plugin'; export default { chainWebpack: (memo) => { // More configuration https://github.com/Microsoft/monaco-editor-webpack-plugin#options memo.plugin('monaco-editor-webpack-plugin').use(MonacoWebpackPlugin, [ // Configure on demand { languages: ['javascript'] } ]); return memo; } } ``` -------------------------------- ### Programmatic Navigation with history Source: https://v3.umijs.org/docs/routing Use the history object to navigate between routes, pass query parameters, or return to the previous page. ```javascript import { history } from 'umi'; // Jump to the specified route history.push('/list'); // Jump to the specified route with parameters history.push('/list?a=b'); history.push({ pathname: '/list', query: { a: 'b', }, }); // Jump to the previous route history.goBack(); ``` -------------------------------- ### Use the Access component Source: https://v3.umijs.org/plugins/plugin-access Control the rendering of UI elements based on permission checks using the Access component. ```typescript import React from 'react'; import { useAccess, Access } from 'umi'; const PageA = props => { const {foo} = props; const access = useAccess(); if (access.canReadFoo) { // user has permission canReadFoo } return (
Can not read foo content.
} > Foo content. Can not update foo.} > Update foo. Can not delete foo.} > Delete foo. ); }; ``` -------------------------------- ### Define a model in src/models Source: https://v3.umijs.org/plugins/plugin-model Create a custom hook in the src/models directory to define shared state and logic. The file name serves as the namespace for the model. ```javascript import { useState, useCallback } from 'react' export default function useAuthModel() { const [user, setUser] = useState(null) const signin = useCallback((account, password) => { // signin implementation // setUser(user from signin API) }, []) const signout = useCallback(() => { // signout implementation // setUser(null) }, []) return { user, signin, signout } } ``` -------------------------------- ### dynamic Source: https://v3.umijs.org/api The dynamic function allows for on-demand component loading to reduce initial bundle size. It handles chunk splitting, asynchronous loading, and loading state management. ```APIDOC ## dynamic ### Description Load components dynamically on demand to reduce first screen download cost. ### Usage ```javascript import { dynamic } from 'umi'; export default dynamic({ loader: async function () { const { default: HugeA } = await import('./HugeA'); return HugeA; }, }); ``` ``` -------------------------------- ### Configure Layout at Runtime Source: https://v3.umijs.org/plugins/plugin-layout Define layout settings in src/app.tsx using the exported layout function. This allows for dynamic configurations that require DOM or runtime state. ```typescript import React from 'react'; import { BasicLayoutProps, Settings as LayoutSettings, } from '@ant-design/pro-layout'; export const layout = ({ initialState, }: { initialState: { settings?: LayoutSettings; currentUser?: API.CurrentUser }; }): BasicLayoutProps => { return { rightContentRender: () => , footerRender: () =>