[英]Code splitting route components wrapped in a HOC with React Loadable
I am running into problems using React Loadable with route based code splitting using Webpack 3.11. 我在使用React Loadable和使用Webpack 3.11进行基于路由的代码拆分时遇到了问题。
When I try to render my app on the server my async modules immediately resolve without waiting for the promise. 当我尝试在服务器上呈现我的应用程序时,我的异步模块会立即解析,而无需等待承诺。 Thus the SSR output becomes
<div id="root"></div>
. 因此,SSR输出变为
<div id="root"></div>
。
App.js: App.js:
const App = () => (
<Switch>
{routes.map((route, index) => (
<Route key={index} path={route.path} render={routeProps => {
const RouteComponent = route.component
return <RouteComponent {...routeProps} />
}} />
))}
</Switch>
)
I've defined my async route components with React Loadable like this: 我已经用React Loadable定义了异步路由组件,如下所示:
Routes.js Routes.js
function Loading ({ error }) {
if (error) {
return 'Oh nooess!'
} else {
return <h3>Loading...</h3>
}
}
const Article = Loadable({
loader: () => import(/* webpackChunkName: "Article" */ '../components/contentTypes/Article'),
loading: Loading
})
const Page = Loadable({
loader: () => import(/* webpackChunkName: "Page" */ '../components/contentTypes/Page'),
loading: Loading,
render (loaded, props) {
let Component = WithSettings(loaded.default)
return <Component {...props}/>
}
})
export default [
{
path: `/:projectSlug/:env${getEnvironments()}/article/:articleSlug`,
component: Article,
exact: true
},
{
path: `/:projectSlug/:env${getEnvironments()}/:menuSlug?/:pageSlug?`,
component: Page
}
]
WithSettings.js WithSettings.js
export default (WrappedComponent: any) => {
class WithSettings extends React.Component<WithSettingsProps, WithSettingsState> {
static displayName = `WithSettings(${WrappedComponent.displayName || WrappedComponent.name || 'Component'})`
state = {
renderWidth: 1200
}
componentDidMount () {
this.loadSettings({ match: { params: { projectSlug: '', env: '' } } })
window.addEventListener('resize', this.onResize)
this.onResize()
}
componentWillUnmount () {
if (isClient) {
window.removeEventListener('resize', this.onResize)
}
}
componentDidUpdate (oldProps) {
this.loadSettings(oldProps)
}
onResize = () => {
this.setState({ renderWidth: this.getLayoutWidth() })
}
getLayoutWidth () {
return (document.body && document.body.offsetWidth) || 0
}
loadSettings (oldProps) {
const { settings, request, getNewSettings } = this.props
const { projectSlug: oldProjectSlug, env: oldEnv } = oldProps.match.params
const { projectSlug: newProjectSlug, env: newEnv } = this.props.match.params
if (
(
oldProjectSlug !== newProjectSlug ||
oldEnv !== newEnv
) ||
(
settings === undefined ||
(request.networkStatus === 'ready')
)
) {
getNewSettings()
}
}
render () {
const { settings, request, history, location, match } = this.props
const { renderWidth } = this.state
if (!settings || !request || request.networkStatus === 'loading') {
return <div />
}
if (request.networkStatus === 'failed') {
return <ErrorBlock {...getErrorMessages(match.params, 'settings')[4044]} fullscreen match={match} />
}
return (
<WrappedComponent
settings={settings}
settingsRequest={request}
history={history}
location={location}
match={match}
renderWidth={renderWidth}
/>
)
}
}
hoistNonReactStatic(WithSettings, WrappedComponent)
return connect(mapStateToProps, mapDispatchToProps)(WithSettings)
}
I've managed to narrow it down to the WithSettings
HOC that I am using to wrap my route components in. If I don't use the WithSettings
HOC (as with the Article route) then my SSR output waits for the async import to complete, and the server generated html includes markup related to the route (good!). 我已经成功地缩小它的
WithSettings
我使用包在我的路线组件HOC。如果我不使用WithSettings
HOC(与第二条路线),那么我的SSR输出等待异步进口完成,并且服务器生成的html包含与路由相关的标记(好!)。 If I do use the HOC (as with the Page route) then the module immediately resolves and my SSR output turns into <div id="root"></div
because it no longer waits for the dynamic import to complete before rendering. 如果我确实使用HOC(与Page路由一样),则该模块会立即解析,并且我的SSR输出变为
<div id="root"></div
因为它不再等待动态导入完成才渲染。 Problem is: I need the WithSettings HOC in all my routes as it fetches required data from the server that I need to render the app. 问题是:我需要在所有路由中使用WithSettings HOC,因为它会从服务器中获取渲染应用程序所需的数据。
Can anyone tell me how I can use a HOC and use React Loadable's async component for route components so that it works on the server? 谁能告诉我如何使用HOC 并将 React Loadable的async组件用于路由组件,从而使其在服务器上工作?
Managed to figure it out. 设法弄清楚了。
It was due to my HOC. 这是由于我的HOC。 In the render method it would return
<div />
when settings
or request
where undefined or request.networkStatus
is loading
. 在render方法中,当
settings
或request
loading
未定义或request.networkStatus
时,它将返回<div />
。 It turns out this tripped up server side rendering. 事实证明,这跳了服务器端渲染。 Removing this block was enough to make it work.
删除该块足以使其正常工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.