使用SSR

时间:2019-11-22 23:01:50

标签: webpack webpack-dev-server server-side-rendering react-loadable

我正在使用可加载的反应,也正在做SSR。我遇到以下失败:

The "chunk" argument must be one of type string or Buffer. Received type object{ Error: Cannot find module './simple-search~workspaces.chunk.js'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:581:15)
    at Function.Module._load (internal/modules/cjs/loader.js:507:25)
    at Module.require (internal/modules/cjs/loader.js:637:17)
    at require (internal/modules/cjs/helpers.js:22:18)
    at Function.requireEnsure [as e] (bundle.middleware.js:58:25)
    at loader (webpack-internal:///./src/main/webapp/routes.js:158:79)

我觉得这与react-loadables SSR插件的资产清单中的公共路径有关,但我不太确定它应该是什么。如果直接点击它,我可以在浏览器中查看实际的捆绑软件,但是当我的服务器点击它时,它无法加载。

Webpack配置文件

  entry: [nodeResolve('babel-polyfill'), nodeResolve('whatwg-fetch'), 'index.js'],
  output: {
    path: resolve('./target/webapp'),
    filename: 'bundle.[hash].js',
    globalObject: 'this',
    chunkFilename: '[name].chunk.js',
  },
  plugins: [
    new ReactLoadableSSRAddon({
      filename: 'react-loadable-ssr-addon.json',
    }),
  ],
  optimization: {
    splitChunks: {
      cacheGroups: {
        commons: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all',
          minChunks: 2,
        },
        default: {
          minChunks: 2,
          reuseExistingChunk: true,
        },
      },
    },
  },

服务器端代码


module.exports = async (req, res, next) => {
  const path = req.originalUrl.replace(ROOT_PATH, '')
  try {
    if (hasPath(path)) {
      const { originalUrl, clientBundle } = req
      const html = await executeSSR(originalUrl, clientBundle)
      res.end(html)
    } else {
      next()
    }
  } catch (e) {
    process.stderr.write(e.message)
    res.status(500)
    res.end(e.message)
  }
}

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))

const executeSSR = async (originalUrl, clientBundle) => {
  const sheets = new ServerStyleSheets()
  const client = createClient({ ssrMode: true })
  const modules = new Set()

  const App = sheets.collect(
    <Loadable.Capture report={moduleName => modules.add(moduleName)}>
      <ApolloProvider client={client}>
        <StaticRouter location={originalUrl} basename={ROOT_PATH} context={{}}>
          <Routes />
        </StaticRouter>
      </ApolloProvider>
    </Loadable.Capture>
  )

  const Html = ({ content, state, css }) => {
    const bundles = getBundles(manifest, [
      ...manifest.entrypoints,
      ...Array.from(modules),
    ])

    const styles = bundles.css || []
    const scripts = bundles.js || []

    return `
    <!doctype html>
    <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>React Loadable SSR Add-on Example</title>
        ${styles
          .map(style => {
            return `<link href="${style.file}" rel="stylesheet" />`
          })
          .join('\n')}
      </head>
      <body>
        <div id="app">${content}</div>
        ${scripts
          .map(script => {
            return `<script src="${script.file}"></script>`
          })
          .join('\n')}
      </body>
    </html>
  `
  }

  try {
    await getDataFromTree(App)
    await sleep(300)
    const content = renderToString(App)
    const styling = sheets.toString()
    const initialState = client.extract()
    const html = <Html content={content} state={initialState} css={styling} />
    return html
  } catch (e) {
    console.log(e)
    const html = <Html content="" state={{}} />
    return html
  }
}

0 个答案:

没有答案