Commit 24f98bb57160390272b4fc1a4a28de08d37f4abd
1 parent
6ac81823
chore: upgrade landing-page dependencies
Showing
3 changed files
with
122 additions
and
45 deletions
Too many changes to show.
To preserve performance only 3 of 4 files are displayed.
front-end/landing-page/src/pages/.umi/router.js
| 1 | 1 | import React from 'react'; |
| 2 | -import { Router as DefaultRouter, Route, Switch } from 'react-router-dom'; | |
| 2 | +import { | |
| 3 | + Router as DefaultRouter, | |
| 4 | + Route, | |
| 5 | + Switch, | |
| 6 | + StaticRouter, | |
| 7 | +} from 'react-router-dom'; | |
| 3 | 8 | import dynamic from 'umi/dynamic'; |
| 4 | 9 | import renderRoutes from 'umi/lib/renderRoutes'; |
| 5 | -import history from '@tmp/history'; | |
| 10 | +import history from '@@/history'; | |
| 6 | 11 | |
| 7 | 12 | const Router = DefaultRouter; |
| 8 | 13 | |
| ... | ... | @@ -68,7 +73,15 @@ export default class RouterWrapper extends React.Component { |
| 68 | 73 | }); |
| 69 | 74 | } |
| 70 | 75 | this.unListen = history.listen(routeChangeHandler); |
| 71 | - routeChangeHandler(history.location); | |
| 76 | + // dva 中 history.listen 会初始执行一次 | |
| 77 | + // 这里排除掉 dva 的场景,可以避免 onRouteChange 在启用 dva 后的初始加载时被多执行一次 | |
| 78 | + const isDva = | |
| 79 | + history.listen | |
| 80 | + .toString() | |
| 81 | + .indexOf('callback(history.location, history.action)') > -1; | |
| 82 | + if (!isDva) { | |
| 83 | + routeChangeHandler(history.location); | |
| 84 | + } | |
| 72 | 85 | } |
| 73 | 86 | |
| 74 | 87 | componentWillUnmount() { | ... | ... |
front-end/landing-page/src/pages/.umi/umi.js
| ... | ... | @@ -32,7 +32,7 @@ let clientRender = async () => { |
| 32 | 32 | props = window.g_initialData; |
| 33 | 33 | } else { |
| 34 | 34 | const pathname = location.pathname; |
| 35 | - const activeRoute = findRoute(require('@tmp/router').routes, pathname); | |
| 35 | + const activeRoute = findRoute(require('@@/router').routes, pathname); | |
| 36 | 36 | // 在客户端渲染前,执行 getInitialProps 方法 |
| 37 | 37 | // 拿到初始数据 |
| 38 | 38 | if ( |
| ... | ... | @@ -81,58 +81,122 @@ if (__IS_BROWSER) { |
| 81 | 81 | // export server render |
| 82 | 82 | let serverRender, ReactDOMServer; |
| 83 | 83 | if (!__IS_BROWSER) { |
| 84 | + const { matchRoutes } = require('react-router-config'); | |
| 85 | + const { StaticRouter } = require('react-router'); | |
| 86 | + // difference: umi-history has query object | |
| 87 | + const { createLocation } = require('umi-history'); | |
| 88 | + // don't remove, use stringify html map | |
| 89 | + const stringify = require('serialize-javascript'); | |
| 90 | + const router = require('./router'); | |
| 91 | + | |
| 92 | + /** | |
| 93 | + * 1. Load dynamicImport Component | |
| 94 | + * 2. Get Component initialProps function data | |
| 95 | + * return Component props | |
| 96 | + * @param pathname | |
| 97 | + * @param props | |
| 98 | + */ | |
| 99 | + const getInitialProps = async (pathname, props) => { | |
| 100 | + const { routes } = router; | |
| 101 | + const matchedComponents = matchRoutes(routes, pathname) | |
| 102 | + .map(({ route }) => { | |
| 103 | + if (route.component) { | |
| 104 | + return !route.component.preload | |
| 105 | + ? // 同步 | |
| 106 | + route.component | |
| 107 | + : // 异步,支持 dynamicImport | |
| 108 | + route.component.preload().then(component => component.default); | |
| 109 | + } | |
| 110 | + }) | |
| 111 | + .filter(c => c); | |
| 112 | + const loadedComponents = await Promise.all(matchedComponents); | |
| 113 | + | |
| 114 | + // get Store | |
| 115 | + const initialProps = plugins.apply('modifyInitialProps', { | |
| 116 | + initialValue: {}, | |
| 117 | + }); | |
| 118 | + // support getInitialProps | |
| 119 | + const promises = loadedComponents.map(component => { | |
| 120 | + if (component && component.getInitialProps) { | |
| 121 | + return component.getInitialProps({ | |
| 122 | + isServer: true, | |
| 123 | + ...props, | |
| 124 | + ...initialProps, | |
| 125 | + }); | |
| 126 | + } | |
| 127 | + return Promise.resolve(null); | |
| 128 | + }); | |
| 129 | + | |
| 130 | + return Promise.all(promises); | |
| 131 | + }; | |
| 132 | + | |
| 84 | 133 | serverRender = async (ctx = {}) => { |
| 85 | 134 | // ctx.req.url may be `/bar?locale=en-US` |
| 86 | 135 | const [pathname] = (ctx.req.url || '').split('?'); |
| 87 | - const history = require('@tmp/history').default; | |
| 88 | - history.push(ctx.req.url); | |
| 89 | - let props = {}; | |
| 90 | - const activeRoute = | |
| 91 | - findRoute(require('./router').routes, pathname) || false; | |
| 92 | - if ( | |
| 93 | - activeRoute && | |
| 94 | - activeRoute.component && | |
| 95 | - activeRoute.component.getInitialProps | |
| 96 | - ) { | |
| 97 | - const initialProps = plugins.apply('modifyInitialProps', { | |
| 98 | - initialValue: {}, | |
| 99 | - }); | |
| 100 | - // patch query object | |
| 101 | - const location = history.location | |
| 102 | - ? { ...history.location, query: getUrlQuery(history.location.search) } | |
| 103 | - : {}; | |
| 104 | - props = await activeRoute.component.getInitialProps({ | |
| 105 | - route: activeRoute, | |
| 106 | - isServer: true, | |
| 107 | - location, | |
| 108 | - // only exist in server | |
| 109 | - req: ctx.req || {}, | |
| 110 | - res: ctx.res || {}, | |
| 111 | - ...initialProps, | |
| 112 | - }); | |
| 113 | - props = plugins.apply('initialProps', { | |
| 114 | - initialValue: props, | |
| 136 | + // global | |
| 137 | + global.req = { | |
| 138 | + url: ctx.req.url, | |
| 139 | + }; | |
| 140 | + const location = createLocation(ctx.req.url); | |
| 141 | + const activeRoute = findRoute(router.routes, pathname); | |
| 142 | + // omit component | |
| 143 | + const { component, ...restRoute } = activeRoute || {}; | |
| 144 | + // router context hook | |
| 145 | + // get current router status 40x / 30x, share with server | |
| 146 | + const context = {}; | |
| 147 | + // TODO: getInitialProps timeout handle | |
| 148 | + const initialData = await getInitialProps(pathname, { | |
| 149 | + route: restRoute, | |
| 150 | + // only exist in server | |
| 151 | + req: ctx.req || {}, | |
| 152 | + res: ctx.res || {}, | |
| 153 | + context, | |
| 154 | + location, | |
| 155 | + }); | |
| 156 | + | |
| 157 | + // 当前路由(不包含 Layout)的 getInitialProps 有返回值 | |
| 158 | + // Page 值为 undefined 时,有 getInitialProps 无返回,此时 return dva model | |
| 159 | + const pageData = initialData[initialData.length - 1]; | |
| 160 | + if (pageData === undefined) { | |
| 161 | + initialData[initialData.length - 1] = plugins.apply('initialProps', { | |
| 162 | + initialValue: pageData, | |
| 115 | 163 | }); |
| 116 | - } else { | |
| 117 | - // message activeRoute or getInitialProps not found | |
| 118 | - console.log( | |
| 119 | - !activeRoute | |
| 120 | - ? `${pathname} activeRoute not found` | |
| 121 | - : `${pathname} activeRoute's getInitialProps function not found`, | |
| 122 | - ); | |
| 123 | 164 | } |
| 165 | + | |
| 166 | + // reduce all match component getInitialProps | |
| 167 | + // in the same object key | |
| 168 | + // page data key will override layout key | |
| 169 | + const props = Array.isArray(initialData) | |
| 170 | + ? initialData.reduce( | |
| 171 | + (acc, curr) => ({ | |
| 172 | + ...acc, | |
| 173 | + ...curr, | |
| 174 | + }), | |
| 175 | + {}, | |
| 176 | + ) | |
| 177 | + : {}; | |
| 178 | + | |
| 179 | + const App = React.createElement( | |
| 180 | + StaticRouter, | |
| 181 | + { | |
| 182 | + location: ctx.req.url, | |
| 183 | + context, | |
| 184 | + }, | |
| 185 | + React.createElement(router.default, props), | |
| 186 | + ); | |
| 187 | + | |
| 188 | + // render rootContainer for htmlTemplateMap | |
| 124 | 189 | const rootContainer = plugins.apply('rootContainer', { |
| 125 | - initialValue: React.createElement(require('./router').default, props), | |
| 190 | + initialValue: App, | |
| 126 | 191 | }); |
| 127 | 192 | const htmlTemplateMap = {}; |
| 193 | + const matchPath = activeRoute ? activeRoute.path : undefined; | |
| 128 | 194 | return { |
| 129 | - htmlElement: | |
| 130 | - activeRoute && activeRoute.path | |
| 131 | - ? htmlTemplateMap[activeRoute.path] | |
| 132 | - : '', | |
| 195 | + htmlElement: matchPath ? htmlTemplateMap[matchPath] : '', | |
| 133 | 196 | rootContainer, |
| 134 | - matchPath: activeRoute && activeRoute.path, | |
| 197 | + matchPath, | |
| 135 | 198 | g_initialData: props, |
| 199 | + context, | |
| 136 | 200 | }; |
| 137 | 201 | }; |
| 138 | 202 | // using project react-dom version | ... | ... |
front-end/landing-page/src/pages/.umi/umiExports.ts
0 → 100644