【发布时间】:2017-07-13 21:30:28
【问题描述】:
我已经阅读了很多关于 React 服务器端渲染、使用 Webpack、Express 等常用设置的文章和研究。大多数组件使用 React + ES6,将 babel-register 放在 express 入口点的开头,以允许在客户端和服务器之间共享用 ES6 编写的 React Routes。其他的,运行 babe-node 来解决这个问题。不幸的是,不建议将 babel-register 或 babel-node 用于生产环境,显然建议将其编译为单独的文件用于生产环境。
// As an example, demonstrating that `production` should not
// require babe-register, but development
if (['staging', 'production'].indexOf(process.env.NODE_ENV) > -1) {
require('./dist/server.prod.js')
} else {
require('babel-register')
require('./server.dev.js')
}
据我所知和测试(除非我在设置中遗漏了一些东西),客户端工作正常(一个捆绑的 js 文件,其中包含所有路由等);而服务器端渲染由于语法错误而失败。构建器将 express ES6 代码(服务器)转译为 ES5,但不会提前将所有路由组件转译为动态命中!
参见以下示例,对于没有 Routes 的项目,这不是问题,因为 App 组件是预先导入的,因此构建作业会对其进行编译:
router.get('*', (req, res, next) => {
const preloadedState = {'foobar': 1}
const store = configureStore(preloadedState)
const myAppHtml = renderToString(
<Provider store={store}>
<App />
</Provider>
)
const finalState = store.getState()
let html = htmlTemplateString.replace('<div id="app">', '<div id="app">' + myAppHtml)
const preloadedStateScript = `<script>window.__PRELOADED_STATE__ = ${JSON.stringify(finalState).replace(/</g, '\\x3c')}</script>`
html = html.replace('</head>', preloadedStateScript)
res.send(html)
})
同时,服务器中的动态路由更改,会import React ES6 组件并导致语法错误。例如:
router.get('*', (req, res) => {
match({routes, location: req.url}, (error, redirectLocation, renderProps) => {
const myAppHtml = renderToString(<RouterContext {...renderProps}/>);
...
})
})
我的问题是关于如何编译所有 React ES6 组件以避免在生产中使用 babel-register 或 babel-node?
Webpack 有一个 ExtractTextPlugin 用于将 CSS 从输出中提取到单个文件中,是否可以对组件执行相同的操作?
我们是否必须运行 babel 将所有 React App 目录结构转换到一个新目录中,该目录仅用于生产中的服务器端渲染?
这些是我在使用路由和匹配路由时发现的关于 React 服务器端渲染的大多数文章中没有找到任何答案的一些问题。
【问题讨论】:
标签: reactjs webpack babeljs server-side-rendering