为什么preloadAll()在使用react-loadable时不起作用?

时间:2019-01-03 14:46:24

标签: react-loadable

我正在尝试在我的项目上使用react-loadable,但是Loadable.preloadAll无法正常工作。当我尝试加载http://localhost:1337/时,我得到的是localhost refused to connectreact-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>
  `
}

0 个答案:

没有答案