我正在尝试使用我的使用HMR的反应应用程序实现服务器端渲染,并需要对我的问题进行一些澄清。服务器和前端之间似乎存在沟通错误,但我并不完全确定为什么会这样。
当我启动服务器时,浏览器会加载客户端index.html,我可以使用HMR编辑我的网站。但是,当我导航到主页旁边的另一个页面,并刷新浏览器时,服务器然后在我的handleRender函数中呈现html标记。网站html标记出现,但没有CSS和HMR不起作用。
总结一下,在第一次加载时,它会呈现应用程序客户端,但在刷新时,它会呈现应用服务器端。我认为这可能与我使用router.use(express.static(clientDir));
的方式有关,但我不确定。任何澄清都会有所帮助!
客户端Index.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Base Template</title>
<link rel="stylesheet" type="text/css" href="/static/bundle.css">
</head>
<body id="body">
<div class="root"></div>
<script src="/static/bundle.js"></script>
</body>
</html>
React App index.js
import React from 'react'
import ReactDOM from 'react-dom'
import { AppContainer } from 'react-hot-loader'
import { BrowserRouter } from 'react-router-dom'
import App from './App'
const root = document.querySelector('.root');
// Wraps our App in AppContainer
const render = (Component) => {
ReactDOM.render(
<BrowserRouter>
<AppContainer>
<Component/>
</AppContainer>
</BrowserRouter>,
root
);
};
// Renders our application
render(App);
// Checks if there have been changes and accepts them.
// This activates HMR and refreshes modules in the browser
if (module.hot) {
module.hot.accept();
}
Express Server
import express from 'express'
import React from 'react'
import { renderToString } from 'react-dom/server'
import { StaticRouter } from 'react-router'
import { resolve } from 'path'
import routes from './routes'
// Imports our React App
import App from '../client/scripts/App'
// Create Express App
const app = express();
// Set the port for our server
app.set('port', process.env.PORT || 3000)
// Use routes to check if the environment is prod || dev
app.use(routes)
// Use handleRender for SSR
app.use(handleRender)
function handleRender(req, res) {
const context = {};
const html = renderToString(
<StaticRouter location={req.url} context={context} >
<App/>
</StaticRouter>
)
if (context.url) {
res.writeHead(301, {
Location: context.url
})
res.end()
} else {
res.write(`
<!doctype html>
<head>
<title>Redux Universal Example</title>
<link rel="stylesheet" type="text/css" href="/static/bundle.css">
</head>
<body>
<div id="app">${html}</div>
<script type="javascript" src="/static/bundle.js"></script>
</body>
`)
res.end()
}
}
export default app
服务器路由
import express, { Router } from 'express'
import { resolve } from 'path'
import { isDev } from '../utils'
const router = Router();
const clientDir = resolve(`${__dirname}/../../client`);
if (isDev()) {
const webpackDevMiddleware = require('webpack-dev-middleware')
const webpack = require('webpack')
const webpackConfig = require('../../../webpack.config')
const webpackHotMiddleware = require('webpack-hot-middleware')
const compiler = webpack(webpackConfig)
// This compiles our app using webpack
router.use(webpackDevMiddleware(compiler, {
publicPath: webpackConfig.output.publicPath,
noInfo: true
}))
// This connects our app to HMR using the middleware
router.use(webpackHotMiddleware(compiler))
}
router.use(express.static(clientDir));
export default router