From 798ba6969c3d3ab4a5a707ce39441c174c883c22 Mon Sep 17 00:00:00 2001 From: ycjcl868 <45808948@qq.com> Date: Wed, 2 Oct 2019 17:27:11 +0800 Subject: [PATCH 1/4] fix: dynamicImport getInitialProps can't work in ssr --- packages/umi-plugin-dva/src/index.js | 17 +++++++++++++++++ .../src/plugins/dynamicImport.js | 2 +- packages/umi/src/dynamic.js | 4 ++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/packages/umi-plugin-dva/src/index.js b/packages/umi-plugin-dva/src/index.js index 504c27d671a9..18195cc9281d 100644 --- a/packages/umi-plugin-dva/src/index.js +++ b/packages/umi-plugin-dva/src/index.js @@ -232,6 +232,23 @@ app.use(require('${winPath(require.resolve('dva-immer'))}')()); }) : require('${importPath}').default `.trim(); + // ssr in browser will attach getInitialProps into Dynamic Component + // TODO: dva/dymaic should support config pass down + if (api.config.ssr) { + ret = `(() => { + if (__IS_BROWSER) { + const cp = _dvaDynamic({ + <%= MODELS %> + component: () => import(${extendStr}'${importPath}'), + ${loadingOpts} + }); + // attach + cp.getInitialProps = require('${importPath}').default && require('${importPath}').default.getInitialProps; + return cp; + } + return require('${importPath}').default + })()`.trim(); + } const models = getPageModels(join(paths.absTmpDirPath, importPath), api); if (models && models.length) { ret = ret.replace( diff --git a/packages/umi-plugin-react/src/plugins/dynamicImport.js b/packages/umi-plugin-react/src/plugins/dynamicImport.js index 6efc5b58be14..e24c0c962232 100644 --- a/packages/umi-plugin-react/src/plugins/dynamicImport.js +++ b/packages/umi-plugin-react/src/plugins/dynamicImport.js @@ -36,6 +36,6 @@ export default function(api, options) { if (options.webpackChunkName) { extendStr = `/* webpackChunkName: ^${webpackChunkName}^ */`; } - return `__IS_BROWSER ? dynamic({ loader: () => import(${extendStr}'${importPath}')${loadingOpts} }) : require('${importPath}').default`; + return `__IS_BROWSER ? dynamic({ loader: () => import(${extendStr}'${importPath}')${loadingOpts}, getInitialProps: require('${importPath}').default && require('${importPath}').default.getInitialProps }) : require('${importPath}').default`; }); } diff --git a/packages/umi/src/dynamic.js b/packages/umi/src/dynamic.js index b4a47e83f38b..a40a93cea9d6 100644 --- a/packages/umi/src/dynamic.js +++ b/packages/umi/src/dynamic.js @@ -62,5 +62,9 @@ export default function(dynamicOptions, options) { loadableOptions.loader = loadModules; } + if (loadableOptions.getInitialProps) { + loadableFn.getInitialProps = loadableOptions.getInitialProps; + } + return loadableFn(loadableOptions); } From 65842cd6302e3b28ca04e05f4e49ade6f247afbc Mon Sep 17 00:00:00 2001 From: ycjcl868 <45808948@qq.com> Date: Wed, 2 Oct 2019 18:07:32 +0800 Subject: [PATCH 2/4] test: ci --- packages/umi-plugin-dva/src/index.js | 17 ----- packages/umi/test/dev.e2e.js | 75 +++++++++++++++++++ .../fixtures/dev/ssr-dynamicImport/.umirc.js | 12 +++ .../dev/ssr-dynamicImport/models/count.js | 17 +++++ .../dev/ssr-dynamicImport/pages/index.js | 26 +++++++ .../dev/ssr-dynamicImport/pages/news.js | 23 ++++++ scripts/startDevServers.js | 1 + 7 files changed, 154 insertions(+), 17 deletions(-) create mode 100644 packages/umi/test/fixtures/dev/ssr-dynamicImport/.umirc.js create mode 100644 packages/umi/test/fixtures/dev/ssr-dynamicImport/models/count.js create mode 100644 packages/umi/test/fixtures/dev/ssr-dynamicImport/pages/index.js create mode 100644 packages/umi/test/fixtures/dev/ssr-dynamicImport/pages/news.js diff --git a/packages/umi-plugin-dva/src/index.js b/packages/umi-plugin-dva/src/index.js index 18195cc9281d..504c27d671a9 100644 --- a/packages/umi-plugin-dva/src/index.js +++ b/packages/umi-plugin-dva/src/index.js @@ -232,23 +232,6 @@ app.use(require('${winPath(require.resolve('dva-immer'))}')()); }) : require('${importPath}').default `.trim(); - // ssr in browser will attach getInitialProps into Dynamic Component - // TODO: dva/dymaic should support config pass down - if (api.config.ssr) { - ret = `(() => { - if (__IS_BROWSER) { - const cp = _dvaDynamic({ - <%= MODELS %> - component: () => import(${extendStr}'${importPath}'), - ${loadingOpts} - }); - // attach - cp.getInitialProps = require('${importPath}').default && require('${importPath}').default.getInitialProps; - return cp; - } - return require('${importPath}').default - })()`.trim(); - } const models = getPageModels(join(paths.absTmpDirPath, importPath), api); if (models && models.length) { ret = ret.replace( diff --git a/packages/umi/test/dev.e2e.js b/packages/umi/test/dev.e2e.js index cb98b5a1fa26..f2ab43348a96 100644 --- a/packages/umi/test/dev.e2e.js +++ b/packages/umi/test/dev.e2e.js @@ -278,4 +278,79 @@ describe('ssr', () => { ); }); }); + + describe('ssr dynamicImport', () => { + const dynamicImportPort = 12344; + beforeEach(async () => { + // TODO: maybe using umi/server, reset global + global.window = {}; + }); + + it('routes', async () => { + const ssrFile = join( + winPath(__dirname), + 'fixtures', + 'dev', + 'ssr-dynamicImport', + 'dist', + 'umi.server.js', + ); + const manifestFile = join( + winPath(__dirname), + 'fixtures', + 'dev', + 'ssr-dynamicImport', + 'dist', + 'ssr-client-mainifest.json', + ); + expect(existsSync(ssrFile)).toBeTruthy(); + expect(existsSync(manifestFile)).toBeTruthy(); + + const serverRender = require('./fixtures/dev/ssr-dynamicImport/dist/umi.server'); + const manifest = require('./fixtures/dev/ssr-dynamicImport/dist/ssr-client-mainifest.json'); + // export react-dom/server to avoid React hooks ssr error + const { ReactDOMServer } = serverRender; + + expect(manifest).toEqual({ + '/': { + js: ['umi.js'], + css: ['umi.css'], + }, + '/news': { + js: ['umi.js'], + css: ['umi.css'], + }, + __404: { + js: ['umi.js'], + css: ['umi.css'], + }, + }); + + const ctx = { + req: { + url: '/', + }, + }; + + const { rootContainer } = await serverRender.default(ctx); + const ssrHtml = ReactDOMServer.renderToString(rootContainer); + + expect(ssrHtml).toEqual( + '

