├── packages ├── umi │ ├── src │ │ ├── test.md │ │ ├── scripts │ │ │ ├── dev.md │ │ │ ├── help.md │ │ │ ├── test.md │ │ │ ├── generate.md │ │ │ ├── realDev.md │ │ │ └── build.md │ │ ├── dev.md │ │ ├── generate.md │ │ ├── buildDevOpts.md │ │ ├── build.md │ │ ├── help.md │ │ ├── cli.md │ │ └── generators │ │ │ └── page.md │ └── bin │ │ └── umi.md └── umi-build-dev │ └── src │ └── plugins │ └── 404 │ └── index.md ├── README.md └── docs ├── zh ├── guide │ ├── navigate-between-pages.md │ ├── load-on-demand.md │ ├── create-umi-app.md │ ├── config.md │ ├── html-template.md │ ├── examples.md │ ├── README.md │ ├── env-variables.md │ ├── migration.md │ ├── deploy.md │ ├── mock-data.md │ ├── app-structure.md │ ├── getting-started.md │ ├── with-dva.md │ ├── faq.md │ └── router.md ├── plugin │ ├── README.md │ ├── umi-plugin-react.md │ └── develop.md ├── README.md ├── api │ └── README.md └── config │ └── README.md ├── guide ├── navigate-between-pages.md ├── load-on-demand.md ├── create-umi-app.md ├── config.md ├── html-template.md ├── examples.md ├── README.md ├── env-variables.md ├── migration.md ├── getting-started.md ├── deploy.md ├── mock-data.md ├── app-structure.md ├── with-dva.md ├── faq.md └── router.md ├── plugin ├── README.md ├── umi-plugin-react.md └── develop.md ├── README.md ├── api └── README.md └── config └── README.md /packages/umi/src/test.md: -------------------------------------------------------------------------------- 1 | ```js 2 | export default from 'umi-test'; 3 | ``` -------------------------------------------------------------------------------- /packages/umi/src/scripts/dev.md: -------------------------------------------------------------------------------- 1 | ```js 2 | import fork from 'umi-build-dev/lib/fork'; 3 | 4 | fork(require.resolve('./realDev.js')); 5 | ``` 6 | 从其他文件引入 7 | 此处的fork来自child_process 8 | -------------------------------------------------------------------------------- /packages/umi/src/scripts/help.md: -------------------------------------------------------------------------------- 1 | ```js 2 | import yParser from 'yargs-parser'; 3 | import help from '../help'; 4 | 5 | const argv = yParser(process.argv.slice(2)); 6 | const [type] = argv._; 7 | 8 | help({ 9 | type, 10 | }); 11 | ``` 12 | 从别的文件中引入help方法 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 源码共读计划-UMI 2 | 突然发现自己的博客好久没有更新了,不知道写点什么,正好最近在学习UMI框架。 3 | 所以干脆把学习笔记整理出来。 4 | 项目目录是根据UMI项目的目录设置的。 5 | 希望对大家有所帮助。 6 | 7 | ## change log 8 | 请查看[Releases](https://github.com/xiaohuoni/source-code-co-reading-umi/releases) 9 | 你们可以使用Releases Only来关注这个项目,这样就收不到issues中的相关消息了。 10 | -------------------------------------------------------------------------------- /packages/umi/src/scripts/test.md: -------------------------------------------------------------------------------- 1 | ```js 2 | import test from '../test'; 3 | 4 | const args = process.argv.slice(2); 5 | 6 | const watch = args.indexOf('-w') > -1 || args.indexOf('--watch') > -1; 7 | const coverage = args.indexOf('--coverage') > -1; 8 | 9 | test({ 10 | watch, 11 | coverage, 12 | }); 13 | ``` 14 | 从umi-test中引入test模块,然后执行。 -------------------------------------------------------------------------------- /packages/umi/src/dev.md: -------------------------------------------------------------------------------- 1 | ```js 2 | import buildDevOpts from './buildDevOpts'; 3 | 4 | process.env.NODE_ENV = 'development'; 5 | 6 | export default function(opts = {}) { 7 | return require('umi-build-dev/lib/dev').default(buildDevOpts(opts)); 8 | } 9 | 10 | export { fork } from 'umi-build-dev/lib/dev'; 11 | ``` 12 | 调用umi-build-dev模块的方法 13 | -------------------------------------------------------------------------------- /packages/umi/src/scripts/generate.md: -------------------------------------------------------------------------------- 1 | ```js 2 | import yParser from 'yargs-parser'; 3 | import generate from '../generate'; 4 | 5 | const argv = yParser(process.argv.slice(2)); 6 | const [type, file] = argv._; 7 | 8 | generate({ 9 | type, 10 | file, 11 | useClass: argv.c || argv.class || false, 12 | isDirectory: argv.d || argv.directory || false, 13 | }); 14 | ``` 15 | 取出参数调用generate -------------------------------------------------------------------------------- /packages/umi/src/scripts/realDev.md: -------------------------------------------------------------------------------- 1 | ```js 2 | import yParser from 'yargs-parser'; 3 | import dev from '../dev'; 4 | 5 | const argv = yParser(process.argv.slice(2)); 6 | 7 | // 修复 Ctrl+C 时 dev server 没有正常退出的问题 8 | process.on('SIGINT', () => { 9 | process.exit(1); 10 | }); 11 | 12 | dev({ 13 | plugins: argv.plugins ? argv.plugins.split(',') : [], 14 | }); 15 | ``` 16 | 从命令行中去除参数,调用dev方法 -------------------------------------------------------------------------------- /docs/zh/guide/navigate-between-pages.md: -------------------------------------------------------------------------------- 1 | # 在页面间跳转 2 | 3 | 在 umi 里,页面之间跳转有两种方式:声明式和命令式。 4 | 5 | ## 声明式 6 | 7 | 基于 `umi/link`,通常作为 React 组件使用。 8 | 9 | ```bash 10 | import Link from 'umi/link'; 11 | 12 | export default () => ( 13 | Go to list page 14 | ); 15 | ``` 16 | 17 | ## 命令式 18 | 19 | 基于 `umi/router`,通常在事件处理中被调用。 20 | 21 | ```js 22 | import router from 'umi/router'; 23 | 24 | function goToListPage() { 25 | router.push('/list'); 26 | } 27 | ``` 28 | 29 | 更多命令式的跳转方法,详见 [api#umi/router](/zh/api/#umi-router)。 30 | -------------------------------------------------------------------------------- /docs/zh/guide/load-on-demand.md: -------------------------------------------------------------------------------- 1 | # 按需加载 2 | 3 | 出于性能的考虑,我们会对模块和组件进行按需加载。 4 | 5 | ## 按需加载组件 6 | 7 | 通过 `umi/dynamic` 接口实现,比如: 8 | 9 | ```js 10 | import dynamic from 'umi/dynamic'; 11 | 12 | const delay = (timeout) => new Promise(resolve => setTimeout(resolve, timeout)); 13 | const App = dynamic({ 14 | loader: async function() { 15 | await delay(/* 1s */1000); 16 | return () =>
I will render after 1s
; 17 | }, 18 | }); 19 | ``` 20 | 21 | ## 按需加载模块 22 | 23 | 通过 `import()` 实现,比如: 24 | 25 | ```js 26 | import('g2').then(() => { 27 | // do something with g2 28 | }); 29 | ``` 30 | -------------------------------------------------------------------------------- /packages/umi/src/generate.md: -------------------------------------------------------------------------------- 1 | ```js 2 | import assert from 'assert'; 3 | import page from './generators/page'; 4 | 5 | const generators = { 6 | page, 7 | }; 8 | ``` 9 | 这里应该是为了后续扩展使用的,这里暂时只有一个page 10 | ```js 11 | export default function(opts = {}) { 12 | const { type, file } = opts; 13 | assert(type, 'opts.type should be supplied'); 14 | assert(typeof type === 'string', 'opts.file should be string'); 15 | assert(file, 'opts.file should be supplied'); 16 | assert(typeof file === 'string', 'opts.file should be string'); 17 | assert(generators[type], `generator of type (${type}) not found`); 18 | 19 | delete opts.type; 20 | generators[type](opts); 21 | } 22 | ``` -------------------------------------------------------------------------------- /docs/guide/navigate-between-pages.md: -------------------------------------------------------------------------------- 1 | # Navigate between pages 2 | 3 | In umi, there are two ways to navigate between pages: declarative and imperative. 4 | 5 | ## Declarative 6 | 7 | Based on `umi/link`, it is usually used as a React component. 8 | 9 | ```bash 10 | import Link from 'umi/link'; 11 | 12 | export default () => ( 13 | Go to list page 14 | ); 15 | ``` 16 | 17 | ## Command 18 | 19 | Based on `umi/router`, it is usually called in event processing. 20 | 21 | ```js 22 | import router from 'umi/router'; 23 | 24 | function goToListPage() { 25 | router.push('/list'); 26 | } 27 | ``` 28 | 29 | For more command-style jump methods, see [api#umi/router](/api/#umi-router). 30 | -------------------------------------------------------------------------------- /docs/guide/load-on-demand.md: -------------------------------------------------------------------------------- 1 | # Load on demand 2 | 3 | For performance reasons, we load modules and components on demand. 4 | 5 | ## Loading Components on Demand 6 | 7 | Implemented through the `umi/dynamic` interface, such as: 8 | 9 | ```js 10 | import dynamic from 'umi/dynamic'; 11 | 12 | const delay = (timeout) => new Promise(resolve => setTimeout(resolve, timeout)); 13 | const App = dynamic({ 14 | loader: async function() { 15 | await delay(/* 1s */1000); 16 | return () =>
I will render after 1s
; 17 | }, 18 | }); 19 | ``` 20 | 21 | ## Loading Modules on Demand 22 | 23 | Implemented by `import()`, such as: 24 | 25 | ```js 26 | import('g2').then(() => { 27 | // do something with g2 28 | }); 29 | ``` 30 | -------------------------------------------------------------------------------- /packages/umi/src/scripts/build.md: -------------------------------------------------------------------------------- 1 | ```js 2 | import chalk from 'chalk'; 3 | import yParser from 'yargs-parser'; 4 | import build from '../build'; 5 | const argv = yParser(process.argv.slice(2)); 6 | ``` 7 | ```js 8 | //回顾 9 | [require.resolve(`../lib/scripts/${script}`)].concat(args), 10 | ``` 11 | yargs-parser取出命令行参数,如 12 | ```base 13 | umi build abc --xiaohu=haha --bcd=123 14 | ``` 15 | ```json 16 | argv = { _: [ 'abc' ], xiaohu: 'haha', bcd: 123 } 17 | ``` 18 | ```js 19 | build({ 20 | plugins: argv.plugins ? argv.plugins.split(',') : [], 21 | }).catch(e => { 22 | console.error(chalk.red(`Build failed: ${e.message}`)); 23 | console.log(e); 24 | }); 25 | ``` 26 | 执行build。 27 | 注,这里取得是argv.plugins的值,但是我执行了很多种情况的命令,都没有plugins这个值。 28 | -------------------------------------------------------------------------------- /docs/zh/plugin/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebarDepth: 2 3 | --- 4 | 5 | # 插件 6 | 7 | umi 区别于其他前端开发框架和工具的核心就是它的插件机制,基于 umi 的插件机制,你可以获得扩展项目的编译时和运行时的能力。通过插件支持的功能也会变得更强大,我们针对功能的需要可以去使用修改代码打包配置,修改启动代码,约定目录结构,修改 HTML 等更丰富接口。 8 | 9 | ## 插件使用 10 | 11 | 插件可以是一个 npm 包,也可以是路径直接引向一个 JS 的模块。用户通过配置 `plugins` 来使用插件。如下所示: 12 | 13 | ```js 14 | // .umirc.js 15 | export default { 16 | plugins: [ 17 | ['umi-plugin-dva', { 18 | immer: true, 19 | }], 20 | ['./src/plugins/customPlugin.js', { 21 | // plugin config 22 | }] 23 | ], 24 | }; 25 | ``` 26 | 27 | ## 插件列表 28 | 29 | ### 官方插件 30 | 31 | - [umi-plugin-react](/zh/plugin/umi-plugin-react.html)(插件集) 32 | - umi-plugin-dva 33 | - umi-plugin-locale 34 | - umi-plugin-dll 35 | - umi-plugin-routes 36 | - umi-plugin-polyfills 37 | 38 | ### 社区插件 39 | 40 | - [umi-plugin-*](https://www.npmjs.com/search?q=umi-plugin-) 41 | -------------------------------------------------------------------------------- /docs/zh/guide/create-umi-app.md: -------------------------------------------------------------------------------- 1 | # 通过脚手架创建项目 2 | 3 | umi 通过 [create-umi](https://github.com/umijs/create-umi) 提供脚手架,包含一定的定制化能力。推荐使用 `yarn create` 命令,因为能确保每次使用最新的脚手架。 4 | 5 | 首先,在新目录下使用 `yarn create umi`, 6 | 7 | ```bash 8 | $ mkdir myapp && cd myapp 9 | $ yarn create umi 10 | ``` 11 | 12 | 然后,选择你需要的功能,功能介绍详见 [plugin/umi-plugin-react](../plugin/umi-plugin-react.html), 13 | 14 | 15 | 16 | 确定后,会根据你的选择自动创建好目录和文件, 17 | 18 | 19 | 20 | 然后手动安装依赖, 21 | 22 | ```bash 23 | $ yarn 24 | ``` 25 | 26 | 最后通过 `yarn start` 启动本地开发, 27 | 28 | ```bash 29 | $ yarn start 30 | ``` 31 | 32 | 如果顺利,在浏览器打开 [http://localhost:8000](http://localhost:8000) 可看到以下界面, 33 | 34 | 35 | -------------------------------------------------------------------------------- /docs/zh/guide/config.md: -------------------------------------------------------------------------------- 1 | # 配置 2 | 3 | ## 配置文件 4 | 5 | umi 允许在 `.umirc.js` 或 `config/config.js` (二选一,`.umirc.js` 优先)中进行配置,支持 ES6 语法。 6 | 7 | > 为简化说明,后续文档里只会出现 `.umirc.js`。 8 | 9 | 比如: 10 | 11 | ```js 12 | export default { 13 | base: '/admin/', 14 | publicPath: 'http://cdn.com/foo', 15 | plugins: [ 16 | ['umi-plugin-react', { 17 | dva: true, 18 | }], 19 | ], 20 | }; 21 | ``` 22 | 23 | 具体配置项详见[配置](/zh/config/)。 24 | 25 | ## .umirc.local.js 26 | 27 | `.umirc.local.js` 是本地的配置文件,**不要提交到 git**,所以通常需要配置到 `.gitignore`。如果存在,会和 `.umirc.js` 合并后再返回。 28 | 29 | ## UMI_ENV 30 | 31 | 可以通过环境变量 `UMI_ENV` 区分不同环境来指定配置。 32 | 33 | 举个例子, 34 | 35 | ```js 36 | // .umirc.js 37 | export default { a: 1, b: 2 }; 38 | 39 | // .umirc.cloud.js 40 | export default { b: 'cloud', c: 'cloud' }; 41 | 42 | // .umirc.local.js 43 | export default { c: 'local' }; 44 | ``` 45 | 46 | 不指定 `UMI_ENV` 时,拿到的配置是: 47 | 48 | ```js 49 | { 50 | a: 1, 51 | b: 2, 52 | c: 'local', 53 | } 54 | ``` 55 | 56 | 指定 `UMI_ENV=cloud` 时,拿到的配置是: 57 | 58 | ```js 59 | { 60 | a: 1, 61 | b: 'cloud', 62 | c: 'local', 63 | } 64 | ``` 65 | -------------------------------------------------------------------------------- /docs/zh/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: true 3 | actionText: 快速上手 → 4 | actionLink: /zh/guide/ 5 | features: 6 | - title: 插件化 7 | details: umi 的整个生命周期都是插件化的,甚至其内部实现就是由大量插件组成,比如 pwa、按需加载、一键切换 preact、一键兼容 ie9 等等,都是由插件实现。 8 | - title: 开箱即用 9 | details: 你只需一个 umi 依赖就可启动开发,无需安装 react、preact、webpack、react-router、babel、jest 等等。 10 | - title: 约定式路由 11 | details: 类 next.js 的约定式路由,无需再维护一份冗余的路由配置,支持权限、动态路由、嵌套路由等等。 12 | footer: MIT Licensed | Copyright © 2017-present 13 | --- 14 | 15 | ### 入门非常简单 16 | 17 | ```bash 18 | # 安装 19 | $ yarn global add umi # 或者 npm install -g umi 20 | 21 | # 新建应用 22 | $ mkdir myapp && cd myapp 23 | 24 | # 新建页面 25 | $ umi generate page index 26 | 27 | # 本地开发 28 | $ umi dev 29 | 30 | # 构建上线 31 | $ umi build 32 | ``` 33 | 34 | [10 分钟入门 umi 视频版](https://youtu.be/vkAUGUlYm24) 35 | 36 | ### 社区 37 | 38 | #### 钉钉群 39 | 40 | 41 | 42 | #### 微信群 43 | 44 | 群满 100 人,请加 `sorryccpro` 好友备注 `umi` 邀请加入。 45 | 46 | #### Telegram 47 | 48 | [https://t.me/joinchat/G0DdHw-44FO7Izt4K1lLFQ](https://t.me/joinchat/G0DdHw-44FO7Izt4K1lLFQ) 49 | -------------------------------------------------------------------------------- /packages/umi/bin/umi.md: -------------------------------------------------------------------------------- 1 | ```base 2 | #!/usr/bin/env node 3 | ``` 4 | 声明文件执行环境 node 5 | ```js 6 | const resolveCwd = require('resolve-cwd'); 7 | ``` 8 | resolve-cwd是指从当前工作目录解析像[require.resolve()](https://nodejs.org/api/globals.html#globals_require_resolve)这样的模块的路径. 9 | 这里有个小例子,可以看明白它的功能。 10 | ```js 11 | const resolveCwd = require('resolve-cwd'); 12 | 13 | console.log(__dirname); 14 | //=> '/Users/sindresorhus/rainbow' 15 | 16 | console.log(process.cwd()); 17 | //=> '/Users/sindresorhus/unicorn' 18 | 19 | resolveCwd('./foo'); 20 | //=> '/Users/sindresorhus/unicorn/foo.js' 21 | ``` 22 | 下面的就比较没有阅读难度了,用于调试本地的umi 23 | ```js 24 | const localCLI = resolveCwd.silent('umi/bin/umi'); 25 | if (localCLI && localCLI !== __filename) { 26 | const debug = require('debug')('umi'); 27 | debug('Using local install of umi'); 28 | require(localCLI); 29 | } else { 30 | require('../lib/cli'); 31 | } 32 | ``` 33 | 以下代码是指,开启了debug之后,打印日志。 34 | ```js 35 | const debug = require('debug')('umi'); 36 | debug('Using local install of umi'); 37 | ``` 38 | > 关于引用路径说明:因为umi里面的src目录都会被编译到lib目录,所以在代码中引用的都是类似 **../lib/cli** 这样的路径,但是实际上我们要查看的是 **../src/cli** -------------------------------------------------------------------------------- /packages/umi/src/buildDevOpts.md: -------------------------------------------------------------------------------- 1 | ```js 2 | import { resolve } from 'path'; 3 | 4 | const debug = require('debug')('umi:devDevOpts'); 5 | ``` 6 | ```js 7 | export default function(opts = {}) { 8 | const { extraResolveModules, hash } = opts; 9 | debug(`opts: ${JSON.stringify(opts)}`); 10 | delete opts.extraResolveModules; 11 | 12 | return { 13 | cwd: process.env.APP_ROOT, 14 | // eslint-disable-line 15 | babel: resolve(__dirname, './babel'), 16 | extraResolveModules: [ 17 | ...(extraResolveModules || []), 18 | resolve(__dirname, '../../node_modules'), 19 | ], 20 | libraryAlias: { 21 | dynamic: require.resolve('./dynamic'), 22 | link: require.resolve('./link'), 23 | navlink: require.resolve('./navlink'), 24 | redirect: require.resolve('./redirect'), 25 | router: require.resolve('./router'), 26 | withRouter: require.resolve('./withRouter'), 27 | _renderRoutes: require.resolve('./renderRoutes'), 28 | _createHistory: require.resolve('./createHistory'), 29 | }, 30 | hash, 31 | ...opts, 32 | }; 33 | } 34 | ``` 35 | 当执行umi build时,这里opts={plugins: [],hash: true} 36 | 在这里组装成开发环境中需要的option 37 | -------------------------------------------------------------------------------- /docs/guide/create-umi-app.md: -------------------------------------------------------------------------------- 1 | # Create a Project With create-umi 2 | 3 | Umi provides scaffolding through [create-umi](https://github.com/umijs/create-umi), which includes some customization capabilities. The `yarn create` command is recommended because it ensures that every time you use the latest scaffolding. 4 | 5 | First, use `yarn create umi` in the new directory. 6 | 7 | ```bash 8 | $ mkdir myapp && cd myapp 9 | $ yarn create umi 10 | ``` 11 | 12 | Then, select the function you need, checkout [plugin/umi-plugin-react](../plugin/umi-plugin-react.html) for the detailed description. 13 | 14 | 15 | 16 | Once determined, the directories and files will be automatically created based on your selection. 17 | 18 | 19 | 20 | Then install the dependencies manually, 21 | 22 | ```bash 23 | $ yarn 24 | ``` 25 | 26 | Finally, start local development server with `yarn start`. 27 | 28 | ```bash 29 | $ yarn start 30 | ``` 31 | 32 | If it goes well, open [http://localhost:8000](http://localhost:8000) in the browser and you will see the following ui. 33 | 34 | 35 | -------------------------------------------------------------------------------- /docs/plugin/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebarDepth: 2 3 | --- 4 | 5 | # Plugin 6 | 7 | The key of umi that distinguishes it from other front-end development frameworks and tools is its plugin system. Based on the umi plugin system, you can get the compile-time and runtime capabilities of the extension project. The feature supported by the plugin will also become more powerful. For the needs of the feature, we can use the modified code package configuration, modify the bootstrap code, stipulate the directory structure, modify the HTML and other rich interfaces. 8 | 9 | ## Plugin usage 10 | 11 | The plugin can be an npm package or a JS module that located with a path. You can register a plugin by configuring `plugins`. As follows: 12 | 13 | ```js 14 | // .umirc.js 15 | export default { 16 | plugins: [ 17 | ['umi-plugin-dva', { 18 | immer: true, 19 | }], 20 | ['./src/plugins/customPlugin.js', { 21 | // plugin config 22 | }] 23 | ], 24 | }; 25 | ``` 26 | 27 | ## Plugin list 28 | 29 | ### Official plugins 30 | 31 | - [umi-plugin-react](/plugin/umi-plugin-react.html) (Plugin set) 32 | - umi-plugin-dva 33 | - umi-plugin-locale 34 | - umi-plugin-dll 35 | - umi-plugin-routes 36 | - umi-plugin-polyfills 37 | 38 | ### Community plugins 39 | 40 | - [umi-plugin-*](https://www.npmjs.com/search?q=umi-plugin-) 41 | -------------------------------------------------------------------------------- /docs/zh/guide/html-template.md: -------------------------------------------------------------------------------- 1 | # HTML 模板 2 | 3 | ## 修改默认模板 4 | 5 | 新建 `src/pages/document.ejs`,umi 约定如果这个文件存在,会作为默认模板,内容上需要保证有 `
`,比如: 6 | 7 | ```html 8 | 9 | 10 | 11 | 12 | Your App 13 | 14 | 15 |
16 | 17 | 18 | ``` 19 | 20 | ## 配置模板 21 | 22 | 模板里可通过 `context` 来获取到 umi 提供的变量,context 包含: 23 | 24 | * `route`,路由对象,包含 path、component 等 25 | * `config`,用户配置信息 26 | * `publicPath`,webpack 的 `output.publicPath` 配置 27 | * `env`,环境变量,值为 development 或 production 28 | * 其他在路由上通过 context 扩展的配置信息 29 | 30 | 模板基于 ejs 渲染,可以参考 [https://github.com/mde/ejs](https://github.com/mde/ejs) 查看具体使用。 31 | 32 | 比如输出变量, 33 | 34 | ```html 35 | 36 | ``` 37 | 38 | 比如条件判断, 39 | 40 | ```html 41 | <% if(context.env === 'production') { %> 42 |

生产环境

43 | <% } else {%> 44 |

开发环境

45 | <% } %> 46 | ``` 47 | 48 | ## 针对特定页面指定模板 49 | 50 | ::: warning 51 | 此功能需开启 `exportStatic` 配置,否则只会输出一个 html 文件。 52 | ::: 53 | 54 | ::: tip 55 | 优先级是:路由的 document 属性 > src/pages/document.ejs > umi 内置模板 56 | ::: 57 | 58 | 配置路由的 document 属性。 59 | 60 | 比如约定式路由可通过注释扩展 `document` 属性,路径从项目根目录开始找, 61 | 62 | ```js 63 | /** 64 | * document: ./src/documents/404.ejs 65 | */ 66 | ``` 67 | 68 | 然后这个路由就会以 `./src/documents/404.ejs` 为模板输出 HTML。 69 | -------------------------------------------------------------------------------- /docs/guide/config.md: -------------------------------------------------------------------------------- 1 | # Configuration 2 | 3 | ## Configuration File 4 | 5 | Umi can be configured in `.umirc.js` or `config/config.js` (choose one, `.umirc.js` has priority), ES6 syntax is supported. 6 | 7 | > To simplify the description, only `.umirc.js` will appear in subsequent documents. 8 | 9 | Such as: 10 | 11 | ```js 12 | export default { 13 | base: '/admin/', 14 | publicPath: 'http://cdn.com/foo', 15 | plugins: [ 16 | ['umi-plugin-react', { 17 | dva: true, 18 | }], 19 | ], 20 | }; 21 | ``` 22 | 23 | For details, see [Configuration](/config/). 24 | 25 | ## .umirc.local.js 26 | 27 | `.umirc.local.js` is a local configuration file, **don't commit to git**, so it usually needs to be configured to `.gitignore`. If it exists, it will be merged with `.umirc.js` and then returned. 28 | 29 | ## UMI_ENV 30 | 31 | The configuration can be specified by the environment variable `UMI_ENV` to distinguish between different environments. 32 | 33 | For a example, 34 | 35 | ```js 36 | // .umirc.js 37 | export default { a: 1, b: 2 }; 38 | 39 | // .umirc.cloud.js 40 | export default { b: 'cloud', c: 'cloud' }; 41 | 42 | // .umirc.local.js 43 | export default { c: 'local' }; 44 | ``` 45 | 46 | When `UMI_ENV` is not specified, the configuration is: 47 | 48 | ```js 49 | { 50 | a: 1, 51 | b: 2, 52 | c: 'local', 53 | } 54 | ``` 55 | 56 | When `UMI_ENV=cloud` is specified, the configuration is: 57 | 58 | ```js 59 | { 60 | a: 1, 61 | b: 'cloud', 62 | c: 'local', 63 | } 64 | ``` 65 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: true 3 | actionText: Get Started → 4 | actionLink: /guide/ 5 | features: 6 | - title: Pluggable 7 | details: The entire lifecycle of umi is composed of plugins. Features such as pwa, on-demand loading, one-click switching preact, one-button compatibility ie9, etc., are all implemented by plugins. 8 | - title: Out Of Box 9 | details: You only need an umi dependency to start development without having to install react, preact, webpack, react-router, babel, jest, and more. 10 | - title: Conventional Routing 11 | details: Next.js like and full featured routing conventions, support permissions, dynamic routing, nested routing, and more. 12 | footer: MIT Licensed | Copyright © 2017-present 13 | --- 14 | 15 | ### Getting started is very simple 16 | 17 | ```bash 18 | # Install deps 19 | $ yarn global add umi # or npm install -g umi 20 | 21 | # Create application 22 | $ mkdir myapp && cd myapp 23 | 24 | # Create page 25 | $ umi generate page index 26 | 27 | # Start dev server 28 | $ umi dev 29 | 30 | # Build and deploy 31 | $ umi build 32 | ``` 33 | 34 | [Getting started with a 10 minutes video](https://youtu.be/vkAUGUlYm24) 35 | 36 | ## Community 37 | 38 | ### Telegram 39 | 40 | [https://t.me/joinchat/G0DdHw-44FO7Izt4K1lLFQ](https://t.me/joinchat/G0DdHw-44FO7Izt4K1lLFQ) 41 | 42 | ### 钉钉群 43 | 44 | 45 | 46 | ### WeChat Group 47 | 48 | Group of 100 people, please add `sorryccpro` friend note `umi` invite to join. 49 | -------------------------------------------------------------------------------- /packages/umi/src/build.md: -------------------------------------------------------------------------------- 1 | ```js 2 | import buildDevOpts from './buildDevOpts'; 3 | ``` 4 | 引入buildDevOpts,用于配置开发环境所需要的option。 5 | ```js 6 | process.env.NODE_ENV = 'production'; 7 | ``` 8 | 设置环境变量 9 | ```js 10 | export default function(opts = {}) { 11 | return require('umi-build-dev/lib/build').default( 12 | buildDevOpts({ 13 | ...opts, 14 | hash: true, 15 | }), 16 | ); 17 | } 18 | ``` 19 | 这里传入的opts={ plugins: [] } 20 | buildDevOpts将会返回如下对象 21 | ```json 22 | { 23 | cwd: undefined, 24 | babel: 'C:\\Users\\admin\\AppData\\Roaming\\npm\\node_modules\\umi\\lib\\babel', 25 | extraResolveModules: 26 | [ 'C:\\Users\\admin\\AppData\\Roaming\\npm\\node_modules\\node_modules' ], 27 | libraryAlias: 28 | { dynamic: 'C:\\Users\\admin\\AppData\\Roaming\\npm\\node_modules\\umi\\lib\\dynamic.js', 29 | link: 'C:\\Users\\admin\\AppData\\Roaming\\npm\\node_modules\\umi\\lib\\link.js', 30 | navlink: 'C:\\Users\\admin\\AppData\\Roaming\\npm\\node_modules\\umi\\lib\\navlink.js', 31 | redirect: 'C:\\Users\\admin\\AppData\\Roaming\\npm\\node_modules\\umi\\lib\\redirect.js', 32 | router: 'C:\\Users\\admin\\AppData\\Roaming\\npm\\node_modules\\umi\\lib\\router.js', 33 | withRouter: 'C:\\Users\\admin\\AppData\\Roaming\\npm\\node_modules\\umi\\lib\\withRouter.js', 34 | _renderRoutes: 'C:\\Users\\admin\\AppData\\Roaming\\npm\\node_modules\\umi\\lib\\renderRoutes.js', 35 | _createHistory: 'C:\\Users\\admin\\AppData\\Roaming\\npm\\node_modules\\umi\\lib\\createHistory.js' }, 36 | hash: true, 37 | plugins: [] } 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/zh/guide/examples.md: -------------------------------------------------------------------------------- 1 | # 例子 2 | 3 | ## 成品 4 | 5 | * [Ant Design Pro](https://github.com/ant-design/ant-design-pro),Use Ant Design like a Pro! 6 | * [Antd Admin](https://github.com/zuiidea/antd-admin),A admin dashboard application demo built upon Ant Design and Dva.js. 7 | 8 | ## 官方 9 | 10 | * [with-dva](https://github.com/umijs/umi-examples/tree/master/with-dva),umi + dva 的例子 11 | * [umi-dva-user-dashboard](https://github.com/umijs/umi-dva-user-dashboard),umi + dva 的 dashboard 例子 12 | * [routes](https://github.com/umijs/umi-examples/tree/master/routes),约定式路由的例子 13 | * [routes-via-config](https://github.com/umijs/umi-examples/blob/master/routes-via-config),配置式路由的例子 14 | * [typescript](https://github.com/umijs/umi-examples/blob/master/typescript),使用 TypeScript 的例子 15 | * [umi-example-electron](https://github.com/umijs/umi-example-electron),umi + electron 的例子 16 | * [with-unstated](https://github.com/umijs/umi-examples/tree/master/with-unstated),使用 unstated 的例子 17 | * [with-nav-and-sidebar](https://github.com/umijs/umi-examples/tree/master/with-nav-and-sidebar),包含 antd-pro 的头和侧边栏的例子 18 | 19 | ## 社区 20 | 21 | ::: warning 警告 22 | 以下例子使用 umi@1.x,尚未升级到 umi@2。 23 | ::: 24 | 25 | * [umi-antd-pro](https://github.com/xiaohuoni/umi-antd-pro),来自 @xiaohuni 的 umi + antd-pro 的例子,antd-pro 官方版本计划在 2.0 之后切换到 umi,还需等待一些时间 26 | * [dva-umi](https://github.com/xiaohuoni/dva-umi),来自 @xiaohuni 的 umi + dva 的脚手架 27 | * [dva-umi-mobile](https://github.com/xiaohuoni/dva-umi-mobile),来自 @xiaohuni 的 umi + dva 的 mobile 版本脚手架 28 | * [umi-pro](https://github.com/boxcc/umi-pro),来自 @boxcc 的 antd-pro 例子 29 | 30 | -------------------------------------------------------------------------------- /docs/guide/html-template.md: -------------------------------------------------------------------------------- 1 | # HTML Template 2 | 3 | ::: warning 4 | This article has not been translated yet. Wan't to help us out? Click the `Edit this page on GitHub` at the end of the page. 5 | ::: 6 | 7 | ## Modify the default template 8 | 9 | Create a new `src/pages/document.ejs`, umi stipulates that if this file exists, it will be used as the default template. You need to ensure that `
` appears. 10 | 11 | ```html 12 | 13 | 14 | 15 | 16 | Your App 17 | 18 | 19 |
20 | 21 | 22 | ``` 23 | 24 | ## Configure the template 25 | 26 | 模板里可通过 `context` 来获取到 umi 提供的变量,context 包含: 27 | 28 | * `route`,路由对象,包含 path、component 等 29 | * `config`,用户配置信息 30 | * `publicPath`,webpack 的 `output.publicPath` 配置 31 | * `env`,环境变量,值为 development 或 production 32 | * 其他在路由上通过 context 扩展的配置信息 33 | 34 | 模板基于 ejs 渲染,可以参考 [https://github.com/mde/ejs](https://github.com/mde/ejs) 查看具体使用。 35 | 36 | 比如输出变量, 37 | 38 | ```html 39 | 40 | ``` 41 | 42 | 比如条件判断, 43 | 44 | ```html 45 | <% if(context.env === 'production') { %> 46 |

生产环境

47 | <% } else {%> 48 |

开发环境

49 | <% } %> 50 | ``` 51 | 52 | ## 针对特定页面指定模板 53 | 54 | ::: warning 55 | 此功能需开启 `exportStatic` 配置,否则只会输出一个 html 文件。 56 | ::: 57 | 58 | ::: tip 59 | 优先级是:路由的 document 属性 > src/pages/document.ejs > umi 内置模板 60 | ::: 61 | 62 | 配置路由的 document 属性。 63 | 64 | 比如约定式路由可通过注释扩展 `document` 属性,路径从项目根目录开始找, 65 | 66 | ```js 67 | /** 68 | * document: ./src/documents/404.ejs 69 | */ 70 | ``` 71 | 72 | 然后这个路由就会以 `./src/documents/404.ejs` 为模板输出 HTML。 73 | -------------------------------------------------------------------------------- /packages/umi/src/help.md: -------------------------------------------------------------------------------- 1 | ```js 2 | import chalk from 'chalk'; 3 | ``` 4 | 把现有的支持的命令都罗列出来,名字,简介,别名 5 | ```js 6 | const commands = { 7 | build: { 8 | name: 'build', 9 | description: 'Create a production build', 10 | }, 11 | dev: { 12 | name: 'dev', 13 | description: 'Start a development server', 14 | }, 15 | test: { 16 | name: 'test', 17 | description: 'Start a development server', 18 | }, 19 | help: { 20 | name: 'help', 21 | description: 'show help', 22 | aliases: ['h'], 23 | }, 24 | version: { 25 | name: 'version', 26 | description: 'Outputs Umi version.', 27 | aliases: ['v'], 28 | }, 29 | }; 30 | ``` 31 | 统一调用的打印方法,其实这个应该放别的地方,做util工具使用 32 | ```js 33 | class Logger { 34 | info = message => { 35 | console.log(`${message}`); 36 | }; 37 | 38 | error = message => { 39 | console.error(chalk.red(message)); 40 | }; 41 | 42 | success = message => { 43 | console.error(chalk.green(message)); 44 | }; 45 | } 46 | ``` 47 | 对现有支持的数组做一个遍历,打印出所有的使用方法 48 | ```js 49 | export default function(opts = {}) { 50 | const { type } = opts; 51 | const logger = new Logger(); 52 | logger.info(`\nUsage: umi \n`); 53 | if (!commands[type]) { 54 | logger.error(`Unknown script : ${chalk.cyan(type)}.`); 55 | } 56 | logger.info(`Available Commands:`); 57 | for (const key in commands) { 58 | if (commands.hasOwnProperty(key)) { 59 | const cmd = commands[key]; 60 | logger.info(` ${chalk.cyan(cmd.name)} ${cmd.description}`); 61 | } 62 | } 63 | // 这里应该是留做后续接口扩展说明的,如使用umi dev --help,应该要打印出dev的说明,还有所支持的环境变量等等。 64 | // Support for subsequent extensions 65 | // logger.info(`\nFor more detailed help run "umi [command name] --help"`); 66 | } 67 | ``` 68 | 文中注释可扩展的地方是因为现在umi版本还不是那么稳定,这一块的功能我没想好怎么处理。应该要支持多语言。 -------------------------------------------------------------------------------- /docs/guide/examples.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | ## Finished Products 4 | 5 | * [Ant Design Pro](https://github.com/ant-design/ant-design-pro), Use Ant Design like a Pro! 6 | * [Antd Admin](https://github.com/zuiidea/antd-admin), An admin dashboard application demo built upon Ant Design and Dva.js. 7 | 8 | ## Official 9 | 10 | * [with-dva](https://github.com/umijs/umi-examples/tree/master/with-dva), Example of umi + dva 11 | * [umi-dva-user-dashboard](https://github.com/umijs/umi-dva-user-dashboard), Example of dashboard with umi + dva 12 | * [routes](https://github.com/umijs/umi-examples/tree/master/routes), Example for convensional routing 13 | * [routes-via-config](https://github.com/umijs/umi-examples/blob/master/routes-via-config), Example for configurable routing 14 | * [typescript](https://github.com/umijs/umi-examples/blob/master/typescript), Example of using TypeScript 15 | * [umi-example-electron](https://github.com/umijs/umi-example-electron), Example of umi + electron 16 | * [with-unstated](https://github.com/umijs/umi-examples/tree/master/with-unstated), Example of using unstated 17 | * [with-nav-and-sidebar](https://github.com/umijs/umi-examples/tree/master/with-nav-and-sidebar), Example containing the header and sidebar of antd-pro 18 | 19 | ## Community 20 | 21 | ::: warning 22 | The following example uses umi@1.x and has not been upgraded to umi@2. 23 | ::: 24 | 25 | * [umi-antd-pro](https://github.com/xiaohuoni/umi-antd-pro), an example of umi + antd-pro from @xiaohuni, the official version of antd-pro is scheduled to switch to umi after 2.0 Still have to wait for some time 26 | * [dva-umi](https://github.com/xiaohuoni/dva-umi), umi + dva scaffolding from @xiaohuni 27 | * [dva-umi-mobile](https://github.com/xiaohuoni/dva-umi-mobile), umi + dva mobile version scaffolding from @xiaohuni 28 | * [umi-pro](https://github.com/boxcc/umi-pro), an antd-pro example from @boxcc 29 | 30 | -------------------------------------------------------------------------------- /docs/zh/guide/README.md: -------------------------------------------------------------------------------- 1 | 2 | # 介绍 3 | 4 | umi,中文可发音为乌米,是一个可插拔的企业级 react 应用框架。umi 以路由为基础的,支持[类 next.js 的约定式路由](https://umijs.org/zh/guide/router.html),以及各种进阶的路由功能,并以此进行功能扩展,比如[支持路由级的按需加载](https://umijs.org/zh/plugin/umi-plugin-react.html#dynamicimport)。然后配以完善的[插件体系](https://umijs.org/zh/plugin/),覆盖从源码到构建产物的每个生命周期,支持各种功能扩展和业务需求,目前内外部加起来已有 50+ 的插件。 5 | 6 | umi 是蚂蚁金服的底层前端框架,已直接或间接地服务了 600+ 应用,包括 java、node、H5 无线、离线(Hybrid)应用、纯前端 assets 应用、CMS 应用等。他已经很好地服务了我们的内部用户,同时希望他也能服务好外部用户。 7 | 8 | ## 特性 9 | 10 | * 📦 **开箱即用**,内置 react、react-router 等 11 | * 🏈 **类 next.js 且[功能完备](./router.html)的路由约定**,同时支持配置的路由方式 12 | * 🎉 **完善的插件体系**,覆盖从源码到构建产物的每个生命周期 13 | * 🚀 **高性能**,通过插件支持 PWA、以路由为单元的 code splitting 等 14 | * 💈 **支持静态页面导出**,适配各种环境,比如中台业务、无线业务、[egg](https://github.com/eggjs/egg)、支付宝钱包、云凤蝶等 15 | * 🚄 **开发启动快**,支持一键开启 [dll](../plugin/umi-plugin-react.html#dll) 和 [hard-source-webpack-plugin](../plugin/umi-plugin-react.html#hardSource) 等 16 | * 🐠 **一键兼容到 IE9**,基于 [umi-plugin-polyfills](../plugin/umi-plugin-react.html#polyfills) 17 | * 🍁 **完善的 TypeScript 支持**,包括 d.ts 定义和 umi test 18 | * 🌴 **与 [dva](https://dvajs.com/) 数据流的深入融合**,支持 duck directory、model 的自动加载、code splitting 等等 19 | 20 | ## 架构 21 | 22 | 下图是 umi 的架构图。 23 | 24 | 25 | 26 | ## 从源码到上线的生命周期管理 27 | 28 | 市面上的框架基本都是从源码到构建产物,很少会考虑到各种发布流程,而 umi 则多走了这一步。 29 | 30 | 下图是 umi 从源码到上线的一个流程。 31 | 32 | 33 | 34 | umi 首先会加载用户的配置和插件,然后基于配置或者目录,生成一份路由配置,再基于此路由配置,把 JS/CSS 源码和 HTML 完整地串联起来。用户配置的参数和插件会影响流程里的每个环节。 35 | 36 | ## 他和 dva、roadhog 是什么关系? 37 | 38 | 简单来说, 39 | 40 | * roadhog 是基于 webpack 的封装工具,目的是简化 webpack 的配置 41 | * umi 可以简单地理解为 roadhog + 路由,思路类似 next.js/nuxt.js,辅以一套插件机制,目的是通过框架的方式简化 React 开发 42 | * dva 目前是纯粹的数据流,和 umi 以及 roadhog 之间并没有相互的依赖关系,可以分开使用也可以一起使用,个人觉得 [umi + dva 是比较搭的](https://github.com/sorrycc/blog/issues/66) 43 | 44 | ## 为什么不是...? 45 | 46 | ### next.js 47 | 48 | next.js 的功能相对比较简单,比如他的路由配置并不支持一些高级的用法,比如布局、嵌套路由、权限路由等等,而这些在企业级的应用中是很常见的。相比 next.js,umi 在约定式路由的功能层面会更像 nuxt.js 一些。 49 | 50 | ### roadhog 51 | 52 | roadhog 是比较纯粹的 webpack 封装工具,作为一个工具,他能做的就比较有限(限于 webpack 层)。而 umi 则等于 roadhog + 路由 + HTML 生成 + 完善的插件机制,所以能在提升开发者效率方面发挥出更大的价值。 53 | -------------------------------------------------------------------------------- /docs/guide/README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | umi is a routing-based framework that supports [next.js-like conventional routing](https://umijs.org/guide/router.html) and various advanced routing functions, such as [routing-level on-demand loading](https://umijs.org/en/plugin/umi-plugin-react.html#dynamicimport). With a complete [plugin system](https://umijs.org/plugin/) that covers every life cycle from source code to build product, umi is able to support various functional extensions and business needs. Currently umi has almost 50+ plugins in both community and inside company. 4 | 5 | umi is the basic front-end framework of [Ant Financial](https://www.antfin.com/), and has served 600+ applications directly or indirectly, including Java, node, mobile apps, Hybrid apps, pure front-end assets apps, CMS apps, and more. umi has served our internal users very well and we hope that it can also serve external users well. 6 | 7 | ## Features 8 | 9 | * 📦 **Out of box**, with built-in support for react, react-router, etc. 10 | * 🏈 **Next.js like and [full featured](./router.html) routing conventions**, which also supports configured routing 11 | * 🎉 **Complete plugin system**, covering every lifecycle from source code to production 12 | * 🚀 **High performance**, with support for PWA, route-level code splitting, etc. via plugins 13 | * 💈 **Support for static export**, adapt to various environments, such as console app, mobile app, [egg](https://github.com/eggjs/egg), Alipay wallet, etc 14 | * 🚄 **Fast dev startup**, support enable [dll](../plugin/umi-plugin-react.html#dll) and [hard-source-webpack-plugin](../plugin/umi-plugin-react.html#hardSource) with config 15 | * 🐠 **Compatible with IE9**, based on [umi-plugin-polyfills](../plugin/umi-plugin-react.html#polyfills) 16 | * 🍁 **Support TypeScript**, including d.ts definition and `umi test` 17 | * 🌴 **Deep integration with [dva](https://dvajs.com/)**, support duck directory, automatic loading of model, code splitting, etc 18 | 19 | ## Architecture 20 | 21 | The figure below is the architecture of umi. 22 | 23 | 24 | 25 | ## Why not...? 26 | 27 | ### next.js 28 | 29 | The routing of next.js is relatively simple. For example, its routing configuration does not support some advanced usages such as layout, nested routing, permission routing, etc., which are common in enterprise applications. Compared to next.js, umi is more like nuxt.js at the functional level of contracted routing. 30 | 31 | -------------------------------------------------------------------------------- /docs/zh/guide/env-variables.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebarDepth: 3 3 | --- 4 | 5 | # .env 和环境变量 6 | 7 | ## 如何配置 8 | 9 | 比如要 10 | 11 | ``` 12 | # OS X, Linux 13 | $ PORT=3000 umi dev 14 | 15 | # Windows (cmd.exe) 16 | $ set PORT=3000&&umi dev 17 | 18 | # Or use cross-env for all platforms 19 | $ yarn add cross-env --dev 20 | $ cross-env PORT=3000 umi dev 21 | 22 | # .env 23 | $ echo PORT=3000 > .env 24 | ``` 25 | 26 | ## 环境变量 27 | 28 | ### UMI_ENV 29 | 30 | 指定覆盖默认配置的配置文件。比如 `UMI_ENV=prod umi build`,那么则会用 `.umirc.prod.js` 覆盖 `.umirc.js`。或者是 `config/config.prod.js` 覆盖 `config/config.js`。注意是覆盖而不是替换,`.umirc.prod.js` 中没有的配置者会使用 `.umirc.js` 中的配置。 31 | 32 | 另外,开发模式下 `.umirc.local.js` 或者 `config/config.local.js` 中的配置永远是优先级最高的。 33 | 34 | ### PORT 35 | 36 | 指定端口号,默认是 `8000`。比如: 37 | 38 | ```bash 39 | $ PORT=8001 umi dev 40 | ``` 41 | 42 | ### HOST 43 | 44 | 默认是 `0.0.0.0`。 45 | 46 | ### APP_ROOT 47 | 48 | ::: warning 49 | APP_ROOT 不能配在 .env 里。 50 | ::: 51 | 52 | 指定项目根目录。比如: 53 | 54 | ```bash 55 | $ APP_ROOT=src/renderer umi dev 56 | ``` 57 | 58 | ### ANALYZE 59 | 60 | 默认关闭。分析 bundle 构成,build 时有效。比如: 61 | 62 | ```bash 63 | $ ANALYZE=1 umi build 64 | ``` 65 | 66 | ### ANALYZE_PORT 67 | 68 | ANALYZE 服务器端口,默认 8888。 69 | 70 | ### BABEL_POLYFILL 71 | 72 | 默认引入 `@babel/polyfill`,值为 none 时不引入。比如: 73 | 74 | ```bash 75 | $ BABEL_POLYFILL=none umi build 76 | ``` 77 | 78 | ### COMPRESS 79 | 80 | 默认压缩 CSS 和 JS,值为 none 时不压缩,build 时有效。比如: 81 | 82 | ```bash 83 | $ COMPRESS=none umi build 84 | ``` 85 | 86 | ### CSS_COMPRESS 87 | 88 | 默认压缩,值为 none 时不压缩,build 时有效。因为 css 压缩有时是会有问题的,而且压缩并不能减少多少尺寸,所以有时可以压 JS 而不压 CSS。 89 | 90 | ### BROWSER 91 | 92 | 默认自动开浏览器,值为 none 时不自动打开,dev 时有效。比如: 93 | 94 | ```bash 95 | $ BROWSER=none umi dev 96 | ``` 97 | 98 | ### CLEAR_CONSOLE 99 | 100 | 默认清屏,值为 none 时不清屏。 101 | 102 | ### HMR 103 | 104 | 默认开启 HMR,值为 none 时禁用,值为 reload 时文件有变化时刷新浏览器。 105 | 106 | ### BABELRC 107 | 108 | 开启 `.babelrc` 解析,默认不解析。 109 | 110 | ### BABEL_CACHE 111 | 112 | 默认开启 babel cache,值为 none 时禁用。比如: 113 | 114 | ```bash 115 | $ BABEL_CACHE=none umi dev 116 | ``` 117 | 118 | ### MOCK 119 | 120 | 默认开启 mock,值为 none 时禁用。比如: 121 | 122 | ```bash 123 | $ MOCK=none umi dev 124 | ``` 125 | 126 | ### HTML 127 | 128 | 默认打包 HTML 文件,值为 none 时不打包 HTML 文件。比如: 129 | 130 | ```bash 131 | $ HTML=none umi build 132 | ``` 133 | 134 | ### WATCH_FILES 135 | 136 | ### RM_TMPDIR 137 | 138 | ### FORK_TS_CHECKER 139 | 默认不开启TypeScript检查,值为1时启用。比如: 140 | 141 | ```bash 142 | $ FORK_TS_CHECKER=1 umi dev 143 | ``` 144 | -------------------------------------------------------------------------------- /packages/umi/src/cli.md: -------------------------------------------------------------------------------- 1 | ```js 2 | import { dirname } from 'path'; 3 | import yParser from 'yargs-parser'; 4 | import signale from 'signale'; 5 | import semver from 'semver'; 6 | import buildDevOpts from './buildDevOpts'; 7 | ``` 8 | ```js 9 | let script = process.argv[2]; 10 | const args = yParser(process.argv.slice(3)); 11 | ``` 12 | process模块用来与当前进程互动,可以通过全局变量process访问,不必使用require命令加载。它是一个EventEmitter对象的实例。 13 | 14 | process对象提供一系列属性,用于返回系统信息。 15 | - process.pid:当前进程的进程号。 16 | - process.version:Node的版本,比如v0.10.18。 17 | - process.platform:当前系统平台,比如Linux。 18 | - process.title:默认值为“node”,可以自定义该值。 19 | - process.argv:当前进程的命令行参数数组。 20 | - process.env:指向当前shell的环境变量,比如process.env.HOME。 21 | - process.execPath:运行当前进程的可执行文件的绝对路径。 22 | - process.stdout:指向标准输出。 23 | - process.stdin:指向标准输入。 24 | - process.stderr:指向标准错误。 25 | 26 | yParser 用于取出执行命令时携带的参数。 27 | 比如执行 umi dev haha xixi --me=xiaohuoni 28 | ```base 29 | // process.argv 30 | [ 31 | 'C:\\Program Files\\nodejs\\node.exe', 32 | 'C:\\Users\\Administrator\\AppData\\Roaming\\npm\\node_modules\\umi\\bin\\umi.js', 33 | 'dev', 34 | 'haha', 35 | 'xixi' 36 | ] 37 | ``` 38 | 那么此时 39 | 40 | script = dev 41 | 42 | args = { _: [], haha: true, xixi: true, me:'xiaohuoni' } 43 | 44 | ```js 45 | // Node version check 46 | const nodeVersion = process.versions.node; 47 | if (semver.satisfies(nodeVersion, '<6.5')) { 48 | signale.error(`Node version must >= 6.5, but got ${nodeVersion}`); 49 | process.exit(1); 50 | } 51 | ``` 52 | 判断当前node的版本大于v6.5 53 | - process.exit(0)表示成功完成,回调函数中,err将为null; 54 | - process.exit(非0)表示执行失败,回调函数中,err不为null,err.code就是我们传给exit的数字。 55 | ```js 56 | // Notify update when process exits 57 | const updater = require('update-notifier'); 58 | const pkg = require('../package.json'); 59 | updater({ pkg }).notify({ defer: true }); 60 | ``` 61 | 进程退出时通知更新,其中defer:true,表示在进程退出后显示通知。 62 | ```js 63 | process.env.UMI_DIR = dirname(require.resolve('../package')); 64 | process.env.UMI_VERSION = pkg.version; 65 | ``` 66 | 定义了两个环境变量,用于后续功能使用吧。 67 | ```js 68 | const aliasMap = { 69 | '-v': 'version', 70 | '--version': 'version', 71 | '-h': 'help', 72 | '--help': 'help', 73 | }; 74 | ``` 75 | 给命令取别名,比如这里给version取了个别名叫做-v 76 | 当执行umi -v 时,相当于执行umi version 77 | ```js 78 | switch (script) { 79 | case 'build': 80 | case 'dev': 81 | case 'test': 82 | case 'inspect': 83 | require(`./scripts/${script}`); 84 | break; 85 | default: { 86 | const Service = require('umi-build-dev/lib/Service').default; 87 | new Service(buildDevOpts(args)).run(aliasMap[script] || script, args); 88 | break; 89 | } 90 | } 91 | ``` 92 | 93 | defaule中使用service启动命令,是为了执行那些使用```api.registerCommand```注册的命令行,比如内置的umi help就是这么执行的。 94 | -------------------------------------------------------------------------------- /packages/umi-build-dev/src/plugins/404/index.md: -------------------------------------------------------------------------------- 1 | ```js 2 | import { join, basename, extname } from 'path'; 3 | ``` 4 | # join 5 | 对于以/开始的路径片段,path.join只是简单的将该路径片段进行拼接 6 | ```js 7 | path.join('/a','/b') // 'a/b' 8 | ``` 9 | # basename 10 | 提取出用 '/' 隔开的path的最后一部分 11 | ```js 12 | path.basename('/a/b/c/d/e.html') // 'e.html' 13 | ``` 14 | # extname 15 | 返回path路径文件扩展名,如果path以 ‘.' 为结尾,将返回 ‘.',如果无扩展名 又 不以'.'结尾,将返回空值 16 | ```js 17 | path.extname('/a/b/c/d/e.html') // '.html' 18 | path.extname('/a/b/c/d/e.') // '.' 19 | path.extname('/a/b/c/d/e') // '' 20 | ``` 21 | ```import { readFileSync } from 'fs';``` 22 | readFileSync 同步读取 23 | ```js 24 | /** 25 | ** 26 | **/ 27 | export function patchRoutes(routes) { 28 | let index = null; 29 | for (const [i, value] of routes.entries()) { 30 | const { component } = value; 31 | if (basename(component, extname(component)) === '404') { 32 | index = i; 33 | } 34 | if (value.routes) { 35 | value.routes = patchRoutes(value.routes); 36 | } 37 | } 38 | if (index !== null) { 39 | const route = routes.splice(index, 1)[0]; 40 | routes = routes.concat({ 41 | component: route.component, 42 | }); 43 | } 44 | return routes; 45 | } 46 | ``` 47 | export default function(api) { 48 | const { paths, config } = api.service; 49 | 50 | if (process.env.NODE_ENV === 'production' && !config.exportStatic) { 51 | api.register('modifyRoutes', ({ memo }) => { 52 | return patchRoutes(memo); 53 | }); 54 | } 55 | 56 | api.register('beforeServer', ({ args: { devServer } }) => { 57 | function UMI_PLUGIN_404(req, res, next) { 58 | if (req.accepts('html')) { 59 | let pageContent = readFileSync( 60 | join(__dirname, '../../../template/404.html'), 61 | 'utf-8', 62 | ); 63 | const routes = [...api.service.routes]; 64 | const rootRoute = routes.filter(route => route.path === '/')[0]; 65 | if (rootRoute) { 66 | routes.unshift({ 67 | ...rootRoute, 68 | path: '/index.html', 69 | }); 70 | } 71 | pageContent = pageContent 72 | .replace('<%= PAGES_PATH %>', paths.pagesPath) 73 | .replace( 74 | '<%= PAGES_LIST %>', 75 | routes 76 | .map(route => { 77 | return `
  • ${route.path}
  • `; 78 | }) 79 | .join('\r\n'), 80 | ); 81 | res.writeHead(404, { 'Content-Type': 'text/html' }); 82 | res.write(pageContent); 83 | res.end(); 84 | } else { 85 | next(); 86 | } 87 | } 88 | devServer.use(UMI_PLUGIN_404); 89 | }); 90 | } 91 | -------------------------------------------------------------------------------- /docs/zh/guide/migration.md: -------------------------------------------------------------------------------- 1 | # 从 umi 1.x 迁移 2 | 3 | > 更喜欢观看视频?可以[点此观看](https://youtu.be/1mvKzFLLBck)。 4 | 5 | 下面以 [antd-admin](https://github.com/zuiidea/antd-admin/pull/877) 为例,介绍如何从 umi@1 升级到 umi@2 。 6 | 7 | ## npm 依赖 8 | 9 | 升级 umi 到 `^2.0.0-0`,并使用 umi-plugin-react 代替以前的众多插件,包含 umi-plugin-dva、umi-plugin-dll、umi-plugin-routes、umi-plugin-polyfill 和 umi-plugin-locale。 10 | 11 | ```diff 12 | - "umi": "^1.3.17", 13 | + "umi": "^2.0.0-beta.16", 14 | 15 | - "umi-plugin-dll": "^0.2.1", 16 | - "umi-plugin-dva": "^0.9.1", 17 | - "umi-plugin-routes": "^0.1.5" 18 | + "umi-plugin-react": "^1.0.0-beta.16", 19 | ``` 20 | 21 | umi-plugin-react 是一个包含了十多个插件的集合,详见 [umi-plugin-react 介绍](/zh/plugin/umi-plugin-react.html)。 22 | 23 | ## 环境变量 24 | 25 | umi@2 支持在 `.env` 里配置环境变量,所以之前写在 package.json scripts 里的环境变量可以切到这里。 26 | 27 | ```diff 28 | - "start": "cross-env COMPILE_ON_DEMAND=none BROWSER=none HOST=0.0.0.0 umi dev", 29 | + "start": "cross-env BROWSER=none HOST=0.0.0.0 umi dev", 30 | ``` 31 | 32 | 然后新建 `.env`,(其中 `COMPILE_ON_DEMAND` 已不再支持) 33 | 34 | ``` 35 | BROWSER=none 36 | HOST=0.0.0.0 37 | ``` 38 | 39 | 另外,有些环境变量有变化或不再支持: 40 | 41 | * 不再支持 `PUBLIC_PATH`,通过配置 `publicPath` 实现 42 | * 不再支持 `BASE_URL`,通过配置 `base` 实现 43 | * 不再支持 `COMPILE_ON_DEMAND`,umi@2 里没有这个功能了 44 | * 不再支持 `TSLINT`,umi@2 里没有这个功能了 45 | * 不再支持 `ESLINT`,umi@2 里没有这个功能了 46 | 47 | ## 配置 48 | 49 | ### 插件配置 50 | 51 | 由于前面我们把很多插件改成通过 umi-plugin-react 实现,所以需要修改 `.umirc.js`, 52 | 53 | ```diff 54 | export default { 55 | plugins: [ 56 | - 'umi-plugin-dva', 57 | + ['umi-plugin-react', { 58 | + dva: true, 59 | + antd: true, // antd 默认不开启,如有使用需自行配置 60 | + }], 61 | ], 62 | }; 63 | ``` 64 | 65 | 更多 dll、hardSource、polyfilles、locale、title 等,参考 [umi-plugin-react 文档](/zh/plugin/umi-plugin-react.html)。 66 | 67 | ### webpackrc.js 68 | 69 | umi@2 不再支持 `webpackrc.js`,把里面的配置原样复制到 `.umirc.js` 即可。 70 | 71 | ### webpack.config.js 72 | 73 | umi@2 不再支持 `webpack.config.js`,改为通过配置 [chainWebpack](/zh/config/#chainwebpack) 实现。 74 | 75 | ### 详细的配置项变更 76 | 77 | * 不再支持 `hd`,如需开启,装载插件 `umi-plugin-react` 并配置 `hd: {}` 78 | * 不再支持 `disableServiceWorker`,默认不开启,如需开启,装载插件 `umi-plugin-react` 并配置 `pwa: {}` 79 | * 不再支持 `preact`,如需配置,装载插件 `umi-plugin-react` 并配置 `library: 'preact'` 80 | * 不再支持 `loading`,如需配置,装载插件 `umi-plugin-react` 并配置 `dynamicImport.loadingComponent` 81 | * `hashHistory: true` 变更为 `history: 'hash'` 82 | * 不再支持 `disableDynamicImport`,默认不开启,如需开启,装载插件 `umi-plugin-react` 并配置 `dynamicImport: {}` 83 | * 不再支持 `disableFastClick`,默认不开启,如需开启,装载插件 `umi-plugin-react` 并配置 `fastClick: {}` 84 | * 不再支持 `pages`,改为直接配在路由上 85 | * 不再支持 `disableHash`,默认不开启,如需开启,配置 `hash: true` 86 | 87 | ## 约定式路由 88 | 89 | 路由层不再支持 `page.js` 的目录级路由。之前如果有用,需要把不需要的路由通过 umi-plugin-react 的 routes.exclude 排除掉。 90 | 91 | ## umi/dynamic 92 | 93 | 接口变更,umi@2 是基于 [react-loadable](https://github.com/jamiebuilds/react-loadable) 实现的。 94 | 95 | ```diff 96 | - dynamic(async () => {}) 97 | + dynamic({ loader: async () => {}}) 98 | ``` 99 | 100 | 详见 [umi/dynamic 接口说明](/zh/api/#umi-dynamic)。 101 | -------------------------------------------------------------------------------- /docs/zh/guide/deploy.md: -------------------------------------------------------------------------------- 1 | # 部署 2 | 3 | ## 默认方案 4 | 5 | umi@2 默认对新手友好,所以默认不做按需加载处理,`umi build` 后输出 `index.html`、`umi.js` 和 `umi.css` 三个文件。 6 | 7 | ## 不输出 html 文件 8 | 9 | 某些场景 html 文件交给后端输出,前端构建并不需要输出 html 文件,可配置环境变量 `HTML=none` 实现。 10 | 11 | ```bash 12 | $ HTML=none umi build 13 | ``` 14 | 15 | ## 部署 html 到非根目录 16 | 17 | 经常有同学问这个问题: 18 | 19 | > 为什么我本地开发是好的,部署后就没反应了,而且没有报错? 20 | 21 | **没有报错!** 这是应用部署在非根路径的典型现象。为啥会有这个问题?因为路由没有匹配上,比如你把应用部署在 `/xxx/` 下,然后访问 `/xxx/hello`,而代码里匹配的是 `/hello`,那就匹配不上了,而又没有定义 fallback 的路由,比如 404,那就会显示空白页。 22 | 23 | 怎么解决? 24 | 25 | 可通过配置 [base](/zh/config/#base) 解决。 26 | 27 | ```bash 28 | export default { 29 | base: '/path/to/your/app/root', 30 | }; 31 | ``` 32 | 33 | ## 使用 hashHistory 34 | 35 | 可通过配置 [history](/zh/config/#history) 为 `hash` 为解决。 36 | 37 | ```bash 38 | export default { 39 | history: 'hash', 40 | }; 41 | ``` 42 | 43 | ## 按需加载 44 | 45 | 要实现按需加载,需装载 umi-plugin-react 插件并配置 [dynamicImport](/zh/plugin/umi-plugin-react.html#dynamicimport)。 46 | 47 | ```js 48 | export default { 49 | plugins: [ 50 | ['umi-plugin-react', { 51 | dynamicImport: true, 52 | }], 53 | ], 54 | }; 55 | ``` 56 | 57 | 参数详见:[umi-plugin-react#dynamicImport](/zh/plugin/umi-plugin-react.html#dynamicimport)。 58 | 59 | ## 静态资源在非根目录或 cdn 60 | 61 | 这时,就需要配置 [publicPath](/zh/config/#publicPath)。至于 publicPath 是啥?具体看 [webpack 文档](https://webpack.js.org/configuration/output/#output-publicpath),把他指向静态资源(js、css、图片、字体等)所在的路径。 62 | 63 | ```js 64 | export default { 65 | publicPath: "http://yourcdn/path/to/static/" 66 | } 67 | ``` 68 | 69 | ## 使用 runtime 的 publicPath 70 | 71 | 对于需要在 html 里管理 publicPath 的场景,比如在 html 里判断环境做不同的输出,可通过配置 [runtimePublicPath](/zh/config/#history) 为解决。 72 | 73 | ```bash 74 | export default { 75 | runtimePublicPath: true, 76 | }; 77 | ``` 78 | 79 | 然后在 html 里输出: 80 | 81 | ```html 82 | 85 | ``` 86 | 87 | ## 静态化 88 | 89 | 在一些场景中,无法做服务端的 html fallback,即让每个路由都输出 index.html 的内容,那么就要做静态化。 90 | 91 | 比如上面的例子,我们在 .umirc.js 里配置: 92 | 93 | ```js 94 | export default { 95 | exportStatic: {}, 96 | } 97 | ``` 98 | 99 | 然后执行 umi build,会为每个路由输出一个 html 文件。 100 | 101 | ``` 102 | ./dist 103 | ├── index.html 104 | ├── list 105 | │   └── index.html 106 | └── static 107 | ├── pages__index.5c0f5f51.async.js 108 | ├── pages__list.f940b099.async.js 109 | ├── umi.2eaebd79.js 110 | └── umi.f4cb51da.css 111 | ``` 112 | 113 | > 注意:静态化暂不支持有变量路由的场景。 114 | 115 | ## HTML 后缀 116 | 117 | 有些静态化的场景里,是不会自动读索引文件的,比如支付宝的容器环境,那么就不能生成这种 html 文件, 118 | 119 | ``` 120 | ├── index.html 121 | ├── list 122 | │   └── index.html 123 | ``` 124 | 125 | 而是生成, 126 | 127 | ``` 128 | ├── index.html 129 | └── list.html 130 | ``` 131 | 132 | 配置方式是在 .umirc.js 里, 133 | 134 | ```js 135 | export default { 136 | exportStatic: { 137 | htmlSuffix: true, 138 | }, 139 | } 140 | ``` 141 | 142 | umi build 会生成, 143 | 144 | ``` 145 | ./dist 146 | ├── index.html 147 | ├── list.html 148 | └── static 149 | ├── pages__index.5c0f5f51.async.js 150 | ├── pages__list.f940b099.async.js 151 | ├── umi.2924fdb7.js 152 | └── umi.cfe3ffab.css 153 | ``` 154 | 155 | ## 静态化后输出到任意路径 156 | 157 | ```js 158 | export default { 159 | exportStatic: { 160 | htmlSuffix: true, 161 | dynamicRoot: true, 162 | }, 163 | } 164 | ``` 165 | -------------------------------------------------------------------------------- /docs/zh/guide/mock-data.md: -------------------------------------------------------------------------------- 1 | # Mock 数据 2 | 3 | Mock 数据是前端开发过程中必不可少的一环,是分离前后端开发的关键链路。通过预先跟服务器端约定好的接口,模拟请求数据甚至逻辑,能够让前端开发独立自主,不会被服务端的开发所阻塞。 4 | 5 | ## 使用 umi 的 mock 功能 6 | 7 | umi 里约定 mock 文件夹下的文件即 mock 文件,文件导出接口定义,支持基于 `require` 动态分析的实时刷新,支持 ES6 语法,以及友好的出错提示,详情参看 [mock-data](https://umijs.org/zh/guide/mock-data.html)。 8 | 9 | ```js 10 | export default { 11 | // 支持值为 Object 和 Array 12 | 'GET /api/users': { users: [1, 2] }, 13 | 14 | // GET POST 可省略 15 | '/api/users/1': { id: 1 }, 16 | 17 | // 支持自定义函数,API 参考 express@4 18 | 'POST /api/users/create': (req, res) => { res.end('OK'); }, 19 | }; 20 | ``` 21 | 22 | 当客户端(浏览器)发送请求,如:`GET /api/users`,那么本地启动的 `umi dev` 会跟此配置文件匹配请求路径以及方法,如果匹配到了,就会将请求通过配置处理,就可以像样例一样,你可以直接返回数据,也可以通过函数处理以及重定向到另一个服务器。 23 | 24 | 比如定义如下映射规则: 25 | 26 | ``` 27 | 'GET /api/currentUser': { 28 | name: 'momo.zxy', 29 | avatar: imgMap.user, 30 | userid: '00000001', 31 | notifyCount: 12, 32 | }, 33 | ``` 34 | 35 | 访问的本地 `/api/users` 接口: 36 | 37 | 请求头 38 | 39 | 40 | 41 | 返回的数据 42 | 43 | 44 | 45 | ### 引入 Mock.js 46 | 47 | [Mock.js](http://mockjs.com/) 是常用的辅助生成模拟数据的第三方库,当然你可以用你喜欢的任意库来结合 roadhog 构建数据模拟功能。 48 | 49 | ```js 50 | import mockjs from 'mockjs'; 51 | 52 | export default { 53 | // 使用 mockjs 等三方库 54 | 'GET /api/tags': mockjs.mock({ 55 | 'list|100': [{ name: '@city', 'value|1-100': 50, 'type|0-2': 1 }], 56 | }), 57 | }; 58 | ``` 59 | 60 | ### 添加跨域请求头 61 | 62 | 设置 `response` 的请求头即可: 63 | 64 | ``` 65 | 'POST /api/users/create': (req, res) => { 66 | ... 67 | res.setHeader('Access-Control-Allow-Origin', '*'); 68 | ... 69 | }, 70 | ``` 71 | 72 | ## 合理的拆分你的 mock 文件 73 | 74 | 对于整个系统来说,请求接口是复杂并且繁多的,为了处理大量模拟请求的场景,我们通常把每一个数据模型抽象成一个文件,统一放在 `mock` 的文件夹中,然后他们会自动被引入。 75 | 76 | 77 | 78 | ## 如何模拟延迟 79 | 80 | 为了更加真实的模拟网络数据请求,往往需要模拟网络延迟时间。 81 | 82 | ### 手动添加 setTimeout 模拟延迟 83 | 84 | 你可以在重写请求的代理方法,在其中添加模拟延迟的处理,如: 85 | 86 | ```js 87 | 'POST /api/forms': (req, res) => { 88 | setTimeout(() => { 89 | res.send('Ok'); 90 | }, 1000); 91 | }, 92 | ``` 93 | 94 | ### 使用插件模拟延迟 95 | 96 | 上面的方法虽然简便,但是当你需要添加所有的请求延迟的时候,可能就麻烦了,不过可以通过第三方插件来简化这个问题,如:[roadhog-api-doc#delay](https://github.com/nikogu/roadhog-api-doc/blob/master/lib/utils.js#L5)。 97 | 98 | ```js 99 | import { delay } from 'roadhog-api-doc'; 100 | 101 | const proxy = { 102 | 'GET /api/project/notice': getNotice, 103 | 'GET /api/activities': getActivities, 104 | 'GET /api/rule': getRule, 105 | 'GET /api/tags': mockjs.mock({ 106 | 'list|100': [{ name: '@city', 'value|1-100': 50, 'type|0-2': 1 }] 107 | }), 108 | 'GET /api/fake_list': getFakeList, 109 | 'GET /api/fake_chart_data': getFakeChartData, 110 | 'GET /api/profile/basic': getProfileBasicData, 111 | 'GET /api/profile/advanced': getProfileAdvancedData, 112 | 'POST /api/register': (req, res) => { 113 | res.send({ status: 'ok' }); 114 | }, 115 | 'GET /api/notices': getNotices, 116 | }; 117 | 118 | // 调用 delay 函数,统一处理 119 | export default delay(proxy, 1000); 120 | ``` 121 | 122 | ## 联调 123 | 124 | 当本地开发完毕之后,如果服务器的接口满足之前的约定,那么你只需要不开本地代理或者重定向代理到目标服务器就可以访问真实的服务端数据,非常方便。 125 | 126 | -------------------------------------------------------------------------------- /packages/umi/src/generators/page.md: -------------------------------------------------------------------------------- 1 | ```js 2 | import assert from 'assert'; 3 | ``` 4 | 该模块用于编写应用程序的单元测试 5 | ```js 6 | import ejs from 'ejs'; 7 | ``` 8 | 嵌入式JavaScript模板 9 | ```js 10 | import uppercamelcase from 'uppercamelcase'; 11 | ``` 12 | 首字母大写转换 如 foo-bar => FooBar 13 | ```js 14 | import { join, basename } from 'path'; 15 | import { existsSync, statSync, readFileSync, writeFileSync } from 'fs'; 16 | ``` 17 | 属性 | 说明| 18 | -------- | ------| 19 | existsSync|测试某个路径下的文件是否存在 20 | statSync|获取文件信息 21 | readFileSync|读取文件 22 | writeFileSync|写文件 23 | 24 | ```js 25 | //目录存在 26 | function directoryExists(path) { 27 | return existsSync(path) && statSync(path).isDirectory(); 28 | } 29 | ``` 30 | ```js 31 | //文件存在 32 | function fileExists(path) { 33 | return existsSync(path) && statSync(path).isFile(); 34 | } 35 | ``` 36 | ```js 37 | //去除空行 38 | function stripEmptyLine(content) { 39 | const ret = content 40 | .trim() 41 | // 两行 -> 一行 42 | .replace(/\n\n/g, '\n'); 43 | 44 | // 结尾空行 45 | return `${ret}\n`; 46 | } 47 | ``` 48 | ```js 49 | //看一下代码时,可先忽略assert 50 | export default function(opts = {}) { 51 | const { file } = opts; 52 | //断言 53 | assert( 54 | !('isDirectory' in opts) || typeof opts.isDirectory === 'boolean', 55 | 'opts.isDirectory should be boolean', 56 | ); 57 | assert( 58 | !('useClass' in opts) || typeof opts.useClass === 'boolean', 59 | 'opts.useClass should be boolean', 60 | ); 61 | //目录 62 | const isDirectory = opts.isDirectory || false; 63 | //当前执行路径 64 | const cwd = opts.cwd || process.cwd(); 65 | 66 | console.log(`[DEBUG] generate page ${file} with isDirectory ${isDirectory}`); 67 | 68 | let cssTargetPath; 69 | let jsTargetPath; 70 | //是目录的时候,在file目录下新建page文件 71 | //不是目录的时候,新建file文件 72 | if (isDirectory) { 73 | assert( 74 | !directoryExists(join(cwd, 'src', 'page', file)), 75 | `directory src/page/${file} exists`, 76 | ); 77 | jsTargetPath = join(cwd, 'src', 'page', file, 'page.js'); 78 | cssTargetPath = join(cwd, 'src', 'page', file, 'page.css'); 79 | } else { 80 | jsTargetPath = join(cwd, 'src', 'page', `${file}.js`); 81 | cssTargetPath = join(cwd, 'src', 'page', `${file}.css`); 82 | } 83 | 84 | assert(!fileExists(jsTargetPath), `file src/page/${file} exists`); 85 | assert(!fileExists(cssTargetPath), `file src/page/${file} exists`); 86 | 87 | //从模板中读取文件 88 | const jsTpl = readFileSync( 89 | join(__dirname, '../../template/page.js'), 90 | 'utf-8', 91 | ); 92 | const cssTpl = readFileSync( 93 | join(__dirname, '../../template/page.css'), 94 | 'utf-8', 95 | ); 96 | 97 | 98 | const fileName = basename(file); 99 | const componentName = uppercamelcase(fileName); 100 | //使用ejs render文件 101 | //ejs.render(str, data, options); 102 | //options https://www.npmjs.com/package/ejs#options 103 | const jsContent = ejs.render( 104 | jsTpl, 105 | { 106 | useClass: opts.useClass, 107 | fileName, 108 | componentName, 109 | }, 110 | { 111 | _with: false, 112 | localsName: 'umi', 113 | }, 114 | ); 115 | 116 | const cssContent = ejs.render( 117 | cssTpl, 118 | {}, 119 | { 120 | _with: false, 121 | localsName: 'umi', 122 | }, 123 | ); 124 | 125 | //写入文件 126 | writeFileSync(jsTargetPath, stripEmptyLine(jsContent), 'utf-8'); 127 | writeFileSync(cssTargetPath, stripEmptyLine(cssContent), 'utf-8'); 128 | } 129 | ``` -------------------------------------------------------------------------------- /docs/zh/api/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebarDepth: 2 3 | --- 4 | 5 | # API 6 | 7 | ## 路由 8 | 9 | ### umi/link 10 | 11 | 通过声明的方式做路由跳转。 12 | 13 | 例子: 14 | 15 | ```markup 16 | import Link from 'umi/link'; 17 | 18 | export default () => { 19 |
    20 | /* 普通使用 */ 21 | Go to list page 22 | 23 | /* 带参数 */ 24 | Go to list page 25 | 26 | /* 包含子组件 */ 27 | 28 |
    29 | } 30 | ``` 31 | 32 | ### umi/router 33 | 34 | 通过编程的方式做路由切换,包含以下 4 个 API 。 35 | 36 | #### router.push(path) 37 | 38 | 推一个新的页面到 history 里。 39 | 40 | 例子: 41 | 42 | ```js 43 | import router from 'umi/router'; 44 | 45 | // 普通跳转,不带参数 46 | router.push('/list'); 47 | 48 | // 带参数 49 | router.push('/list?a=b'); 50 | router.push({ 51 | pathname: '/list', 52 | query: { 53 | a: 'b', 54 | }, 55 | }); 56 | # 对象且不包含 pathname 会报错 57 | router.push({ 58 | query: {} 59 | }); 60 | ``` 61 | 62 | #### router.replace(path) 63 | 64 | 替换当前页面,参数和 [router.push()](#router.push\(path\)) 相同。 65 | 66 | #### router.go(n) 67 | 68 | 往前或往后跳指定页数。 69 | 70 | 例子: 71 | 72 | ```js 73 | import router from 'umi/router'; 74 | 75 | router.go(-1); 76 | router.go(2); 77 | ``` 78 | 79 | #### router.goBack() 80 | 81 | 后退一页。 82 | 83 | 例子: 84 | 85 | ```js 86 | import router from 'umi/router'; 87 | router.goBack(); 88 | ``` 89 | 90 | ### umi/navlink 91 | 92 | 详见:[https://reacttraining.com/react-router/web/api/NavLink](https://reacttraining.com/react-router/web/api/NavLink) 93 | 94 | ### umi/redirect 95 | 96 | 重定向用。 97 | 98 | 例子: 99 | 100 | ```js 101 | import Redirect from 'umi/redirect'; 102 | 103 | ``` 104 | 105 | 详见:[https://reacttraining.com/react-router/web/api/Redirect](https://reacttraining.com/react-router/web/api/Redirect) 106 | 107 | ### umi/prompt 108 | 109 | 例子: 110 | 111 | ```js 112 | import Prompt from 'umi/prompt'; 113 | 114 | export default () => { 115 | return ( 116 | <> 117 |

    Prompt

    118 | { 121 | return window.confirm(`confirm to leave to ${location.pathname}?`); 122 | }} 123 | /> 124 | 125 | ); 126 | } 127 | ``` 128 | 129 | 详见:[https://reacttraining.com/react-router/web/api/Prompt](https://reacttraining.com/react-router/web/api/Prompt) 130 | 131 | ### umi/withRouter 132 | 133 | 详见:[https://reacttraining.com/react-router/web/api/withRouter](https://reacttraining.com/react-router/web/api/withRouter) 134 | 135 | ## 性能 136 | 137 | ### umi/dynamic 138 | 139 | 动态加载组件,基于 [react-loadable](https://github.com/jamiebuilds/react-loadable) 实现。 140 | 141 | #### dynamic(options) 142 | 143 | 例子: 144 | 145 | ```js 146 | import dynamic from 'umi/dynamic'; 147 | 148 | // 延时 1s 渲染的组件。 149 | const App = dynamic({ 150 | loader: () => { 151 | return new Promise((resolve) => { 152 | setTimeout(() => { 153 | resolve(() =>
    I will render after 1s
    ); 154 | }, /* 1s */1000); 155 | })); 156 | }, 157 | }); 158 | 159 | // 或者用 async 语法 160 | const delay = (timeout) => new Promise(resolve => setTimeout(resolve, timeout)); 161 | const App = dynamic({ 162 | loader: async function() { 163 | await delay(/* 1s */1000); 164 | return () =>
    I will render after 1s
    ; 165 | }, 166 | }); 167 | ``` 168 | 169 | ## 构建 170 | 171 | ### umi/babel 172 | 173 | 让用户可基于 umi 的 babel 配置进行扩展。 174 | -------------------------------------------------------------------------------- /docs/zh/guide/app-structure.md: -------------------------------------------------------------------------------- 1 | # 目录及约定 2 | 3 | 在文件和目录的组织上,umi 尽量选择了约定的方式。 4 | 5 | 一个复杂应用的目录结构如下: 6 | 7 | ``` 8 | . 9 | ├── dist/ // 默认的 build 输出目录 10 | ├── mock/ // mock 文件所在目录,基于 express 11 | ├── config/ 12 | ├── config.js // umi 配置,同 .umirc.js,二选一 13 | └── src/ // 源码目录,可选 14 | ├── layouts/index.js // 全局布局 15 | ├── pages/ // 页面目录,里面的文件即路由 16 | ├── .umi/ // dev 临时目录,需添加到 .gitignore 17 | ├── .umi-production/ // build 临时目录,会自动删除 18 | ├── document.ejs // HTML 模板 19 | ├── 404.js // 404 页面 20 | ├── page1.js // 页面 1,任意命名,导出 react 组件 21 | ├── page1.test.js // 用例文件,umi test 会匹配所有 .test.js 和 .e2e.js 结尾的文件 22 | └── page2.js // 页面 2,任意命名 23 | ├── global.css // 约定的全局样式文件,自动引入,也可以用 global.less 24 | ├── global.js // 可以在这里加入 polyfill 25 | ├── .umirc.js // umi 配置,同 config/config.js,二选一 26 | ├── .env // 环境变量 27 | └── package.json 28 | ``` 29 | 30 | ## ES6 语法 31 | 32 | 配置文件、mock 文件等都有通过 `@babel/register` 注册实时编译,所以可以和 src 里的文件一样,使用 ES6 的语法和 es modules 。 33 | 34 | ## dist 35 | 36 | 默认输出路径,可通过配置 outputPath 修改。 37 | 38 | ## mock 39 | 40 | 约定 mock 目录里所有的 `.js` 文件会被解析为 mock 文件。 41 | 42 | 比如,新建 `mock/users.js`,内容如下: 43 | 44 | ```js 45 | export default { 46 | '/api/users': ['a', 'b'], 47 | } 48 | ``` 49 | 50 | 然后在浏览器里访问 [http://localhost:8000/api/users](http://localhost:8000/api/users) 就可以看到 `['a', 'b']` 了。 51 | 52 | ## src 53 | 54 | 约定 `src` 为源码目录,但是可选,简单项目可以不加 `src` 这层目录。 55 | 56 | 比如:下面两种目录结构的效果是一致的。 57 | 58 | ``` 59 | + src 60 | + pages 61 | - index.js 62 | + layouts 63 | - index.js 64 | - .umirc.js 65 | ``` 66 | 67 | ``` 68 | + pages 69 | - index.js 70 | + layouts 71 | - index.js 72 | - .umirc.js 73 | ``` 74 | 75 | ## src/layouts/index.js 76 | 77 | 全局布局,实际上是在路由外面套了一层。 78 | 79 | 比如,你的路由是: 80 | 81 | ``` 82 | [ 83 | { path: '/', component: './pages/index' }, 84 | { path: '/users', component: './pages/users' }, 85 | ] 86 | ``` 87 | 88 | 如果有 `layouts/index.js`,那么路由则变为: 89 | 90 | ``` 91 | [ 92 | { path: '/', component: './layouts/index', routes: [ 93 | { path: '/', component: './pages/index' }, 94 | { path: '/users', component: './pages/users' }, 95 | ] } 96 | ] 97 | ``` 98 | 99 | ## src/pages 100 | 101 | 约定 pages 下所有的 `(j|t)sx?` 文件即路由。关于更多关于约定式路由的介绍,请前往路由章节。 102 | 103 | ## src/pages/404.js 104 | 105 | 404 页面。注意开发模式下有内置 umi 提供的 404 提示页面,所以只有显式访问 `/404` 才能访问到这个页面。 106 | 107 | ## src/pages/document.ejs 108 | 109 | 有这个文件时,会覆盖默认的 HTML 模板。需至少包含以下代码, 110 | 111 | ```html 112 |
    113 | ``` 114 | 115 | ## src/pages/.umi 116 | 117 | 这是 umi dev 时生产的临时目录,默认包含 `umi.js` 和 `router.js`,有些插件也会在这里生成一些其他临时文件。可以在这里做一些验证,**但请不要直接在这里修改代码,umi 重启或者 pages 下的文件修改都会重新生成这个文件夹下的文件。** 118 | 119 | ## src/pages/.umi-production 120 | 121 | 同 `src/pagers/.umi`,但是是在 `umi build` 时生成的,会在 `umi build` 执行完自动删除。 122 | 123 | ## .test.js 和 .e2e.js 124 | 125 | 测试文件,`umi test` 会查找所有的 .(test|e2e).(j|t)s 文件跑测试。 126 | 127 | ## src/global.(j|t)sx? 128 | 129 | 在入口文件最前面被自动引入,可以考虑在此加入 polyfill。 130 | 131 | ## src/global.(css|less|sass|scss) 132 | 133 | 这个文件不走 css modules,自动被引入,可以写一些全局样式,或者做一些样式覆盖。 134 | 135 | ## .umirc.js 和 config/config.js 136 | 137 | umi 的配置文件,二选一。 138 | 139 | ## .env 140 | 141 | 环境变量,比如: 142 | 143 | ``` 144 | CLEAR_CONSOLE=none 145 | BROWSER=none 146 | ``` 147 | -------------------------------------------------------------------------------- /docs/guide/env-variables.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebarDepth: 3 3 | --- 4 | 5 | # .env and Environment Variables 6 | 7 | ## How to Configure 8 | 9 | For example 10 | 11 | ``` 12 | # OS X, Linux 13 | $ PORT=3000 umi dev 14 | 15 | # Windows (cmd.exe) 16 | $ set PORT=3000&&umi dev 17 | 18 | # Or use cross-env for all platforms 19 | $ yarn add cross-env --dev 20 | $ cross-env PORT=3000 umi dev 21 | 22 | # .env 23 | $ echo PORT=3000 > .env 24 | ``` 25 | 26 | ## Environment Variables 27 | 28 | ### UMI_ENV 29 | 30 | Specifies a profile that overrides the default configuration. For example, `UMI_ENV=prod umi build`, then `.umirc.js` will be overwritten with `.umirc.prod.js`. Or `config/config.prod.js` overrides `config/config.js`. Note that overriding instead of replacing, configurators not in `.umirc.prod.js` will use the configuration in `.umirc.js`. 31 | 32 | In addition, the configuration in `.umirc.local.js` or `config/config.local.js` in development mode is always the highest priority. 33 | 34 | ### PORT 35 | 36 | Specify the port number. The default is `8000`. such as: 37 | 38 | ```bash 39 | $ PORT=8001 umi dev 40 | ``` 41 | 42 | ### HOST 43 | 44 | The default is `0.0.0.0`. 45 | 46 | ### APP_ROOT 47 | 48 | ::: warning 49 | APP_ROOT cannot be included in .env. 50 | ::: 51 | 52 | Specify the project root directory. such as: 53 | 54 | ```bash 55 | $ APP_ROOT=src/renderer umi dev 56 | ``` 57 | 58 | ### ANALYZE 59 | 60 | It is off by default. Analyze the bundle composition, valid when building. such as: 61 | 62 | ```bash 63 | $ ANALYZE=1 umi build 64 | ``` 65 | 66 | ### ANALYZE_PORT 67 | 68 | ANALYZE server port, default 8888. 69 | 70 | ### BABEL_POLYFILL 71 | 72 | 默认引入 `@babel/polyfill`,值为 none 时不引入。比如: 73 | 74 | `@babel/polyfill` is included by default, set the value to `none` if you don't want it. 75 | 76 | e.g. 77 | 78 | ```bash 79 | $ BABEL_POLYFILL=none umi build 80 | ``` 81 | 82 | ### COMPRESS 83 | 84 | The default compression CSS and JS, the value is none when it is none, and it is valid when building. such as: 85 | 86 | ```bash 87 | $ COMPRESS=none umi build 88 | ``` 89 | 90 | ### CSS_COMPRESS 91 | 92 | The default compression, the value is none without compression, and is valid at build time. Because css compression is sometimes problematic, and compression does not reduce the size, sometimes you can suppress JS without pressing CSS. 93 | 94 | ### BROWSER 95 | 96 | The browser is automatically opened by default. If the value is none, it will not be automatically opened. It is valid when dev. such as: 97 | 98 | ```bash 99 | $ BROWSER=none umi dev 100 | ``` 101 | 102 | ### CLEAR_CONSOLE 103 | 104 | The default is cleared. If the value is none, the screen is not cleared. 105 | 106 | ### HMR 107 | 108 | The HMR is enabled by default, the value is disabled when none, and the value is refreshed when the file changes when reload. 109 | 110 | ### BABELRC 111 | 112 | Turn on `.babelrc` parsing, which is not resolved by default. 113 | 114 | ### BABEL_CACHE 115 | 116 | The babel cache is enabled by default, and is disabled when the value is none. such as: 117 | 118 | ```bash 119 | $ BABEL_CACHE=none umi dev 120 | ``` 121 | 122 | ### MOCK 123 | 124 | The mock is enabled by default, and is disabled when the value is none. such as: 125 | 126 | ```bash 127 | $ MOCK=none umi dev 128 | ``` 129 | 130 | ### HTML 131 | 132 | The HTML file is packaged by default, and the HTML file is not packaged when the value is none. such as: 133 | 134 | ```bash 135 | $ HTML=none umi build 136 | ``` 137 | 138 | ### WATCH_FILES 139 | 140 | ### RM_TMPDIR 141 | ### FORK_TS_CHECKER 142 | 默认不开启TypeScript检查,值为1时启用。比如: 143 | ```bash 144 | $ FORK_TS_CHECKER=1 umi dev 145 | ``` 146 | -------------------------------------------------------------------------------- /docs/zh/guide/getting-started.md: -------------------------------------------------------------------------------- 1 | # 快速上手 2 | 3 | > 更喜欢观看视频?可以[点此观看](https://www.youtube.com/watch?v=vkAUGUlYm24&list=PLzu0PBqV2jld2q5gCADxX17NE3gF3FvYq) 4 | 5 | ## 环境准备 6 | 7 | 首先得有 [node](https://nodejs.org/en/),并确保 node 版本是 8.10 或以上。(mac 下推荐使用 [nvm](https://github.com/creationix/nvm) 来管理 node 版本) 8 | 9 | ```bash 10 | $ node -v 11 | 8.1x 12 | ``` 13 | 14 | 推荐使用 yarn 管理 npm 依赖,并[使用国内源](https://github.com/yiminghe/tyarn)(阿里用户使用内网源)。 15 | 16 | ```bash 17 | # 国内源 18 | $ npm i yarn tyarn -g 19 | # 后面文档里的 yarn 换成 tyarn 20 | $ tyarn -v 21 | 22 | # 阿里内网源 23 | $ tnpm i yarn @alipay/yarn -g 24 | # 后面文档里的 yarn 换成 ayarn 25 | $ ayarn -v 26 | ``` 27 | 28 | 然后全局安装 umi,并确保版本是 2.0.0 或以上。 29 | 30 | ```bash 31 | $ yarn global add umi 32 | $ umi -v 33 | 2.0.0 34 | ``` 35 | 36 | ## 脚手架 37 | 38 | 先找个地方建个空目录。 39 | 40 | ```bash 41 | $ mkdir myapp && cd myapp 42 | ``` 43 | 44 | 然后通过 `umi g` 创建一些页面, 45 | 46 | ```bash 47 | $ umi g page index 48 | $ umi g page users 49 | ``` 50 | 51 | > `umi g` 是 `umi generate` 的别名,可用于快速生成 component、page、layout 等,并且可在插件里被扩展,比如 umi-plugin-dva 里扩展了 dva:model,然后就可以通过 `umi g dva:model foo` 快速 dva 的 model。 52 | 53 | 然后通过 tree 查看下目录,(windows 用户可跳过此步) 54 | 55 | ```bash 56 | $ tree 57 | . 58 | └── pages 59 | ├── index.css 60 | ├── index.js 61 | ├── users.css 62 | └── users.js 63 | ``` 64 | 65 | 这里的 pages 目录是页面所在的目录,umi 里约定默认情况下 pages 下所有的 js 文件即路由,如果有 [next.js](https://github.com/zeit/next.js) 或 [nuxt.js](https://nuxtjs.org/) 的使用经验,应该会有点眼熟吧。 66 | 67 | 然后启动本地服务器, 68 | 69 | ```bash 70 | $ umi dev 71 | ``` 72 | 73 | 74 | 75 | ## 约定式路由 76 | 77 | 启动 `umi dev` 后,大家会发现 pages 下多了个 `.umi` 的目录。这是啥?这是 umi 的临时目录,可以在这里做一些验证,但请不要直接在这里修改代码,umi 重启或者 pages 下的文件修改都会重新生成这个文件夹下的文件。 78 | 79 | 然后我们在 index 和 users 直接加一些路由跳转逻辑。 80 | 81 | 先修改 `pages/index.js`, 82 | 83 | ```diff 84 | + import Link from 'umi/link'; 85 | import styles from './index.css'; 86 | 87 | export default function() { 88 | return ( 89 |
    90 |

    Page index

    91 | + go to /users 92 |
    93 | ); 94 | } 95 | ``` 96 | 97 | 再修改 `pages/users.js`, 98 | 99 | ```diff 100 | + import router from 'umi/router'; 101 | import styles from './index.css'; 102 | 103 | export default function() { 104 | return ( 105 |
    106 |

    Page index

    107 | + 108 |
    109 | ); 110 | } 111 | ``` 112 | 113 | 然后浏览器验证,应该已经可以在 index 和 users 两个页面之间通过路由跳转了。 114 | 115 | ## 部署发布 116 | 117 | ### 构建 118 | 119 | 执行 `umi build`, 120 | 121 | ```bash 122 | $ umi build 123 | 124 | DONE Compiled successfully in 1729ms 125 | 126 | File sizes after gzip: 127 | 128 | 68.04 KB dist/umi.js 129 | 83 B dist/umi.css 130 | ``` 131 | 132 | 构建产物默认生成到 `./dist` 下,然后通过 tree 命令查看,(windows 用户可忽略此步) 133 | 134 | ```bash 135 | $ tree ./dist 136 | ./dist 137 | ├── index.html 138 | ├── umi.css 139 | └── umi.js 140 | ``` 141 | 142 | ### 本地验证 143 | 144 | 发布之前,可以通过 `serve` 做本地验证, 145 | 146 | ```bash 147 | $ yarn global add serve 148 | $ serve ./dist 149 | 150 | Serving! 151 | 152 | - Local: http://localhost:5000 153 | - On Your Network: http://{Your IP}:5000 154 | 155 | Copied local address to clipboard! 156 | ``` 157 | 158 | 访问 http://localhost:5000,正常情况下应该是和 `umi dev` 一致的。 159 | 160 | ### 部署 161 | 162 | 本地验证完,就可以部署了,这里通过 [now](http://now.sh/) 来做演示。 163 | 164 | ```bash 165 | $ yarn global add now 166 | $ now ./dist 167 | 168 | > Deploying /private/tmp/sorrycc-1KVCmK/dist under chencheng 169 | > Synced 3 files (301.93KB) [2s] 170 | > https://dist-jtckzjjatx.now.sh [in clipboard] [1s] 171 | > Deployment complete! 172 | ``` 173 | 174 | 然后打开相应的地址就能访问到线上的地址了。 175 | -------------------------------------------------------------------------------- /docs/api/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebarDepth: 2 3 | --- 4 | 5 | # API 6 | 7 | ## Route 8 | 9 | ### umi/link 10 | 11 | Navigation via route declaration. 12 | 13 | Example: 14 | 15 | ```markup 16 | import Link from 'umi/link'; 17 | 18 | export default () => { 19 |
    20 | /* Normal use */ 21 | Go to list page 22 | 23 | /* With query string */ 24 | Go to list page 25 | 26 | /* Include child component */ 27 | 28 |
    29 | } 30 | ``` 31 | 32 | ### umi/router 33 | 34 | Programmatic navigation via four router methods 35 | 36 | #### router.push(path) 37 | 38 | Add one entry to the browser's history. 39 | 40 | Example: 41 | 42 | ```js 43 | import router from 'umi/router'; 44 | 45 | // Normal navigation without query string 46 | router.push('/list'); 47 | 48 | // With query string 49 | router.push('/list?a=b'); 50 | router.push({ 51 | pathname: '/list', 52 | query: { 53 | a: 'b', 54 | }, 55 | }); 56 | # Object without property `pathname` will throw an error 57 | router.push({ 58 | query: {} 59 | }); 60 | ``` 61 | 62 | #### router.replace(path) 63 | 64 | Replace current page. Accept same parameter as [router.push()](#router.push\(path\)) 65 | 66 | #### router.go(n) 67 | 68 | Move back or forward through history. 69 | 70 | Example: 71 | 72 | ```js 73 | import router from 'umi/router'; 74 | 75 | router.go(-1); 76 | router.go(2); 77 | ``` 78 | 79 | #### router.goBack() 80 | 81 | Move backward. 82 | 83 | Example: 84 | 85 | ```js 86 | import router from 'umi/router'; 87 | router.goBack(); 88 | ``` 89 | 90 | ### umi/navlink 91 | 92 | See: [https://reacttraining.com/react-router/web/api/NavLink](https://reacttraining.com/react-router/web/api/NavLink) 93 | 94 | ### umi/redirect 95 | 96 | Redirection. 97 | 98 | Example: 99 | 100 | ```js 101 | import Redirect from 'umi/redirect'; 102 | 103 | ``` 104 | 105 | See: [https://reacttraining.com/react-router/web/api/Redirect](https://reacttraining.com/react-router/web/api/Redirect) 106 | 107 | ### umi/prompt 108 | 109 | Example. 110 | 111 | ```js 112 | import Prompt from 'umi/prompt'; 113 | 114 | export default () => { 115 | return ( 116 | <> 117 |

    Prompt

    118 | { 121 | return window.confirm(`confirm to leave to ${location.pathname}?`); 122 | }} 123 | /> 124 | 125 | ); 126 | } 127 | ``` 128 | 129 | See:[https://reacttraining.com/react-router/web/api/Prompt](https://reacttraining.com/react-router/web/api/Prompt) 130 | 131 | ### umi/withRouter 132 | 133 | See: [https://reacttraining.com/react-router/web/api/withRouter](https://reacttraining.com/react-router/web/api/withRouter) 134 | 135 | ## Performance 136 | 137 | ### umi/dynamic 138 | 139 | Dynamically loading components based on [react-loadable](https://github.com/jamiebuilds/react-loadable). 140 | 141 | #### dynamic(options) 142 | 143 | Example: 144 | 145 | ```js 146 | import dynamic from 'umi/dynamic'; 147 | 148 | // Render component with 1s delay 149 | const App = dynamic({ 150 | loader: () => { 151 | return new Promise((resolve) => { 152 | setTimeout(() => { 153 | resolve(() =>
    I will render after 1s
    ); 154 | }, /* 1s */1000); 155 | })); 156 | }, 157 | }); 158 | 159 | // Or use `async function` 160 | const delay = (timeout) => new Promise(resolve => setTimeout(resolve, timeout)); 161 | const App = dynamic({ 162 | loader: async function() { 163 | await delay(/* 1s */1000); 164 | return () =>
    I will render after 1s
    ; 165 | }, 166 | }); 167 | ``` 168 | 169 | ## Build 170 | 171 | ### umi/babel 172 | 173 | Make umi's babel configuration extensible. 174 | -------------------------------------------------------------------------------- /docs/zh/guide/with-dva.md: -------------------------------------------------------------------------------- 1 | # Use umi with dva 2 | 3 | ::: warning 4 | This article has not been translated yet. Wan't to help us out? Click the `Edit this page on GitHub` at the end of the page. 5 | ::: 6 | 7 | 自`>= umi@2`起,`dva`的整合可以直接通过 [umi-plugin-react](https://github.com/umijs/umi/tree/master/packages/umi-plugin-react) 来配置。 8 | 9 | ## 特性 10 | 11 | * **按目录约定注册 model**,无需手动 `app.model` 12 | * **文件名即 namespace**,可以省去 model 导出的 `namespace` key 13 | * **无需手写 router.js**,交给 umi 处理,支持 model 和 component 的按需加载 14 | * **内置 query-string 处理**,无需再手动解码和编码 15 | * **内置 dva-loading 和 dva-immer**,其中 dva-immer 需通过配置开启 16 | * **开箱即用**,无需安装额外依赖,比如 dva、dva-loading、dva-immer、path-to-regexp、object-assign、react、react-dom 等 17 | 18 | ## 使用 19 | 20 | 用 yarn 安装依赖, 21 | 22 | ```bash 23 | $ yarn add umi-plugin-react 24 | ``` 25 | 26 | 如果你用 npm,执行 `npm install --save umi-plugin-react`。 27 | 28 | 然后在 `.umirc.js` 里配置插件: 29 | 30 | ```js 31 | export default { 32 | plugins: [ 33 | [ 34 | 'umi-plugin-react', 35 | { 36 | dva: true, 37 | }, 38 | ] 39 | ], 40 | }; 41 | ``` 42 | 43 | 推荐开启 dva-immer 以简化 reducer 编写, 44 | 45 | ```js 46 | export default { 47 | plugins: [ 48 | [ 49 | 'umi-plugin-react', 50 | { 51 | dva: { 52 | immer: true 53 | } 54 | } 55 | ], 56 | ], 57 | }; 58 | ``` 59 | 60 | ## model 注册 61 | 62 | model 分两类,一是全局 model,二是页面 model。全局 model 存于 `/src/models/` 目录,所有页面都可引用;**页面 model 不能被其他页面所引用**。 63 | 64 | 规则如下: 65 | 66 | * `src/models/**/*.js` 为 global model 67 | * `src/pages/**/models/**/*.js` 为 page model 68 | * global model 全量载入,page model 在 production 时按需载入,在 development 时全量载入 69 | * page model 为 page js 所在路径下 `models/**/*.js` 的文件 70 | * page model 会向上查找,比如 page js 为 `pages/a/b.js`,他的 page model 为 `pages/a/b/models/**/*.js` + `pages/a/models/**/*.js`,依次类推 71 | * 约定 model.js 为单文件 model,解决只有一个 model 时不需要建 models 目录的问题,有 model.js 则不去找 `models/**/*.js` 72 | 73 | 举个例子, 74 | 75 | ``` 76 | + src 77 | + models 78 | - g.js 79 | + pages 80 | + a 81 | + models 82 | - a.js 83 | - b.js 84 | + ss 85 | - s.js 86 | - page.js 87 | + c 88 | - model.js 89 | + d 90 | + models 91 | - d.js 92 | - page.js 93 | - page.js 94 | ``` 95 | 96 | 如上目录: 97 | 98 | * global model 为 `src/models/g.js` 99 | * `/a` 的 page model 为 `src/pages/a/models/{a,b,ss/s}.js` 100 | * `/c` 的 page model 为 `src/pages/c/model.js` 101 | * `/c/d` 的 page model 为 `src/pages/c/model.js, src/pages/c/d/models/d.js` 102 | 103 | ## 配置及插件 104 | 105 | > 之前在 `src/dva.js` 下进行配置的方式已 deprecated,下个大版本会移除支持。 106 | 107 | 在 `src` 目录下新建 `app.js`,内容如下: 108 | 109 | ```js 110 | export const dva = { 111 | config: { 112 | onError(e) { 113 | e.preventDefault(); 114 | console.error(e.message); 115 | }, 116 | }, 117 | plugins: [ 118 | require('dva-logger')(), 119 | ], 120 | }; 121 | ``` 122 | 123 | ## FAQ 124 | 125 | ### url 变化了,但页面组件不刷新,是什么原因? 126 | 127 | `layouts/index.js` 里如果用了 connect 传数据,需要用 `umi/withRouter` 高阶一下。 128 | 129 | ```js 130 | import withRouter from 'umi/withRouter'; 131 | 132 | export default withRouter(connect(mapStateToProps)(LayoutComponent)); 133 | ``` 134 | 135 | ### 如何访问到 store 或 dispatch 方法? 136 | 137 | ```js 138 | window.g_app._store 139 | window.g_app._store.dispatch 140 | ``` 141 | 142 | ### 如何禁用包括 component 和 models 的按需加载? 143 | 144 | 在 .umirc.js 里配置: 145 | 146 | ```js 147 | export default { 148 | plugins: [ 149 | [ 150 | 'umi-plugin-react', 151 | { 152 | dva: { 153 | dynamicImport: undefined // 配置在dva里 154 | }, 155 | dynamicImport: undefined // 或者直接写在react插件的根配置,写在这里也会被继承到上面的dva配置里 156 | } 157 | ], 158 | ], 159 | }; 160 | ``` 161 | 162 | ### 全局 layout 使用 connect 后路由切换后没有刷新? 163 | 164 | 需用 withRouter 包一下导出的 react 组件,注意顺序。 165 | 166 | ```js 167 | import withRouter from 'umi/withRouter'; 168 | export default withRouter(connect()(Layout)); 169 | ``` 170 | 171 | ## 参考 172 | 173 | * [使用 umi 改进 dva 项目开发](https://github.com/sorrycc/blog/issues/66) 174 | * [umi + dva,完成用户管理的 CURD 应用](https://github.com/sorrycc/blog/issues/62) 175 | -------------------------------------------------------------------------------- /docs/guide/migration.md: -------------------------------------------------------------------------------- 1 | # Migrate from umi 1.x 2 | 3 | > More like watching videos? You can [click here to watch](https://youtu.be/1mvKzFLLBck). 4 | 5 | Let's take an example of [antd-admin](https://github.com/zuiidea/antd-admin/pull/877) to update from umi@1 to umi@2. 6 | 7 | ## npm Dependency 8 | 9 | Upgrade umi to `^2.0.0-0` and use umi-plugin-react instead of the previous plugins, including umi-plugin-dva, umi-plugin-dll, umi-plugin-routes, umi-plugin-polyfill and Umi-plugin-locale. 10 | 11 | ```diff 12 | - "umi": "^1.3.17", 13 | + "umi": "^2.0.0-beta.16", 14 | 15 | - "umi-plugin-dll": "^0.2.1", 16 | - "umi-plugin-dva": "^0.9.1", 17 | - "umi-plugin-routes": "^0.1.5" 18 | + "umi-plugin-react": "^1.0.0-beta.16", 19 | ``` 20 | 21 | Umi-plugin-react is a collection of more than a dozen plugins, as described in [Introduction to umi-plugin-react](/plugin/umi-plugin-react.html). 22 | 23 | ## Environment Variables 24 | 25 | Umi@2 supports configuring environment variables in `.env`, so the environment variables previously written in package.json scripts can be cut here. 26 | 27 | ```diff 28 | - "start": "cross-env COMPILE_ON_DEMAND=none BROWSER=none HOST=0.0.0.0 umi dev", 29 | + "start": "cross-env BROWSER=none HOST=0.0.0.0 umi dev", 30 | ``` 31 | 32 | Then create a new `.env`, (where `COMPILE_ON_DEMAND` is no longer supported) 33 | 34 | ``` 35 | BROWSER=none 36 | HOST=0.0.0.0 37 | ``` 38 | 39 | In addition, some environment variables have changed or are no longer supported: 40 | 41 | * `PUBLIC_PATH` is no longer supported, configured by `publicPath` 42 | * `BASE_URL` is no longer supported, configured by `base` 43 | * `COMPILE_ON_DEMAND` is no longer supported, and this function is not available in umi@2. 44 | * `TSLINT` is no longer supported, and this function is not available in umi@2. 45 | * `ESLINT` is no longer supported, and this function is not available in umi@2. 46 | 47 | ## Configuration 48 | 49 | ### Plugin Configuration 50 | 51 | Since we changed a lot of plugins to umi-plugin-react, we need to modify `.umirc.js`. 52 | 53 | ```diff 54 | export default { 55 | plugins: [ 56 | - 'umi-plugin-dva', 57 | + ['umi-plugin-react', { 58 | + dva: true, 59 | + antd: true, // antd is not enabled by default, if you need to use it yourself 60 | + }], 61 | ], 62 | }; 63 | ``` 64 | 65 | For more dll, hardSource, polyfilles, locale, title, etc., refer to [umi-plugin-react documentation](/plugin/umi-plugin-react.html). 66 | 67 | ### webpackrc.js 68 | 69 | Umi@2 no longer supports `webpackrc.js`, copy the configuration inside it to `.umirc.js`. 70 | 71 | ### webpack.config.js 72 | 73 | Umi@2 no longer supports `webpack.config.js`, instead it is implemented by configuring [chainWebpack](/config/#chainwebpack). 74 | 75 | ### Detailed Configuration Item Changes 76 | 77 | * `hd` is no longer supported. To enable it, load the plugin `umi-plugin-react` and configure `hd: {}` 78 | * `disableServiceWorker` is no longer supported, it is not enabled by default. To enable it, load the plugin `umi-plugin-react` and configure `pwa: {}` 79 | * `preact` is no longer supported. To configure, load the plugin `umi-plugin-react` and configure `library: 'preact'. 80 | * `loading` is no longer supported. To configure, load the plugin `umi-plugin-react` and configure `dynamicImport.loadingComponent` 81 | * `hashHistory: true` changed to `history: 'hash'` 82 | * `disableDynamicImport` is no longer supported, it is not enabled by default. To enable it, load the plugin `umi-plugin-react` and configure `dynamicImport: {}` 83 | * `disableFastClick` is no longer supported, it is not enabled by default. To enable it, load the plugin `umi-plugin-react` and configure `fastClick: {}` 84 | * No longer supports `pages`, instead of directly on the route 85 | * `disableHash` is no longer supported, it is not enabled by default. To enable it, configure `hash: true` 86 | 87 | ## Conventional Routing 88 | 89 | The routing layer no longer supports directory-level routing for `page.js`. Previously useful, you need to exclude unwanted routes through umi-plugin-react's routes.exclude. 90 | 91 | ## umi/dynamic 92 | 93 | Interface changes, umi@2 is based on [react-loadable](https://github.com/jamiebuilds/react-loadable). 94 | 95 | ```diff 96 | - dynamic(async () => {}) 97 | + dynamic({ loader: async () => {}}) 98 | ``` 99 | 100 | See [umi/dynamic Interface Description](/api/#umi-dynamic) for details. 101 | -------------------------------------------------------------------------------- /docs/guide/getting-started.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | > There's also a [video version](https://www.youtube.com/watch?v=vkAUGUlYm24&list=PLzu0PBqV2jld2q5gCADxX17NE3gF3FvYq) of this. 4 | 5 | ## Environmental preparation 6 | 7 | First you should have [node](https://nodejs.org/en/), and make sure it's version 8.10 or above. 8 | 9 | ```bash 10 | $ node -v 11 | 8.1x 12 | ``` 13 | 14 | Recommended to use `yarn` to management npm dependency. 15 | 16 | Then install `umi` globally, and make sure it's 2.0.0 or above. 17 | 18 | ```bash 19 | $ yarn global add umi 20 | $ umi -v 21 | 2.0.0 22 | ``` 23 | 24 | ## Boilerplate 25 | 26 | First create an empty directory. 27 | 28 | ```bash 29 | $ mkdir myapp && cd myapp 30 | ``` 31 | 32 | Then create some pages with `umi g`, 33 | 34 | ```bash 35 | $ umi g page index 36 | $ umi g page users 37 | ``` 38 | 39 | > `umi g` is the alias of `umi generate`, used for generate `component`, `page`, `layout` quickly. And it can be extended in plugins, such as uni-plugin-dva extended `dva:model`, then you can generate dva's model via `umi g dva:model foo`. 40 | 41 | Then view the directory with `tree`, (windows users can skip this step) 42 | 43 | ```bash 44 | $ tree 45 | . 46 | └── pages 47 | ├── index.css 48 | ├── index.js 49 | ├── users.css 50 | └── users.js 51 | ``` 52 | 53 | The pages directory here is the directory where the page is located. In umi, all the js files under the pages are routes. It's like [next.js](https://github.com/zeit/next.js) or [nuxt The experience of .js](https://nuxtjs.org/). 54 | 55 | Then start the local dev server, 56 | 57 | ```bash 58 | $ umi dev 59 | ``` 60 | 61 | 62 | 63 | ## Convensional Routing 64 | 65 | After starting `umi dev`, you will find a directory of `.umi` under pages. What is this? This is the temporary directory of umi, you can do some verification here, but please do not modify the code directly here, umi restart or file modification under pages will regenerate the files in this folder. 66 | 67 | Then we add some route jump code to `index.js` and `users.js`. 68 | 69 | First modify `pages/index.js`, 70 | 71 | ```diff 72 | + import Link from 'umi/link'; 73 | import styles from './index.css'; 74 | 75 | export default function() { 76 | return ( 77 |
    78 |

    Page index

    79 | + go to /users 80 |
    81 | ); 82 | } 83 | ``` 84 | 85 | Then modify `pages/users.js`, 86 | 87 | ```diff 88 | + import router from 'umi/router'; 89 | import styles from './index.css'; 90 | 91 | export default function() { 92 | return ( 93 |
    94 |

    Page index

    95 | + 96 |
    97 | ); 98 | } 99 | ``` 100 | 101 | Then verify in the browser, and it should already be able to jump between the index page and the users pages. 102 | 103 | ## Build and Deploy 104 | 105 | ### Build 106 | 107 | Run `umi build`, 108 | 109 | ```bash 110 | $ umi build 111 | 112 | DONE Compiled successfully in 1729ms 113 | 114 | File sizes after gzip: 115 | 116 | 68.04 KB dist/umi.js 117 | 83 B dist/umi.css 118 | ``` 119 | 120 | The files is generated to `./dist` by default. You could view the files by the `tree` command (Windows users can skip this step) 121 | 122 | ```bash 123 | $ tree ./dist 124 | ./dist 125 | ├── index.html 126 | ├── umi.css 127 | └── umi.js 128 | ``` 129 | 130 | ### Local Verification 131 | 132 | Local verification can be done via `serve` before publishing. 133 | 134 | ```bash 135 | $ yarn global add serve 136 | $ serve ./dist 137 | 138 | Serving! 139 | 140 | - Local: http://localhost:5000 141 | - On Your Network: http://{Your IP}:5000 142 | 143 | Copied local address to clipboard! 144 | ``` 145 | 146 | Visit http://localhost:5000, which should be same as `umi dev`. 147 | 148 | ### Deploy 149 | 150 | Once verified, you can deploy it. Here is a demonstration with [now](http://now.sh/). 151 | 152 | ```bash 153 | $ yarn global add now 154 | $ now ./dist 155 | 156 | > Deploying /private/tmp/sorrycc-1KVCmK/dist under chencheng 157 | > Synced 3 files (301.93KB) [2s] 158 | > https://dist-jtckzjjatx.now.sh [in clipboard] [1s] 159 | > Deployment complete! 160 | ``` 161 | 162 | Then open the url to view it online. 163 | -------------------------------------------------------------------------------- /docs/zh/plugin/umi-plugin-react.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebarDepth: 3 3 | --- 4 | 5 | # umi-plugin-react 6 | 7 | 这是官方封装的一个插件集,包含 13 个常用的进阶功能。 8 | 9 | ## 安装 10 | 11 | ```bash 12 | $ yarn add umi-plugin-react --dev 13 | ``` 14 | 15 | ## 使用 16 | 17 | 在 `.umirc.js` 里配置: 18 | 19 | ```js 20 | export default { 21 | plugins: [ 22 | ['umi-plugin-react', { 23 | dva: { 24 | immer: true, 25 | }, 26 | antd: true, 27 | routes: { 28 | exclude: [/models\//], 29 | }, 30 | polyfills: ['ie9'], 31 | locale: {}, 32 | library: 'react', 33 | dynamicImport: { 34 | webpackChunkName: true, 35 | loadingComponent: './components/Loading.js', 36 | }, 37 | dll: { 38 | exclude: [], 39 | }, 40 | hardSource: true, 41 | pwa: true, 42 | hd: true, 43 | fastClick: true, 44 | title: 'default title', 45 | }], 46 | ], 47 | }; 48 | ``` 49 | 50 | ## 配置项 51 | 52 | 所有功能默认关闭,有真值配置才会开启。 53 | 54 | ### dva 55 | 56 | * 类型:`Object` 57 | 58 | 基于 [umi-plugin-dva](https://github.com/umijs/umi/tree/master/packages/umi-plugin-dva) 实现,功能详见 [和 dva 一起用](/zh/guide/with-dva.html)。 59 | 60 | 配置项包含: 61 | 62 | * `immer`,是否启用 [dva-immer](https://github.com/dvajs/dva/tree/master/packages/dva-immer) 63 | * `dynamicImport`,是否启用按需加载,配置项同 [#dynamicImport](#dynamicImport),并且如果在 [#dynamicImport](#dynamicImport) 有配置,配置项会继承到 dva 中 64 | * `hmr`,是否启用 dva 的 hmr 65 | 66 | ::: warning 67 | 如果项目中有 dva 依赖,则优先使用项目中的依赖。 68 | ::: 69 | 70 | ### antd 71 | 72 | * 类型:`Boolean` 73 | 74 | 启用后自动配置 [babel-plugin-import](https://github.com/ant-design/babel-plugin-import) 实现 antd 和 antd-mobile 的按需编译,并且内置 antd 和 antd-mobile 依赖,无需手动在项目中安装。 75 | 76 | ::: warning 77 | 如果项目中有 antd 或者 antd-mobile 依赖,则优先使用项目中的依赖。 78 | ::: 79 | 80 | ### routes 81 | 82 | * 类型:`Object` 83 | 84 | 基于 [umi-plugin-routes](https://github.com/umijs/umi/tree/master/packages/umi-plugin-routes) 实现,用于批量修改路由。 85 | 86 | 配置项包含: 87 | 88 | * `exclude`,值为 `Array(RegExp)`,用于忽略某些路由,比如使用 dva 后,通常需要忽略 models、components、services 等目录 89 | * `update`, 值为 `Function`,用于更新路由 90 | 91 | ### polyfills 92 | 93 | * 类型:`Array(String)` 94 | 95 | 基于 [umi-plugin-polyfills](https://github.com/umijs/umi/tree/master/packages/umi-plugin-polyfills) 实现,用于加各种补丁。 96 | 97 | 目前支持配置 `['ie9']`、`['ie10']` 或 `['ie11']`,实现一键兼容。 98 | 99 | ### locale 100 | 101 | * 类型:`Object` 102 | 103 | 基于 [umi-plugin-locale](https://github.com/umijs/umi/tree/master/packages/umi-plugin-locale) 和 [react-intl](https://github.com/yahoo/react-intl) 实现,用于解决 i18n 问题。 104 | 105 | 配置项包含: 106 | 107 | * `default: 'zh-CN'`, // default zh-CN 108 | * `baseNavigator: true`, // default true, when it is true, will use `navigator.language` overwrite default 109 | * `antd: true`, // use antd, default is true 110 | 111 | ### library 112 | 113 | * 类型:`String` 114 | 115 | 可能切换底层库为 preact 或 react。 116 | 117 | ### dynamicImport 118 | 119 | * 类型:`Object` 120 | 121 | 实现路由级的动态加载(code splitting),可按需指定哪一级的按需加载。 122 | 123 | 配置项包含: 124 | 125 | * `webpackChunkName`,是否通过 webpackChunkName 实现有意义的异步文件名 126 | * `loadingComponent`,指定加载时的组件路径 127 | * `level`,指定按需加载的路由等级 128 | 129 | ### dll 130 | 131 | * 类型:`Object` 132 | 133 | 通过 webpack 的 dll 插件预打包一份 dll 文件来达到二次启动提速的目的。 134 | 135 | 配置项包含: 136 | 137 | * `include` 138 | * `exclude` 139 | 140 | ### hardSource 141 | 142 | * 类型:`Boolean` 143 | 144 | 通过 [hard-source-webpack-plugin](https://github.com/mzgoddard/hard-source-webpack-plugin) 开启 webpack 缓存,二次启动时间减少 80%。推荐非 windows 电脑使用,windows 下由于大文件 IO 比较慢,可自行决定是否启用。 145 | 146 | ### pwa 147 | 148 | * 类型:`Object` 149 | 150 | 开启 pwa 。 151 | 152 | ### hd 153 | 154 | * 类型:`Boolean` 155 | 156 | 开启高清方案。 157 | 158 | ### fastClick 159 | 160 | * 类型:`Boolean` 161 | 162 | 启用 fastClick。 163 | 164 | ### title 165 | 166 | * 类型:`String` 或者 `Object` 167 | 168 | 开启 title 插件,设置 HTML title: 169 | 170 | 配置项包含: 171 | 172 | * `defaultTitle: '默认标题'`, // 必填,当配置项为 String 时直接配置项作为 defaultTitle 173 | * `format: '{parent}{separator}{current}'`, // default {parent}{separator}{current}, title format 174 | * `separator: ' - '`, // default ' - ' 175 | 176 | 当 title 插件开启后你可以在 routes 配置或者 pages 下的页面组件中配置 title。 177 | 178 | 比如使用配置式路由的时候如下配置: 179 | 180 | ```js 181 | // .umirc.js or config/config.js 182 | export default { 183 | routes: [{ 184 | path: '/testpage', 185 | component: './testpage', 186 | title: 'test page', 187 | }], 188 | } 189 | ``` 190 | 191 | 使用约定式路由的时候则直接在页面组件中配置: 192 | 193 | ```jsx 194 | /** 195 | * title: test page 196 | */ 197 | export default () => { 198 | return
    testpage
    ; 199 | } 200 | ``` 201 | -------------------------------------------------------------------------------- /docs/guide/deploy.md: -------------------------------------------------------------------------------- 1 | # Deploy 2 | 3 | ## Default Scheme 4 | 5 | Umi@2 is friendly to newbies by default, so it does not load on-demand by default. After `umi build`, it outputs three files: `index.html`, `umi.js` and `umi.css`. 6 | 7 | ## Do Not Output HTML Files 8 | 9 | Some scene html files are handed to the backend output. The frontend build does not need to output html files. The environment variable `HTML=none` is configurable. 10 | 11 | ```bash 12 | $ HTML=none umi build 13 | ``` 14 | 15 | ## Deploy HTML to a Non-Root Directory 16 | 17 | I often have students asking this question: 18 | 19 | > Why is my local development good, no response after deployment, and no error? 20 | 21 | **No error!** This is a typical phenomenon where an application is deployed on a non-root path. Why do you have this problem? Because the route does not match, for example, if you deploy the application under `/xxx/` and then access `/xxx/hello`, and the code matches `/hello`, then it will not match, but there is no definition. A fallback route, such as 404, will display a blank page. 22 | 23 | How to deal with it? 24 | 25 | Can be solved by configuring [base](/config/#base). 26 | 27 | ```bash 28 | export default { 29 | base: '/path/to/your/app/root', 30 | }; 31 | ``` 32 | 33 | ## Use hashHistory 34 | 35 | This can be solved by configuring [history](/config/#history) for `hash`. 36 | 37 | ```bash 38 | export default { 39 | history: 'hash', 40 | }; 41 | ``` 42 | 43 | ## Load on Demand 44 | 45 | To implement on-demand loading, load the umi-plugin-react plugin and configure [dynamicImport](/plugin/umi-plugin-react.html#dynamicimport). 46 | 47 | ```js 48 | export default { 49 | plugins: [ 50 | ['umi-plugin-react', { 51 | dynamicImport: true, 52 | }], 53 | ], 54 | }; 55 | ``` 56 | 57 | See the parameter [umi-plugin-react#dynamicImport](/plugin/umi-plugin-react.html#dynamicimport) for details. 58 | 59 | ## Static Resources in Non-Root Directory or CDN 60 | 61 | At this point, you need to configure [publicPath](/config/#publicPath). As for publicPath, what? Look at the [webpack documentation](https://webpack.js.org/configuration/output/#output-publicpath) and point it to the path where the static resources (js, css, images, fonts, etc.) are located. 62 | 63 | ```js 64 | export default { 65 | publicPath: "http://yourcdn/path/to/static/" 66 | } 67 | ``` 68 | 69 | ## Using the publicPath of Runtime 70 | 71 | For scenes that need to manage publicPath in html, such as judging the environment to make different output in html, you can solve it by configuring [runtimePublicPath](/config/#history). 72 | 73 | ```bash 74 | export default { 75 | runtimePublicPath: true, 76 | }; 77 | ``` 78 | 79 | Then output in html: 80 | 81 | ```html 82 | 85 | ``` 86 | 87 | ## Static 88 | 89 | In some scenarios, you can't do html fallback on the server side, that is, let each route output the contents of index.html, then it needs to be static. 90 | 91 | For example, in the above example, we configured in .umirc.js: 92 | 93 | ```js 94 | export default { 95 | exportStatic: {}, 96 | } 97 | ``` 98 | 99 | Then execute the umi build and output an html file for each route. 100 | 101 | ``` 102 | ./dist 103 | ├── index.html 104 | ├── list 105 | │   └── index.html 106 | └── static 107 | ├── pages__index.5c0f5f51.async.js 108 | ├── pages__list.f940b099.async.js 109 | ├── umi.2eaebd79.js 110 | └── umi.f4cb51da.css 111 | ``` 112 | 113 | > Note: Statics does not support scenarios with variable routing. 114 | 115 | ## HTML Suffix 116 | 117 | In some static scenarios, the index file is not automatically read, such as Alipay's container environment, then this html file cannot be generated. 118 | 119 | ``` 120 | ├── index.html 121 | ├── list 122 | │ └── index.html 123 | ``` 124 | 125 | But generate, 126 | 127 | ``` 128 | ├── index.html 129 | └── list.html 130 | ``` 131 | 132 | The configuration is in .umirc.js, 133 | 134 | ```js 135 | export default { 136 | exportStatic: { 137 | htmlSuffix: true, 138 | }, 139 | } 140 | ``` 141 | 142 | Umi build will generate, 143 | 144 | ``` 145 | ./dist 146 | ├── index.html 147 | ├── list.html 148 | └── static 149 | ├── pages__index.5c0f5f51.async.js 150 | ├── pages__list.f940b099.async.js 151 | ├── umi.2924fdb7.js 152 | └── umi.cfe3ffab.css 153 | ``` 154 | 155 | ## Statically Output to Any Path 156 | 157 | ```js 158 | export default { 159 | exportStatic: { 160 | htmlSuffix: true, 161 | dynamicRoot: true, 162 | }, 163 | } 164 | ``` 165 | -------------------------------------------------------------------------------- /docs/zh/guide/faq.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebarDepth: 3 3 | --- 4 | 5 | # FAQ 6 | 7 | ## General 8 | 9 | ### 是否可用于生产环境? 10 | 11 | umi 是蚂蚁金服的底层前端框架,已直接或间接地服务了 600+ 应用,包括 java、node、H5 无线、离线(Hybrid)应用、纯前端 assets 应用、CMS 应用等。 12 | 13 | ### 如何查看 react、react-dom、react-router 等版本号? 14 | 15 | ```bash 16 | $ umi -v --verbose 17 | 18 | umi@2.0.0 19 | darwin x64 20 | node@v10.6.0 21 | umi-build-dev@1.0.0 22 | af-webpack@1.0.0 23 | babel-preset-umi@1.0.0 24 | umi-test@1.0.0 25 | react@16.4.2 (/Users/chencheng/code/github.com/ant-design/ant-design-pro/node_modules/react) 26 | react-dom@16.4.2 (/Users/chencheng/code/github.com/ant-design/ant-design-pro/node_modules/react-dom) 27 | react-router@4.3.1 (/Users/chencheng/code/github.com/umijs/umi/packages/umi-build-dev/node_modules/react-router) 28 | react-router-dom@4.3.1 (/Users/chencheng/code/github.com/ant-design/ant-design-pro/node_modules/react-router-dom) 29 | dva@2.4.0 (/Users/chencheng/code/github.com/ant-design/ant-design-pro/node_modules/dva) 30 | dva-loading@2.0.5 31 | dva-immer@0.2.3 32 | path-to-regexp@1.7.0 33 | ``` 34 | 35 | ### 如何引入 @babel/polyfill ? 36 | 37 | 先安装依赖, 38 | 39 | ```bash 40 | $ yarn add @babel/polyfill 41 | ``` 42 | 43 | 然后新建 `src/global.js`,内容如下: 44 | 45 | ```js 46 | import '@babel/polyfill'; 47 | ``` 48 | 49 | ### 如何动态修改 title ? 50 | 51 | 可以通过 [react-helmet](https://github.com/nfl/react-helmet) 动态修改 title 。 52 | > 注意:在混合应用中,ios端web容器内,使用react-helmet失效的话,可以尝试使用[react-document-title](https://github.com/gaearon/react-document-title)。 53 | 54 | ## 报错 55 | 56 | ### `Object.values` is not a function 57 | 58 | e.g. 59 | 60 | 61 | 62 | 升级 node 版本,并确保版本是 8.10 或以上。 63 | 64 | ### `exports is not defined` 65 | 66 | e.g. 67 | 68 | 69 | 70 | 检查 babel 配置,删除不必要的 preset 和 plugin 。 71 | 72 | ### `Plugin umi-plugin-react:pwa initialize failed` 73 | 74 | e.g. 75 | 76 | 77 | 78 | 确保有 package.json 并配置 `name` 属性。 79 | 80 | ### `Conflicting order between [mini-css-extract-plugin]` 81 | 82 | e.g. 83 | 84 | 85 | 86 | 这是 [webpack 插件的问题](https://github.com/webpack-contrib/mini-css-extract-plugin/issues/250),不会影响 CSS 文件的正常生产,可暂时忽略。 87 | 88 | ### `umi` 不是内部或外部命令 89 | 90 | e.g. 91 | 92 | 93 | 94 | 需配置 NODE_PATH 环境变量,如使用 yarn,可通过执行 `yarn global bin` 拿到 bin 路径。 95 | 96 | ## webpack 97 | 98 | ### 如何配置额外的 loader ? 99 | 100 | 比如 svg 我希望不走 base64,而是全部产生 svg 文件,可以这样配: 101 | 102 | ```js 103 | export default { 104 | // 添加 url-loader 的 exclude 105 | urlLoaderExcludes: [/.svg$/], 106 | // 添加 loader 107 | chainWebpack(config) { 108 | config.module.rule('svg-with-file') 109 | .test(/.svg$/) 110 | .use('svg-with-file-loader') 111 | .loader('file-loader') 112 | }, 113 | } 114 | ``` 115 | 116 | ## CSS 117 | 118 | ### 为啥我 import 的 css 文件不生效? 119 | 120 | umi 默认是开启 css modules 的,请按照 css modules 的方式进行书写。 121 | 122 | 参考: 123 | 124 | * [css-modules/css-modules](https://github.com/css-modules/css-modules) 125 | * [CSS Modules 用法教程](http://www.ruanyifeng.com/blog/2016/06/css_modules.html) 126 | 127 | ### 如何禁用 css modules ? 128 | 129 | 修改 `.umirc.js`: 130 | 131 | ```json 132 | { 133 | "disableCSSModules": true 134 | } 135 | ``` 136 | 137 | 但没有特殊的理由时,不建议关闭 css modules。 138 | 139 | ### 如何使用 sass ? 140 | 141 | 先安装额外的依赖, 142 | 143 | ```bash 144 | $ npm i node-sass sass-loader --save 145 | ``` 146 | 147 | 然后修改 `.umirc.js`: 148 | 149 | ```json 150 | { 151 | "sass": {} 152 | } 153 | ``` 154 | 155 | ## Test 156 | 157 | ### 如何断点调试 158 | 159 | 确保 node 在 8.10 以上,然后执行: 160 | 161 | ```bash 162 | $ node --inspect-brk ./node_modules/.bin/umi test 163 | ``` 164 | 165 | 然后在浏览器里打开 chrome://inspect/#devices 进行 inspect 和断点。 166 | 167 | ## 部署 168 | 169 | ### build 后访问路由刷新后 404? 170 | 171 | 几个方案供选择: 172 | 173 | * 改用 hashHistory,在 `.umirc.js` 里配 `history: 'hash'` 174 | * 静态化,在 `.umirc.js` 里配 `exportStatic: true` 175 | * 服务端配置路由 fallback 到 index.html 176 | 177 | ### build之后图片丢失? 178 | 179 | 可能是图片没有正确引用,可以参考一下代码,正确引入图片。 180 | 181 | ```js 182 | import React from 'react'; 183 | import logo from './logo.png'; // 告诉WebPACK这个JS文件使用这个图像 184 | 185 | console.log(logo); // logo.84287d09.png 186 | 187 | function Header() { 188 | // 导入图片 189 | return Logo; 190 | } 191 | 192 | export default Header; 193 | 194 | ``` 195 | 在css中使用,注意不要使用绝对路径 196 | ```css 197 | .Logo { 198 | background-image: url(./logo.png); 199 | } 200 | ``` 201 | 202 | > 注意:图片大小小于 10 k 时会走 base64。即不会被拷贝到 public 文件夹下,而是以 base64 的资源存在。 203 | -------------------------------------------------------------------------------- /docs/guide/mock-data.md: -------------------------------------------------------------------------------- 1 | # Mock Data 2 | 3 | Mock data is indispensable in front-end development process and it is the key link to separate the front-end from the back-end. Through the pre-agreed interface with the server-side, simulation request data and even logic, can make the front-end development independent, will not be blocked by the development of the server-side. 4 | 5 | ## Using the mock feature of umi 6 | 7 | Umi agreed that the files under the mock folder are mock files, files export interface definitions, support for real-time refresh based on 'require' dynamic analysis, support for ES6 syntax, and with friendly error messages, see [mock-data](https://umijs.org/guide/mock-data.html) for more detail. 8 | 9 | ```js 10 | export default { 11 | // supported values are Object and Array 12 | 'GET /api/users': { users: [1, 2] }, 13 | 14 | // GET and POST can be omitted 15 | '/api/users/1': { id: 1 }, 16 | 17 | // support for custom functions, APIs refer to express@4 18 | 'POST /api/users/create': (req, res) => { res.end('OK'); }, 19 | }; 20 | ``` 21 | 22 | When a client(browser) sends a request, such as `GET /api/users`, the locally launched `umi dev` will match the request path and method with this configuration file, if it find a match, the request will be processed through configuration, just like the sample, you can directly return the data, or process and redirect it to another server through a function. 23 | 24 | For example, define the following mapping rules as below: 25 | 26 | ``` 27 | 'GET /api/currentUser': { 28 | name: 'momo.zxy', 29 | avatar: imgMap.user, 30 | userid: '00000001', 31 | notifyCount: 12, 32 | }, 33 | ``` 34 | 35 | Request local interface `/api/users`: 36 | 37 | Request header 38 | 39 | 40 | 41 | Response data 42 | 43 | 44 | 45 | ### Introduce Mock.js 46 | 47 | [Mock.js](http://mockjs.com/) is a commonly used third-party library to help generate mock data. Of course, you can use any library you like working with roadhog to build data simulation functions. 48 | 49 | ```js 50 | import mockjs from 'mockjs'; 51 | 52 | export default { 53 | // Use third-party library such as mockjs 54 | 'GET /api/tags': mockjs.mock({ 55 | 'list|100': [{ name: '@city', 'value|1-100': 50, 'type|0-2': 1 }], 56 | }), 57 | }; 58 | ``` 59 | 60 | ### Add a cross-domain request header 61 | 62 | Just set the header of `response`: 63 | 64 | ``` 65 | 'POST /api/users/create': (req, res) => { 66 | ... 67 | res.setHeader('Access-Control-Allow-Origin', '*'); 68 | ... 69 | }, 70 | ``` 71 | 72 | ## Properly split your mock file 73 | 74 | For the entire system, the request interface is complex and numerous, in order to handle a large number of mock request scenarios, we usually abstract each data model into a file, and put them all in the `mock` folder. And then they will be automatically introduced. 75 | 76 | 77 | 78 | ## How to simulate delay 79 | 80 | In order to simulate the network data request more realistically, it is necessary to simulate network delay time in most cases. 81 | 82 | ### Add setTimeout manually to simulate delay 83 | 84 | You can rewrite the proxy method of the request and add the processing of simulation delay to it, like: 85 | 86 | ```js 87 | 'POST /api/forms': (req, res) => { 88 | setTimeout(() => { 89 | res.send('Ok'); 90 | }, 1000); 91 | }, 92 | ``` 93 | 94 | ### Use plugins to simulate delay 95 | 96 | Although the method above is simple, it may be troublesome when you need to add delays for all request, it can be simplified by a third-party plugin,such as [roadhog-api-doc#delay](https://github.com/nikogu/roadhog-api-doc/blob/master/lib/utils.js#L5). 97 | 98 | ```js 99 | import { delay } from 'roadhog-api-doc'; 100 | 101 | const proxy = { 102 | 'GET /api/project/notice': getNotice, 103 | 'GET /api/activities': getActivities, 104 | 'GET /api/rule': getRule, 105 | 'GET /api/tags': mockjs.mock({ 106 | 'list|100': [{ name: '@city', 'value|1-100': 50, 'type|0-2': 1 }] 107 | }), 108 | 'GET /api/fake_list': getFakeList, 109 | 'GET /api/fake_chart_data': getFakeChartData, 110 | 'GET /api/profile/basic': getProfileBasicData, 111 | 'GET /api/profile/advanced': getProfileAdvancedData, 112 | 'POST /api/register': (req, res) => { 113 | res.send({ status: 'ok' }); 114 | }, 115 | 'GET /api/notices': getNotices, 116 | }; 117 | 118 | // Calling the delay function, unified processing 119 | export default delay(proxy, 1000); 120 | ``` 121 | 122 | ## Joint debugging 123 | 124 | After finishing the local development, if the interface of server-side meets the previous convention, you only need to open the local proxy or redirect the proxy to the target server to access the real server data, which is very convenient. 125 | -------------------------------------------------------------------------------- /docs/guide/app-structure.md: -------------------------------------------------------------------------------- 1 | # Directory and Convention 2 | 3 | In the organization of files and directories, umi tries to choose the agreed upon way. 4 | 5 | The directory structure of a complex application is as follows: 6 | 7 | ``` 8 | . 9 | ├── dist/ // default build output directory 10 | ├── mock/ // The directory where the mock file is located, based on express 11 | ├── config/ 12 | ├── config.js // umi configuration, same as .umirc.js, choose one 13 | └── src/ // source directory, optional 14 | ├──layouts/index.js // global layout 15 | ├── pages/ // page directory, the file inside is the route 16 | ├── .umi/ // dev temp directory, need to be added to .gitignore 17 | ├── .umi-production/ // build temporary directory, will be deleted automatically 18 | ├── document.ejs // HTML template 19 | ├── 404.js // 404 page 20 | ├── page1.js // page 1, arbitrarily named, export react component 21 | ├── page1.test.js // Use case file, umi test will match all files ending in .test.js and .e2e.js 22 | └── page2.js // page 2, arbitrarily named 23 | ├── global.css // Conventional global style files, imported automatically, or global.less 24 | ├── global.js // can add polyfill here 25 | ├── .umirc.js // umi configuration, same as config/config.js, choose one 26 | ├── .env // environment variable 27 | └── package.json 28 | ``` 29 | 30 | ## ES6 Grammar 31 | 32 | Configuration files, mock files, etc. are registered in real time with `@babel/register`, so you can use ES6 syntax and es modules just like files in src. 33 | 34 | ## dist 35 | 36 | The default output path can be modified by configuring `outputPath`. 37 | 38 | ## mock 39 | 40 | It is agreed that all `.js` files in the mock directory will be parsed as mock files. 41 | 42 | For example, create a new `mock/users.js` with the following contents: 43 | 44 | ```js 45 | export default { 46 | '/api/users': ['a', 'b'], 47 | } 48 | ``` 49 | 50 | Then visit [http://localhost:8000/api/users](http://localhost:8000/api/users) in your browser to see `['a', 'b']`. 51 | 52 | ## src 53 | 54 | By convention, `src` is the source directory. But optional, simple items can be added without the `src` directory. 55 | 56 | For example: the effect of the following two directory structures is the same. 57 | 58 | ``` 59 | + src 60 | + pages 61 | - index.js 62 | + layouts 63 | - index.js 64 | - .umirc.js 65 | ``` 66 | 67 | ``` 68 | + pages 69 | - index.js 70 | + layouts 71 | - index.js 72 | - .umirc.js 73 | ``` 74 | 75 | ## src/layouts/index.js 76 | 77 | The global layout is actually a layer outside the route. 78 | 79 | For example, your route is: 80 | 81 | ``` 82 | [ 83 | { path: '/', component: './pages/index' }, 84 | { path: '/users', component: './pages/users' }, 85 | ] 86 | ``` 87 | 88 | If there is `layouts/index.js`, then the route becomes: 89 | 90 | ``` 91 | [ 92 | { path: '/', component: './layouts/index', routes: [ 93 | { path: '/', component: './pages/index' }, 94 | { path: '/users', component: './pages/users' }, 95 | ] } 96 | ] 97 | ``` 98 | 99 | ## src/pages 100 | 101 | All the `(j|t)sx?` files under the pages are the routes. For more information on contracted routing, go to the Routing chapter. 102 | 103 | ## src/pages/404.js 104 | 105 | 404 page. Note that there is a 404 prompt page provided by the built-in umi in development mode, so you can access this page only by explicitly accessing `/404`. 106 | 107 | ## src/pages/document.ejs 108 | 109 | When this file is available, it overrides the default HTML template. Needs to include at least the following code: 110 | 111 | ```html 112 |
    113 | ``` 114 | 115 | ## src/pages/.umi 116 | 117 | This is a temporary directory produced by umi dev. It contains `umi.js` and `router.js` by default, and some plugins will generate some other temporary files here. You can do some validation here, **but please don't modify the code directly here, umi restart or file modification under pages will regenerate the files in this folder.** 118 | 119 | ## src/pages/.umi-production 120 | 121 | Same as `src/pagers/.umi`, but generated in `umi build`, it will be automatically deleted after `umi build`. 122 | 123 | ## .test.js and .e2e.js 124 | 125 | The test file, `umi test` will find all the .(test|e2e).(j|t)s files to run the test. 126 | 127 | ## src/global.(j|t)sx? 128 | 129 | At the beginning of the entry file is automatically introduced, you can consider adding polyfill here. 130 | 131 | ## src/global.(css|less|sass|scss) 132 | 133 | This file does not go css modules, is automatically introduced, you can write some global styles, or do some style coverage. 134 | 135 | ## .umirc.js and config/config.js 136 | 137 | Umi's configuration file, choose one. 138 | 139 | ## .env 140 | 141 | Environment variables, such as: 142 | 143 | ``` 144 | CLEAR_CONSOLE=none 145 | BROWSER=none 146 | ``` 147 | -------------------------------------------------------------------------------- /docs/guide/with-dva.md: -------------------------------------------------------------------------------- 1 | # Use umi with dva 2 | 3 | As of `>= umi@2`, we recommend using [umi-plugin-react](https://github.com/umijs/umi/tree/master/packages/umi-plugin-react) for `dva` integration. 4 | 5 | ## Features 6 | 7 | * **Model loading by directory**, getting rid of `app.model` 8 | * **File name as namespace**, `namespace` as model key will be exported by `umi` 9 | * **No manually defined router.js**, `umi` will take over the router stuff, and both `model`s and `component`s can be loaded on demand 10 | * **Built-in query-string handler**, manually encoding and decoding URL are not required any more 11 | * **Built-in dva-loading and dva-immer support**, of which `dva-immer` can be enabled via configuration 12 | * **Out of box**, dependencies such as: `dva`, `dva-loading`, `dva-immer`, `path-to-regexp`, `object-assign`, `react`, `react-dom` are built in, so that you don't have to worry about them 13 | 14 | ## Usage 15 | 16 | Install via `yarn`, 17 | 18 | ```bash 19 | $ yarn add umi-plugin-react 20 | ``` 21 | 22 | Install via `npm`, using the command `npm install --save umi-plugin-react`. 23 | 24 | Add configuration in `.umirc.js`: 25 | 26 | ```js 27 | export default { 28 | plugins: [ 29 | [ 30 | 'umi-plugin-react', 31 | { 32 | dva: true, 33 | },. 34 | ] 35 | ], 36 | }; 37 | ``` 38 | 39 | Enable `dva-immer` for elegant reducer writing experience 40 | 41 | ```js 42 | export default { 43 | plugins: [ 44 | [ 45 | 'umi-plugin-react', 46 | { 47 | dva: { 48 | immer: true 49 | } 50 | } 51 | ], 52 | ], 53 | }; 54 | ``` 55 | 56 | ## Registering models 57 | 58 | There are two types of models: the globally registered (global) model, and the page-level model. 59 | 60 | The global model should be defined in `/src/models/`, and can be referenced in all other pages. 61 | 62 | The page-level model should not be used in any other page. 63 | 64 | 65 | Model loading rules: 66 | 67 | * `src/models/**/*.js` are defined as global models 68 | * `src/pages/**/models/**/*.js` are defined as page-level models 69 | * global models will be loaded along with the application; page-level models are loaded on demand while in `production` build (both will always be loaded in `development` build) 70 | * page-level models can be `.js` files in `models/**/*.js` pattern 71 | * page-level models can be scanned upward to app structure, For example: if you have page `.js` like `pages/a/b.js`, its page-level model shall be `pages/a/b/models/**/*.js` + `pages/a/models/**/*.js`... 72 | * if `model.js` is defined, the page should be a single-file-model, which means you don't have to create `modles` directory if you have only one model. So if you have `model.js` defined, all `.js` files defined in `models/**/*.js` will be ignored 73 | 74 | Example: 75 | 76 | ``` 77 | + src 78 | + models 79 | - g.js 80 | + pages 81 | + a 82 | + models 83 | - a.js 84 | - b.js 85 | + ss 86 | - s.js 87 | - page.js 88 | + c 89 | - model.js 90 | + d 91 | + models 92 | - d.js 93 | - page.js 94 | - page.js 95 | ``` 96 | 97 | With the above file structure: 98 | 99 | * the global model is `src/models/g.js` 100 | * the page-level models for `/a` is `src/pages/a/models/{a,b,ss/s}.js` 101 | * the page-level model for `/c` is `src/pages/c/model.js` 102 | * the page-level models for `/c/d` are `src/pages/c/model.js, src/pages/c/d/models/d.js` 103 | 104 | ## Configuration and plugins 105 | 106 | > The previous configuration in `src/dva.js` has been deprecated, and will remove support in next major release. 107 | 108 | Create a new `app.js` in the `src` directory with the following contents: 109 | 110 | ```js 111 | export const dva = { 112 | config: { 113 | onError(e) { 114 | e.preventDefault(); 115 | console.error(e.message); 116 | }, 117 | }, 118 | plugins: [ 119 | require('dva-logger')(), 120 | ], 121 | }; 122 | ``` 123 | 124 | ## FAQ 125 | 126 | ### Page component is not re-rendered whenever url changed? 127 | 128 | If you have `connect` data in `layouts/index.js`, `umi/withRouter` is required 129 | 130 | ```js 131 | import withRouter from 'umi/withRouter'; 132 | 133 | export default withRouter(connect(mapStateToProps)(LayoutComponent)); 134 | ``` 135 | 136 | ### How to access `store` or `dispatch`? 137 | 138 | ```js 139 | window.g_app._store 140 | window.g_app._store.dispatch 141 | ``` 142 | 143 | ### How to disable load on demand for `component` and `models`? 144 | 145 | Add config to `.umirc.js`: 146 | 147 | ```js 148 | export default { 149 | plugins: [ 150 | [ 151 | 'umi-plugin-react', 152 | { 153 | dva: { 154 | dynamicImport: undefined // config in dva 155 | }, 156 | dynamicImport: undefined // root config will be inherited as well 157 | } 158 | ], 159 | ], 160 | }; 161 | ``` 162 | 163 | ### Page component is not re-rendered whenever url is changed while `connect` data in `layout` 164 | 165 | Check the order of `connect`, `withRouter` usage 166 | 167 | ```js 168 | import withRouter from 'umi/withRouter'; 169 | export default withRouter(connect()(Layout)); 170 | ``` 171 | 172 | ## References 173 | 174 | * [Improve dva project with umi](https://github.com/sorrycc/blog/issues/66) 175 | * [umi + dva, write your own user-management CURD app](https://github.com/sorrycc/blog/issues/62) 176 | -------------------------------------------------------------------------------- /docs/plugin/umi-plugin-react.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebarDepth: 3 3 | --- 4 | 5 | # umi-plugin-react 6 | 7 | This is a collection of officially packaged plugins with 13 commonly used advanced features. 8 | 9 | ## Install 10 | 11 | ```bash 12 | $ yarn add umi-plugin-react --dev 13 | ``` 14 | 15 | ## Usage 16 | 17 | Configured in `.umirc.js`: 18 | 19 | ```js 20 | export default { 21 | plugins: [ 22 | ['umi-plugin-react', { 23 | dva: { 24 | immer: true, 25 | }, 26 | antd: true, 27 | routes: { 28 | exclude: [/models\//], 29 | }, 30 | polyfills: ['ie9'], 31 | locale: {}, 32 | library: 'react', 33 | dynamicImport: { 34 | webpackChunkName: true, 35 | loadingComponent: './components/Loading.js', 36 | }, 37 | dll: { 38 | exclude: [], 39 | }, 40 | hardSource: true, 41 | pwa: true, 42 | hd: true, 43 | fastClick: true, 44 | title: 'default title', 45 | }], 46 | ], 47 | }; 48 | ``` 49 | 50 | ## Configuration items 51 | 52 | All features are turned off by default and will be enabled if there is a true value. 53 | 54 | ### dva 55 | 56 | * Type: `Object` 57 | 58 | Based on [umi-plugin-dva](https://github.com/umijs/umi/tree/master/packages/umi-plugin-dva), see the details at [Use with dva](/guide/with-dva.html)。 59 | 60 | Configuration items includes: 61 | 62 | * `immer`, Whether to enable [dva-immer](https://github.com/dvajs/dva/tree/master/packages/dva-immer) 63 | * `dynamicImport`, Whether to enable dynamic import, options same as [#dynamicImport](#dynamicImport), and if you configure it in [#dynamicImport](#dynamicImport), the options items will be inherited into dva 64 | * `hmr`, Whether to enable dva hmr 65 | 66 | ::: warning 67 | If there is a dva dependency in the project, the dependencies in the project are prioritized. 68 | ::: 69 | 70 | ### antd 71 | 72 | * Type: `Boolean` 73 | 74 | Automatically configure [babel-plugin-import](https://github.com/ant-design/babel-plugin-import) to enable on-demand compilation of antd and antd-mobile, with built-in antd and antd-mobile dependencies, There is no need to manually install in the project. 75 | 76 | ::: warning 77 | If there is an ant or antd-mobile dependency in the project, the dependencies in the project are prioritized. 78 | ::: 79 | 80 | ### routes 81 | 82 | * Type: `Object` 83 | 84 | based on [umi-plugin-routes](https://github.com/umijs/umi/tree/master/packages/umi-plugin-routes), used to modify routes in batches. 85 | 86 | options include: 87 | 88 | * `exclude`, type is `Array(RegExp)`, used to ignore certain routes, such as using dva, usually need to ignore the models, components, services, etc. 89 | * `update`, type is `Function`, for update routes. 90 | 91 | ### polyfills 92 | 93 | * Type: `Array(String)` 94 | 95 | Based on [umi-plugin-polyfills](https://github.com/umijs/umi/tree/master/packages/umi-plugin-polyfills), used to add polyfills. 96 | 97 | Currently supports configuration of `['ie9']`, `['ie10']` or `['ie11']` for quickly compatibility. 98 | 99 | ### locale 100 | 101 | * Type `Object` 102 | 103 | Based on [umi-plugin-locale](https://github.com/umijs/umi/tree/master/packages/umi-plugin-locale) and [react-intl](https://github.com/yahoo/react-intl), used to resolve internationalization. 104 | 105 | options include: 106 | 107 | * `default`: 'zh-CN', // default zh-CN 108 | * `baseNavigator`: true, // default true, when it is true, will use `navigator.language` overwrite default 109 | * `antd`: true, // use antd, default is true 110 | 111 | ### library 112 | 113 | * Type: `String` 114 | 115 | It is possible to switch the underlying library to either preact or react. 116 | 117 | ### dynamicImport 118 | 119 | * Type: `Object` 120 | 121 | Implement routing-level code splitting, which specifies which level of on-demand loading is required. 122 | 123 | options include: 124 | 125 | * `webpackChunkName`, Whether to add a meaningful file name 126 | * `loadingComponent`, Specify the component path at load time 127 | * `level`, specifying the route level to code splitting 128 | 129 | ### dll 130 | 131 | * Type: `Object` 132 | 133 | Increase the second startup speed by webpack dll plugin. 134 | 135 | options include: 136 | 137 | * `include` 138 | * `exclude` 139 | 140 | ### hardSource 141 | 142 | * Type: `Boolean` 143 | 144 | Open webpack cache with [hard-source-webpack-plugin](https://github.com/mzgoddard/hard-source-webpack-plugin), 80% increase in speed of the second start. It is recommended to use non-windows computers. Due to the slowness of large file IO under Windows, it is up to you to decide whether to enable it. 145 | 146 | ### pwa 147 | 148 | * Type `Object` 149 | 150 | Enable pwa 。 151 | 152 | ### hd 153 | 154 | * Type `Boolean` 155 | 156 | Turn on the HD solution. 157 | 158 | ### fastClick 159 | 160 | * Type `Boolean` 161 | 162 | Enable fastClick. 163 | 164 | ### title 165 | 166 | * Type `String` or `Object` 167 | 168 | Enable title plugin for set HTML title: 169 | 170 | options include: 171 | 172 | * `defaultTitle`: 'default tile', // required, when option type is String, will use option as the default title 173 | * `format`: '{parent}{separator}{current}', // default {parent}{separator}{current}, title format 174 | * `separator`: ' - ', // default ' - ' 175 | 176 | When the title plugin is enabled you can configure the title in the route configuration or in the page component in pages folder. 177 | 178 | For example: 179 | 180 | ```js 181 | // .umirc.js or config/config.js 182 | export default { 183 | routes: [{ 184 | path: '/testpage', 185 | component: './testpage', 186 | title: 'test page', 187 | }], 188 | } 189 | ``` 190 | 191 | or 192 | 193 | ```jsx 194 | /** 195 | * title: test page 196 | */ 197 | export default () => { 198 | return
    testpage
    ; 199 | } 200 | ``` 201 | -------------------------------------------------------------------------------- /docs/guide/faq.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebarDepth: 3 3 | --- 4 | 5 | # FAQ 6 | 7 | ## General 8 | 9 | ### Can it be used in a production environment? 10 | 11 | Umi is the underlying front-end framework of Ant Financial, which has directly or indirectly served 600+ applications, including java, node, H5 wireless, Hybrid applications, pure front-end assets applications, CMS applications, and more. 12 | 13 | ### How do I view the version numbers such as react, react-dom, and react-router? 14 | 15 | ```bash 16 | $ umi -v --verbose 17 | 18 | umi@2.0.0 19 | darwin x64 20 | node@v10.6.0 21 | umi-build-dev@1.0.0 22 | af-webpack@1.0.0 23 | babel-preset-umi@1.0.0 24 | umi-test@1.0.0 25 | react@16.4.2 (/Users/chencheng/code/github.com/ant-design/ant-design-pro/node_modules/react) 26 | react-dom@16.4.2 (/Users/chencheng/code/github.com/ant-design/ant-design-pro/node_modules/react-dom) 27 | react-router@4.3.1 (/Users/chencheng/code/github.com/umijs/umi/packages/umi-build-dev/node_modules/react-router) 28 | react-router-dom@4.3.1 (/Users/chencheng/code/github.com/ant-design/ant-design-pro/node_modules/react-router-dom) 29 | dva@2.4.0 (/Users/chencheng/code/github.com/ant-design/ant-design-pro/node_modules/dva) 30 | dva-loading@2.0.5 31 | dva-immer@0.2.3 32 | path-to-regexp@1.7.0 33 | ``` 34 | 35 | ### How to introduce @babel/polyfill? 36 | 37 | Install dependencies first, 38 | 39 | ```bash 40 | $ yarn add @babel/polyfill 41 | ``` 42 | 43 | Then create a new `src/global.js` with the following contents: 44 | 45 | ```js 46 | import '@babel/polyfill'; 47 | ``` 48 | 49 | ### How to dynamically modify the title? 50 | 51 | The title can be dynamically modified via [react-helmet](https://github.com/nfl/react-helmet). 52 | > Note: In a hybrid application, if you use react-helmet in the ios web container, you can try [react-document-title](https://github.com/gaearon/react-document-title). 53 | 54 | ## Reporting Error 55 | 56 | ### `Object.values` is not a function 57 | 58 | E.g. 59 | 60 | 61 | 62 | Upgrade the node version and make sure the version is 8.10 or greater. 63 | 64 | ### `exports is not defined` 65 | 66 | E.g. 67 | 68 | 69 | 70 | Check the babel configuration to remove unnecessary presets and plugins. 71 | 72 | ### `Plugin umi-plugin-react:pwa initialize failed` 73 | 74 | E.g. 75 | 76 | 77 | 78 | Make sure you have package.json and have configured the `name` attribute. 79 | 80 | ### `Conflicting order between [mini-css-extract-plugin]` 81 | 82 | E.g. 83 | 84 | 85 | 86 | This is [a problem with the webpack plugin](https://github.com/webpack-contrib/mini-css-extract-plugin/issues/250), which does not affect the normal production of CSS files and can be ignored for now. 87 | 88 | ### `umi` is not an internal or external command 89 | 90 | E.g. 91 | 92 | 93 | 94 | You need to configure the NODE_PATH environment variable. If you use yarn, you can get the bin path by executing `yarn global bin`. 95 | 96 | ## webpack 97 | 98 | ### How to configure additional loader? 99 | 100 | For example, I hope .svg not to produce base64, but to generate svg files, which can be configured like this: 101 | 102 | ```js 103 | export default { 104 | // Add exclude for url-loader 105 | urlLoaderExcludes: [/.svg$/], 106 | // Add loader 107 | chainWebpack(config) { 108 | config.module.rule('svg-with-file') 109 | .test(/.svg$/) 110 | .use('svg-with-file-loader') 111 | .loader('file-loader') 112 | }, 113 | } 114 | ``` 115 | 116 | ## CSS 117 | 118 | ### Why don't my imported CSS files take effect? 119 | 120 | umi use css modules by default, please write your css as css modules. 121 | 122 | Ref: 123 | 124 | * [css-modules/css-modules](https://github.com/css-modules/css-modules) 125 | * [CSS Modules usage tutorial](http://www.ruanyifeng.com/blog/2016/06/css_modules.html) 126 | 127 | ### How to disable CSS modules? 128 | 129 | Modify `.umirc.js`: 130 | 131 | ```json 132 | { 133 | "disableCSSModules": true 134 | } 135 | ``` 136 | 137 | However, it is not recommended to turn off css modules for no particular reason. 138 | 139 | ### How to use sass? 140 | 141 | Install additional dependencies first, 142 | 143 | ```bash 144 | $ npm i node-sass sass-loader --save 145 | ``` 146 | 147 | Then modify `.umirc.js`: 148 | 149 | ```json 150 | { 151 | "sass": {} 152 | } 153 | ``` 154 | 155 | ## Test 156 | 157 | ### How to do breakpoint debugging? 158 | 159 | Make sure node version is above 8.10 and then execute: 160 | 161 | ```bash 162 | $ node --inspect-brk ./node_modules/.bin/umi test 163 | ``` 164 | 165 | Then open chrome://inspect/#devices in the browser for inspect and breakpoints. 166 | 167 | ## Deployment 168 | 169 | ### After the build access route is refreshed 404? 170 | 171 | Several options are available: 172 | 173 | * Use `hashHistory` instead of `history: 'hash' in `.umirc.js` 174 | * Static, with `exportStatic: true` in `.umirc.js` 175 | * The server configures the route fallback to index.html 176 | 177 | ### After the build, the picture is lost? 178 | 179 | It may be that the picture is not correctly quoted. You can refer to the code and import the picture correctly. 180 | 181 | ```js 182 | import React from 'react'; 183 | import logo from './logo.png'; // Tell Webpack this JS file to use this image 184 | 185 | console.log(logo); // logo.84287d09.png 186 | 187 | function header() { 188 | // import image 189 | return Logo; 190 | } 191 | 192 | export default Header; 193 | 194 | ``` 195 | Use in css, be careful not to use absolute paths 196 | ```css 197 | .Logo { 198 | background-image: url(./logo.png); 199 | } 200 | ``` 201 | 202 | > Note: base64 will be taken when the image size is less than 10 k. That is, it will not be copied to the public folder, but will be stored as a base64 resource. 203 | -------------------------------------------------------------------------------- /docs/zh/config/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebarDepth: 2 3 | --- 4 | 5 | # 配置 6 | 7 | ## 基本配置 8 | 9 | ### plugins 10 | 11 | * 类型:`Array` 12 | * 默认值:`[]` 13 | 14 | 指定插件。 15 | 16 | 比如: 17 | 18 | ```js 19 | export default { 20 | plugins: [ 21 | 'umi-plugin-react', 22 | // 插件有参数时为数组,数组的第二项是参数,类似 babel 插件 23 | ['umi-plugin-react', { 24 | dva: true, 25 | }], 26 | ], 27 | }; 28 | ``` 29 | 30 | ### routes 31 | 32 | * 类型:`Array` 33 | * 默认值:`null` 34 | 35 | 配置路由。 36 | 37 | ::: tip 提醒 38 | 如果配置了 `routes`,则约定式路由会不生效。 39 | ::: 40 | 41 | ### disableRedirectHoist 42 | 43 | * 类型:`Boolean` 44 | * 默认值:`false` 45 | 46 | 禁用 redirect 上提。 47 | 48 | 出于一些原因的考虑,我们在处理路由时把所有 redirect 声明提到路由最前面进行匹配,但这导致了一些问题,所以添加了这个配置项,禁用 redirect 上提。 49 | 50 | ### history 51 | 52 | * 类型:`String` 53 | * 默认值:`browser` 54 | 55 | 如需切换 history 方式为 hash(默认是 browser history),配置 `history: 'hash'`。 56 | 57 | ### outputPath 58 | 59 | * 类型:`String` 60 | * 默认值:`./dist` 61 | 62 | 指定输出路径。 63 | 64 | ### base 65 | 66 | * 类型:`String` 67 | * 默认值:`/` 68 | 69 | 指定 react-router 的 base,部署到非根目录时需要配置。 70 | 71 | ### publicPath 72 | 73 | * 类型:`String` 74 | * 默认值:`/` 75 | 76 | 指定 webpack 的 publicPath,指向静态资源文件所在的路径。 77 | 78 | ### runtimePublicPath 79 | 80 | * 类型:`Boolean` 81 | * 默认值:`false` 82 | 83 | 值为 `true` 时使用 HTML 里指定的 `window.publicPath`。 84 | 85 | ### mountElementId 86 | 87 | * 类型:`String` 88 | * 默认值:`root` 89 | 90 | 指定 react app 渲染到的 HTML 元素 id。 91 | 92 | ### hash 93 | 94 | * Type: `Boolean` 95 | * Default: `false` 96 | 97 | 是否开启 hash 文件后缀。 98 | 99 | ### targets 100 | 101 | * Type: `Object` 102 | * Default: `{ chrome: 49, firefox: 45, safari: 10, edge: 13, ios: 10 }` 103 | 104 | 配置浏览器最低版本,会自动引入 polyfill 和做语法转换,配置的 targets 会和合并到默认值,所以不需要重复配置。 105 | 106 | 比如要兼容 ie11,需配置: 107 | 108 | ```js 109 | export default { 110 | targets: { 111 | ie: 11, 112 | }, 113 | }; 114 | ``` 115 | 116 | ### context 117 | 118 | * 类型:`Object` 119 | * 默认值:`{}` 120 | 121 | 配置全局 context,会覆盖到每个 pages 里的 context。 122 | 123 | ### exportStatic 124 | 125 | * 类型:`Boolean | Object` 126 | * 默认值:`false` 127 | 128 | 如果设为 `true` 或 `Object`,则导出全部路由为静态页面,否则默认只输出一个 index.html。 129 | 130 | 比如: 131 | 132 | ``` 133 | "exportStatic": {} 134 | ``` 135 | 136 | ### exportStatic.htmlSuffix 137 | 138 | * 类型:`Boolean` 139 | * 默认值:`false` 140 | 141 | 启用 `.html` 后缀。 142 | 143 | ### exportStatic.dynamicRoot 144 | 145 | * 类型:`Boolean` 146 | * 默认值:`false` 147 | 148 | 部署到任意路径。 149 | 150 | ### singular 151 | 152 | * 类型:`Boolean` 153 | * 默认值:`false` 154 | 155 | 如果设为 `true`,启用单数模式的目录。 156 | 157 | * src/layout/index.js 158 | * src/page 159 | * model(如果有开启 umi-plugin-dva 插件的话) 160 | 161 | ## webpack 162 | 163 | ### chainWebpack 164 | 165 | 通过 [webpack-chain](https://github.com/mozilla-neutrino/webpack-chain) 的 API 扩展或修改 webpack 配置。 166 | 167 | 比如: 168 | 169 | ```js 170 | chainWebpack(config, { webpack }) { 171 | // 设置 alias 172 | config.resolve.alias.set('a', 'path/to/a'); 173 | 174 | // 删除进度条插件 175 | config.plugins.delete('progress'); 176 | } 177 | ``` 178 | 179 | ### theme 180 | 181 | 配置主题,实际上是配 less 变量。支持对象和字符串两种类型,字符串需要指向一个返回配置的文件。 182 | 比如: 183 | 184 | ``` 185 | "theme": { 186 | "@primary-color": "#1DA57A" 187 | } 188 | ``` 189 | 190 | 或者, 191 | 192 | ``` 193 | "theme": "./theme-config.js" 194 | ``` 195 | 196 | ### define 197 | 198 | 通过 webpack 的 DefinePlugin 传递给代码,值会自动做 `JSON.stringify` 处理。 199 | 比如: 200 | 201 | ```js 202 | "define": { 203 | "process.env.TEST": 1, 204 | "USE_COMMA": 2, 205 | } 206 | ``` 207 | 208 | ### externals 209 | 210 | 配置 webpack 的?[externals](https://webpack.js.org/configuration/externals/)?属性。 211 | 比如: 212 | 213 | ```js 214 | // 配置 react 和 react-dom 不打入代码 215 | "externals": { 216 | "react": "window.React", 217 | "react-dom": "window.ReactDOM" 218 | } 219 | ``` 220 | 221 | ### alias 222 | 223 | 配置 webpack 的 [resolve.alias](https://webpack.js.org/configuration/resolve/#resolve-alias) 属性。 224 | 225 | ### browserslist 226 | 227 | 配置 [browserslist](https://github.com/ai/browserslist),同时作用于 babel-preset-env 和 autoprefixer。 228 | 比如: 229 | 230 | ```js 231 | "browserslist": [ 232 | "> 1%", 233 | "last 2 versions" 234 | ] 235 | ``` 236 | 237 | ### devtool 238 | 239 | 配置 webpack 的 [devtool](https://webpack.js.org/configuration/devtool/) 属性。 240 | 241 | ### disableCSSModules 242 | 243 | 禁用 [CSS Modules](https://github.com/css-modules/css-modules)。 244 | 245 | ### disableCSSSourceMap 246 | 247 | 禁用 CSS 的 SourceMap 生成。 248 | 249 | ### extraBabelPresets 250 | 251 | 定义额外的 babel preset 列表,格式为数组。 252 | 253 | ### extraBabelPlugins 254 | 255 | 定义额外的 babel plugin 列表,格式为数组。 256 | 257 | ### extraBabelIncludes 258 | 259 | 定义额外需要做 babel 转换的文件匹配列表,格式为数组,数组项是 [webpack#Condition](https://webpack.js.org/configuration/module/#condition)。 260 | 261 | ### extraPostCSSPlugins 262 | 263 | 定义额外的 PostCSS 插件,格式为数组。 264 | 265 | ### cssModulesExcludes 266 | 267 | 指定项目目录下的文件不走 css modules,格式为数组,项必须是 css 或 less 文件。 268 | 269 | ### copy 270 | 271 | 定义需要单纯做复制的文件列表,格式为数组,项的格式参考 [copy-webpack-plugin](https://github.com/webpack-contrib/copy-webpack-plugin) 的配置。 272 | 273 | 比如: 274 | 275 | ```markup 276 | "copy": [ 277 | { 278 | "from": "", 279 | "to": "" 280 | } 281 | ] 282 | ``` 283 | 284 | ### proxy 285 | 286 | 配置 webpack-dev-server 的 [proxy](https://webpack.js.org/configuration/dev-server/#devserver-proxy) 属性。 287 | 如果要代理请求到其他服务器,可以这样配: 288 | 289 | ```markup 290 | "proxy": { 291 | "/api": { 292 | "target": "http://jsonplaceholder.typicode.com/", 293 | "changeOrigin": true, 294 | "pathRewrite": { "^/api" : "" } 295 | } 296 | } 297 | ``` 298 | 299 | 然后访问?`/api/users`?就能访问到?[http://jsonplaceholder.typicode.com/users](http://jsonplaceholder.typicode.com/users)?的数据。 300 | 301 | ### sass 302 | 303 | 配置 [node-sass](https://github.com/sass/node-sass#options) 的选项。注意:使用 sass 时需在项目目录安装 node-sass 和 sass-loader 依赖。 304 | 305 | ### manifest 306 | 307 | 配置后会生成 manifest.json,option 传给 [https://www.npmjs.com/package/webpack-manifest-plugin](https://www.npmjs.com/package/webpack-manifest-plugin)。 308 | 比如: 309 | 310 | ```markup 311 | "manifest": { 312 | "basePath": "/app/" 313 | } 314 | ``` 315 | 316 | ### ignoreMomentLocale 317 | 318 | 忽略 moment 的 locale 文件,用于减少尺寸。 319 | 320 | ### lessLoaderOptions 321 | 322 | 给 [less-loader](https://github.com/webpack-contrib/less-loader) 的额外配置项。 323 | 324 | ### cssLoaderOptions 325 | 326 | 给 [css-loader](https://github.com/webpack-contrib/css-loader) 的额外配置项。 327 | -------------------------------------------------------------------------------- /docs/zh/guide/router.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebarDepth: 3 3 | --- 4 | 5 | # 路由 6 | 7 | ::: tip 提示 8 | 下文介绍的路由使用可以在 [umi-examples/routes](https://github.com/umijs/umi-examples/tree/master/routes) 和 [umi-examples/routes-via-config](https://github.com/umijs/umi-examples/tree/master/routes-via-config) 里找到示例代码。 9 | ::: 10 | 11 | umi 会根据 `pages` 目录自动生成路由配置。 12 | 13 | ## 约定式路由 14 | 15 | ### 基础路由 16 | 17 | 假设 `pages` 目录结构如下: 18 | 19 | ``` 20 | + pages/ 21 | + users/ 22 | - index.js 23 | - list.js 24 | - index.js 25 | ``` 26 | 27 | 那么,umi 会自动生成路由配置如下: 28 | 29 | ```js 30 | [ 31 | { path: '/', component: './pages/index.js' }, 32 | { path: '/users/', component: './pages/users/index.js' }, 33 | { path: '/users/list', component: './pages/users/list.js' }, 34 | ] 35 | ``` 36 | 37 | ### 动态路由 38 | 39 | umi 里约定,带 `$` 前缀的目录或文件为动态路由。 40 | 41 | 比如以下目录结构: 42 | 43 | ``` 44 | + pages/ 45 | + $post/ 46 | - index.js 47 | - comments.js 48 | + users/ 49 | $id.js 50 | - index.js 51 | ``` 52 | 53 | 会生成路由配置如下: 54 | 55 | ```js 56 | [ 57 | { path: '/', component: './pages/index.js' }, 58 | { path: '/users/:id', component: './pages/users/$id.js' }, 59 | { path: '/:post/', component: './pages/$post/index.js' }, 60 | { path: '/:post/comments', component: './pages/$post/comments.js' }, 61 | ] 62 | ``` 63 | 64 | ### 可选的动态路由 65 | 66 | umi 里约定动态路由如果带 `$` 后缀,则为可选动态路由。 67 | 68 | 比如以下结构: 69 | 70 | ``` 71 | + pages/ 72 | + users/ 73 | - $id$.js 74 | - index.js 75 | ``` 76 | 77 | 会生成路由配置如下: 78 | 79 | ```js 80 | [ 81 | { path: '/': component: './pages/index.js' }, 82 | { path: '/users/:id?': component: './pages/users/$id$.js' }, 83 | ] 84 | ``` 85 | 86 | ### 嵌套路由 87 | 88 | umi 里约定目录下有 `_layout.js` 时会生成嵌套路由,以 `_layout.js` 为该目录的 layout 。 89 | 90 | 比如以下目录结构: 91 | 92 | ``` 93 | + pages/ 94 | + users/ 95 | - _layout.js 96 | - $id.js 97 | - index.js 98 | ``` 99 | 100 | 会生成路由配置如下: 101 | 102 | ```js 103 | [ 104 | { path: '/users': component: './pages/users/_layout.js' 105 | routes: [ 106 | { path: '/users/', component: './pages/users/index.js' }, 107 | { path: '/users/:id', component: './pages/users/$id.js' }, 108 | ], 109 | }, 110 | ] 111 | ``` 112 | 113 | ### 全局 layout 114 | 115 | 约定 `src/layouts/index.js` 为全局路由,返回一个 React 组件,通过 `props.children` 渲染子组件。 116 | 117 | 比如: 118 | 119 | ```js 120 | export default function(props) { 121 | return ( 122 | <> 123 |
    124 | { props.children } 125 |