├── 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 | 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 | --------------------------------------------------------------------------------