我正在尝试在我的项目上使用react-loadable,但是Loadable.preloadAll无法正常工作。当我尝试加载http://localhost:1337/时,我得到的是localhost refused to connect
。
react-loadable.json
看起来不错。
我正在使用React 16.6.3,Webpack 4.27.1和react-router 4.4.0-beta.6
我使用了来自react-loadable的官方文档,他们的示例并阅读了几篇文章,但我不知道我的错误在哪里。
这是我的代码。
server.js
import Loadable from 'react-loadable'
const express = require('express')
const app = new express()
if (isDev) {
app.use('/', express.static('static'))
} else {
app.use('/', express.static('build', {
maxAge: '1y'
}))
}
app.get('*', require('./server/serverRender')())
Loadable.preloadAll().then(() => {
app.listen(PORT, HOST, error => {
if (error) {
console.error(error)
} else {
console.info('==> Listening on port 1337, PORT, HOST)
}
})
}).catch(error => {
console.log(error)
})
serverRender.js
import React from 'react'
import { matchRoutes, renderRoutes } from 'react-router-config'
import { renderToStaticMarkup } from 'react-dom/server'
import StaticRouter from 'react-router'
import { Provider } from 'react-redux'
import Loadable from 'react-loadable'
import { getBundles } from 'react-loadable/webpack'
import routes from '../routes'
import stats from '../../react-loadable.json'
module.exports = function () {
return function (req, res) {
const store = createStore({ rootReducer, initialState})
const branch = matchRoutes(routes, req.url)
let context = {}
const promises = branch.map(({route}) => {
let fetchData = route.component.fetchData
return fetchData && fetchData instanceof Function ?
fetchData(store) : Promise.resolve(null)})
if (context.url) {
res.redirect(302, context.url);
} else {
promiseTimeout(Promise.all(promises), SERVER_TIMEOUT_THRESHOLD)
.catch((err) => {
console.error('Server prefetching failed', err)
store.dispatch(serverPrefetchFailed())
})
.then((promiseArr = []) => {
const promiseData = promiseArr[0] || {}
const { statusCode, redirect } = promiseData
let modules = []
if (redirect != null) {
return res.redirect(redirect)
}
let bodyHtml = renderToStaticMarkup (
<Loadable.Capture report={moduleName => modules.push(moduleName)}>
<Provider store={store}>
<StaticRouter location={req.path} context={context}>
{renderRoutes(routes)}
</StaticRouter>
</Provider>
</Loadable.Capture>
)
let bundles = getBundles(stats, modules)
let getSingleBundle = () => {
bundles.map(file => {
return `<script src="/js/${bundle.file}"></script>`
}).join('\n')
}
res.status(statusCode || 200).send('<!DOCTYPE html>' + renderHtml({
head,
initialState: store.getState(),
bodyHtml,
bundle: getSingleBundle()
}))
}).catch(err => {
console.error(err);
res.status(500).send(err)
})
}
} }
routes.js
import React from 'react'
import Loadable from 'react-loadable'
import App from './App'
function Loading () {
return <h3>Loading...</h3>
}
const SomeForm = Loadable({
loader: () => import('./pages/SomeForm'),
loading: Loading
})
const LandingPage = Loadable({
loader: () => import('./pages/LandingPage'),
loading: Loading
})
const routes = [
{ component: App,
routes: [
{ path: '/',
exact: true,
component: LandingPage
},
{
path: '/some',
component: SomeForm
}
]
}
]
client.js
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import Loadable from 'react-loadable'
import { BrowserRouter } from 'react-router-dom'
import { renderRoutes } from "react-router-config"
import routes from './routes'
function getRootElement () {
return (
<Provider store={store}>
<BrowserRouter>
{renderRoutes(routes)}
</BrowserRouter>
</Provider>
)
}
Loadable.preloadReady().then(() => {
ReactDOM.hydrate(getRootElement(), document.getElementById('root'))
})
html.js
export function renderHtml ({ head, bodyHtml, initialState, bundle
}) {
return `
<html lang="en">
<head>
<base href="/" />
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
${mainCss || ''}
</head>
<body>
<div id="root">${bodyHtml}</div>
<script>window.__INITIAL_STATE__= ${serialize(initialState)}</script>
${mainScripts || ''}
${bundle}
</body>
</html>
`
}