Hello UmiJS SSR Styles

', + ); + + const ctx2 = { + req: { + url: '/news', + }, + }; + + const { rootContainer: rootContainerNews } = await serverRender.default(ctx2); + const ssrHtmlNews = ReactDOMServer.renderToString(rootContainerNews); + + expect(ssrHtmlNews).toContain( + '

Hello UmiJS SSR Styles

', + ); + }); + }); }); diff --git a/packages/umi/test/fixtures/dev/ssr-dynamicImport/.umirc.js b/packages/umi/test/fixtures/dev/ssr-dynamicImport/.umirc.js new file mode 100644 index 000000000000..eb79e8641a13 --- /dev/null +++ b/packages/umi/test/fixtures/dev/ssr-dynamicImport/.umirc.js @@ -0,0 +1,12 @@ + +export default { + ssr: true, + plugins: [ + ['../../../../../umi-plugin-react/lib/index.js', { + dva: true, + dynamicImport: { + webpackChunkName: true, + }, + }], + ] +} diff --git a/packages/umi/test/fixtures/dev/ssr-dynamicImport/models/count.js b/packages/umi/test/fixtures/dev/ssr-dynamicImport/models/count.js new file mode 100644 index 000000000000..de2addba5dbf --- /dev/null +++ b/packages/umi/test/fixtures/dev/ssr-dynamicImport/models/count.js @@ -0,0 +1,17 @@ +export default { + state: 0, + reducers: { + add(state) { + return state + 1; + }, + reset(state) { + return 0; + } + }, + effects: { + *init({ type, payload }, { put, call, select }) { + yield put({ type: 'add' }); + yield put({ type: 'add' }); + }, + }, +} diff --git a/packages/umi/test/fixtures/dev/ssr-dynamicImport/pages/index.js b/packages/umi/test/fixtures/dev/ssr-dynamicImport/pages/index.js new file mode 100644 index 000000000000..c2139d01d8c0 --- /dev/null +++ b/packages/umi/test/fixtures/dev/ssr-dynamicImport/pages/index.js @@ -0,0 +1,26 @@ +import { connect } from 'dva'; + +function App(props) { + return ( +
+

