├── packages
├── main
│ ├── package.json
│ ├── pages
│ │ └── index
│ │ │ ├── index.css
│ │ │ ├── model.js
│ │ │ └── index.js
│ ├── public
│ │ └── users.css
│ ├── layouts
│ │ └── index.js
│ └── .umirc.js
└── users
│ ├── package.json
│ ├── pages
│ └── users
│ │ ├── index.css
│ │ ├── model.js
│ │ └── index.js
│ └── .umirc.js
├── README.md
├── .gitignore
├── package.json
└── plugins
├── main
├── app.js
└── index.js
└── sub.js
/packages/main/package.json:
--------------------------------------------------------------------------------
1 | {
2 | }
3 |
--------------------------------------------------------------------------------
/packages/users/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "users"
3 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/umijs/umi-example-monorepo/HEAD/README.md
--------------------------------------------------------------------------------
/packages/main/pages/index/index.css:
--------------------------------------------------------------------------------
1 |
2 | .normal {
3 | background: #79C0F2;
4 | }
5 |
--------------------------------------------------------------------------------
/packages/users/pages/users/index.css:
--------------------------------------------------------------------------------
1 |
2 | .normal {
3 | background: #F2E679;
4 | }
5 |
--------------------------------------------------------------------------------
/packages/main/public/users.css:
--------------------------------------------------------------------------------
1 |
2 | .normal___d4l2S {
3 | background: #F2E679;
4 | }
5 |
6 |
--------------------------------------------------------------------------------
/packages/main/pages/index/model.js:
--------------------------------------------------------------------------------
1 |
2 | export default {
3 | namespace: 'index',
4 | state: {
5 | title: 'index page',
6 | },
7 | }
8 |
--------------------------------------------------------------------------------
/packages/users/pages/users/model.js:
--------------------------------------------------------------------------------
1 |
2 | export default {
3 | namespace: 'users',
4 | state: {
5 | data: [
6 | 'chencheng',
7 | 'pigcan',
8 | ],
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # yarn
2 | yarn.lock
3 |
4 | # npm
5 | node_modules
6 | package-lock.json
7 |
8 | # umi
9 | .umi
10 | .umi-production
11 | dist
12 |
13 | /packages/main/public/users.js
14 |
15 |
--------------------------------------------------------------------------------
/packages/main/layouts/index.js:
--------------------------------------------------------------------------------
1 |
2 | export default (props) => {
3 | return (
4 | <>
5 |
layouts
6 | {
7 | props.children
8 | }
9 | >
10 | )
11 | }
12 |
--------------------------------------------------------------------------------
/packages/users/.umirc.js:
--------------------------------------------------------------------------------
1 |
2 | export default {
3 | plugins: [
4 | ['umi-plugin-react', {
5 | dva: true,
6 | routes: {
7 | exclude: [
8 | /model/,
9 | ],
10 | },
11 | }],
12 | '../../plugins/sub',
13 | ],
14 | }
15 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "scripts": {
3 | "start": "APP_ROOT=packages/main umi dev",
4 | "users:build": "COMPRESS=none APP_ROOT=packages/users umi build && cp packages/users/dist/* packages/main/public"
5 | },
6 | "devDependencies": {
7 | "globby": "^7.1.1",
8 | "umi": "^2.4.2",
9 | "umi-plugin-react": "^1.4.0"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/packages/main/.umirc.js:
--------------------------------------------------------------------------------
1 |
2 | export default {
3 | history: 'hash',
4 | plugins: [
5 | ['umi-plugin-react', {
6 | dva: true,
7 | routes: {
8 | exclude: [
9 | /model/,
10 | ],
11 | },
12 | }],
13 | ['../../plugins/main', {
14 | scripts: [
15 | '/users.js',
16 | ],
17 | stylesheets: [
18 | '/users.css'
19 | ],
20 | }],
21 | ],
22 | }
23 |
--------------------------------------------------------------------------------
/packages/main/pages/index/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'dva';
2 | import Link from 'umi/link';
3 | import styles from './index.css';
4 |
5 | export default connect(
6 | state => ({ index: state.index })
7 | )(function(props) {
8 | return (
9 |
10 |
{ props.index.title }
11 |
14 |
15 | );
16 | });
17 |
--------------------------------------------------------------------------------
/plugins/main/app.js:
--------------------------------------------------------------------------------
1 |
2 | export function patchRoutes(routes) {
3 | (window.g_umi && window.g_umi.monorepo || []).forEach((repo) => {
4 | repo.routes.forEach(route => {
5 | // add routes under first layout
6 | routes[0].routes.unshift(route);
7 | });
8 | (repo.models || []).forEach(model => {
9 | window.g_app.model(model);
10 | });
11 | });
12 | window.g_routes = routes;
13 | }
14 |
15 | export function render(oldRender) {
16 | console.log('patch render');
17 | oldRender();
18 | }
19 |
--------------------------------------------------------------------------------
/packages/users/pages/users/index.js:
--------------------------------------------------------------------------------
1 | import Link from 'umi/link';
2 | import { connect } from 'dva';
3 | import styles from './index.css';
4 |
5 | export default connect(state => ({
6 | users: state.users,
7 | }))(function(props) {
8 | return (
9 |
10 |
Page users
11 |
go to /
12 |
Users
13 |
14 | {
15 | props.users.data.map((value, i) => {
16 | return (
17 | - {value}
18 | );
19 | })
20 | }
21 |
22 |
23 | );
24 | });
25 |
--------------------------------------------------------------------------------
/plugins/main/index.js:
--------------------------------------------------------------------------------
1 | import { join } from 'path';
2 |
3 | export default (api, options = {}) => {
4 | api.chainWebpackConfig(config => {
5 | config.externals({
6 | 'react': 'window.React',
7 | 'react-dom': 'window.ReactDOM',
8 | 'dva': 'window.dva',
9 | });
10 | });
11 |
12 | api.addHTMLHeadScript(() => {
13 | const scripts = (options.scripts || []).map(sub => {
14 | return { src: sub };
15 | });
16 | return [
17 | { src: 'https://unpkg.com/react@16.7.0-alpha.2/umd/react.development.js' },
18 | { src: 'https://unpkg.com/react-dom@16.7.0-alpha.2/umd/react-dom.development.js' },
19 | { src: 'https://unpkg.com/dva@2.4.1/dist/dva.min.js' },
20 | ...scripts,
21 | ];
22 | });
23 |
24 | api.addHTMLLink(() => {
25 | return (options.stylesheets || []).map(sub => {
26 | return { href: sub, rel: 'stylesheet' };
27 | });
28 | });
29 |
30 | api.addRuntimePlugin(
31 | join(__dirname, 'app.js'),
32 | );
33 | }
34 |
--------------------------------------------------------------------------------
/plugins/sub.js:
--------------------------------------------------------------------------------
1 | import assert from 'assert';
2 | import { join, relative } from 'path';
3 | import globby from 'globby';
4 |
5 | export default (api) => {
6 | const { cwd, paths, winPath } = api;
7 | const isDev = process.env.NODE_ENV === 'development';
8 |
9 | if (isDev) return;
10 | assert(api.pkg.name, `package.json must contains a name property`);
11 |
12 | function routesToJSON(routes) {
13 | return JSON.stringify(routes, (key, value) => {
14 | switch (key) {
15 | case 'component':
16 | const relPath = winPath(relative(paths.absTmpDirPath, join(cwd, value)))
17 | return `require('${relPath}').default`;
18 | default:
19 | return value;
20 | }
21 | }, 2);
22 | }
23 |
24 | function stripJSONQuotes(str) {
25 | return str
26 | .replace(/\"component\": (\"(.+?)\")/g, (global, m1, m2) => {
27 | return `"component": ${m2.replace(/\^/g, '"')}`;
28 | });
29 | }
30 |
31 | function findModels() {
32 | const models = [
33 | ...(globby.sync('**/models/**/*.js', {
34 | cwd: paths.absPagesPath,
35 | })),
36 | ...(globby.sync('**/model.js', {
37 | cwd: paths.absPagesPath,
38 | })),
39 | ];
40 | return models;
41 | }
42 |
43 | api.onStart(() => {
44 | process.env.HTML = 'none';
45 | });
46 |
47 | api.onGenerateFiles(() => {
48 | const routes = api.routes;
49 | const routesContent = stripJSONQuotes(routesToJSON(routes));
50 | const models = findModels().map(model => {
51 | return `require('../../${model}').default`;
52 | });
53 | const content = `
54 | window.g_umi = window.g_umi || {};
55 | window.g_umi.monorepo = window.g_umi.monorepo = [];
56 | window.g_umi.monorepo.push({
57 | routes: ${routesContent},
58 | models: [${models.join(',')}],
59 | });
60 | `.trim();
61 | api.writeTmpFile('submodule.js', content);
62 | });
63 |
64 | api.chainWebpackConfig(config => {
65 | config.entryPoints.clear();
66 | config.entry(api.pkg.name).add(
67 | join(api.paths.absTmpDirPath, 'submodule.js'),
68 | );
69 | config.externals({
70 | 'react': 'window.React',
71 | 'react-dom': 'window.ReactDOM',
72 | 'dva': 'window.dva',
73 | });
74 | });
75 | }
76 |
--------------------------------------------------------------------------------