count: {props.count}

+ +
+ ); +} + +App.getInitialProps = async ({ store, route, isServer }) => { + console.log('Count getInitialProps', store, route, isServer); + await store.dispatch({ + type: 'count/reset', + }); + await store.dispatch({ + type: 'count/init', + }); +}; + +export default connect(state => { + return { count: state.count }; +})(App); diff --git a/packages/umi/test/fixtures/dev/ssr-dynamicImport/pages/news.js b/packages/umi/test/fixtures/dev/ssr-dynamicImport/pages/news.js new file mode 100644 index 000000000000..b212fb9a8186 --- /dev/null +++ b/packages/umi/test/fixtures/dev/ssr-dynamicImport/pages/news.js @@ -0,0 +1,23 @@ +import { useEffect, useState } from 'react'; + +function Page(props) { + const { list } = props; + return ( +
+

Page users

+

users

+ +
+ ); +} + +Page.getInitialProps = async () => { + console.log('Users getInitialProps'); + return Promise.resolve({ + list: ['foo', 'bar'], + }); +}; + +export default Page; diff --git a/scripts/startDevServers.js b/scripts/startDevServers.js index cbe886aa84e2..0a831fe6785b 100644 --- a/scripts/startDevServers.js +++ b/scripts/startDevServers.js @@ -30,6 +30,7 @@ function start() { [12341, '../packages/umi/test/fixtures/dev/normal'], [12342, '../packages/umi/test/fixtures/dev/ssr'], [12343, '../packages/umi/test/fixtures/dev/ssr-styles'], + [12344, '../packages/umi/test/fixtures/dev/ssr-dynamicImport'], ].map(([port, cwd]) => { return startDevServer({ port, cwd: join(__dirname, cwd) }); }); From e75416511c4eab7b970fd7c2ee1fbd3151abb90a Mon Sep 17 00:00:00 2001 From: ycjcl868 <45808948@qq.com> Date: Wed, 2 Oct 2019 18:08:45 +0800 Subject: [PATCH 3/4] fix: return --- packages/umi-plugin-react/src/plugins/dynamicImport.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/umi-plugin-react/src/plugins/dynamicImport.js b/packages/umi-plugin-react/src/plugins/dynamicImport.js index e24c0c962232..6efc5b58be14 100644 --- a/packages/umi-plugin-react/src/plugins/dynamicImport.js +++ b/packages/umi-plugin-react/src/plugins/dynamicImport.js @@ -36,6 +36,6 @@ export default function(api, options) { if (options.webpackChunkName) { extendStr = `/* webpackChunkName: ^${webpackChunkName}^ */`; } - return `__IS_BROWSER ? dynamic({ loader: () => import(${extendStr}'${importPath}')${loadingOpts}, getInitialProps: require('${importPath}').default && require('${importPath}').default.getInitialProps }) : require('${importPath}').default`; + return `__IS_BROWSER ? dynamic({ loader: () => import(${extendStr}'${importPath}')${loadingOpts} }) : require('${importPath}').default`; }); } From 1d2821b152c1bee5bb208a10ba6a21f27e41cf75 Mon Sep 17 00:00:00 2001 From: ycjcl868 <45808948@qq.com> Date: Thu, 3 Oct 2019 17:09:27 +0800 Subject: [PATCH 4/4] fix: ssr dynamic import support --- packages/umi/package.json | 2 +- packages/umi/src/dynamic.js | 4 +- .../fixtures/dev/ssr-dynamicImport/.umirc.js | 2 +- .../dev/ssr-dynamicImport/pages/index.js | 19 +- .../dev/ssr-dynamicImport/pages/news.js | 4 +- packages/umi/yarn.lock | 14545 +++++++++++++++- 6 files changed, 13813 insertions(+), 763 deletions(-) diff --git a/packages/umi/package.json b/packages/umi/package.json index 19db963dd735..fcfec050890b 100644 --- a/packages/umi/package.json +++ b/packages/umi/package.json @@ -12,7 +12,7 @@ "dotenv": "8.0.0", "is-windows": "1.0.2", "lodash": "4.17.13", - "react-loadable": "5.5.0", + "@umijs/react-loadable": "~1.0.0", "resolve-cwd": "3.0.0", "semver": "6.1.1", "signale": "1.4.0", diff --git a/packages/umi/src/dynamic.js b/packages/umi/src/dynamic.js index a40a93cea9d6..23828cbd01ba 100644 --- a/packages/umi/src/dynamic.js +++ b/packages/umi/src/dynamic.js @@ -1,8 +1,8 @@ import React from 'react'; -import Loadable from 'react-loadable'; +import Loadable from '@umijs/react-loadable'; // Thanks to next.js -// ref: https://github.com/zeit/next.js/blob/canary/lib/dynamic.js +// ref: https://github.com/zeit/next.js/blob/a73fb5d04a90f03ec5b53225ffa19e84f9c7ab14/packages/next/next-server/lib/dynamic.tsx export default function(dynamicOptions, options) { let loadableFn = Loadable; let loadableOptions = { diff --git a/packages/umi/test/fixtures/dev/ssr-dynamicImport/.umirc.js b/packages/umi/test/fixtures/dev/ssr-dynamicImport/.umirc.js index eb79e8641a13..349be86fbd67 100644 --- a/packages/umi/test/fixtures/dev/ssr-dynamicImport/.umirc.js +++ b/packages/umi/test/fixtures/dev/ssr-dynamicImport/.umirc.js @@ -3,7 +3,7 @@ export default { ssr: true, plugins: [ ['../../../../../umi-plugin-react/lib/index.js', { - dva: true, + dva: false, dynamicImport: { webpackChunkName: true, }, diff --git a/packages/umi/test/fixtures/dev/ssr-dynamicImport/pages/index.js b/packages/umi/test/fixtures/dev/ssr-dynamicImport/pages/index.js index c2139d01d8c0..8045cd093b7d 100644 --- a/packages/umi/test/fixtures/dev/ssr-dynamicImport/pages/index.js +++ b/packages/umi/test/fixtures/dev/ssr-dynamicImport/pages/index.js @@ -1,26 +1,19 @@ -import { connect } from 'dva'; +import { Link } from 'umi'; function App(props) { return (
+ news

count: {props.count}

-
); } App.getInitialProps = async ({ store, route, isServer }) => { - console.log('Count getInitialProps', store, route, isServer); - await store.dispatch({ - type: 'count/reset', - }); - await store.dispatch({ - type: 'count/init', + console.log('Index getInitialProps'); + return Promise.resolve({ + count: 0, }); }; -export default connect(state => { - return { count: state.count }; -})(App); +export default App; diff --git a/packages/umi/test/fixtures/dev/ssr-dynamicImport/pages/news.js b/packages/umi/test/fixtures/dev/ssr-dynamicImport/pages/news.js index b212fb9a8186..17de1a381eac 100644 --- a/packages/umi/test/fixtures/dev/ssr-dynamicImport/pages/news.js +++ b/packages/umi/test/fixtures/dev/ssr-dynamicImport/pages/news.js @@ -1,9 +1,11 @@ import { useEffect, useState } from 'react'; +import { Link } from 'umi'; function Page(props) { const { list } = props; return ( -
+
+ index

Page users

users