携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第20天,点击查看活动详情
前两篇文章 我们写了 环境搭建 和 在 Node中写react代码
今天 这篇 文章 开始写 服务端渲染中的 前端注水的功能
前端注水
比如在 Home 组件中 添加一个点击事件
import React from 'react';
const Home = () => {
const handleClick = () => {
console.log('click')
}
return <div>home
<button onClick={handleClick}>点击</button>
</div>
}
export default Home;
当在页面点击的时候,日志没有被打印。
这是因为,Home组件是服务端渲染的,点击事件是在客户端进行的,客户端接收不到 这个点击事件,所以日志没有被打印。
下面通过让客户端 拦截 路由 实现 事件点击
首先在pages下创建client.js
在react-dom中有hydrate可以进行注水,也就是拦截。
通过hydrate进行注水,并且绑定到 id为root的div下面
具体的代码如下:
import React from 'react';
import ReactDom from 'react-dom';
import { BrowserRouter } from 'react-router-dom'
import Routes from './routes';
ReactDom.hydrate(
<BrowserRouter>
<Routes />
</BrowserRouter>,
document.getElementById('#root')
)
这个时候我们需要将这个clent.js文件进行打包
在config目录下创建webpack.client.js,来进行client.js的打包
注意:这个时候需要把webpack-node-externals去掉,因为这个时候是打包的react客户端
同时需要注意,这个时候我们打包的是react代码,所以需要将 webpack中的 target的值 改为 web
将入口文件改为 src/client.js
将出口文件改为 dist/public
const path = require('path')
module.exports = {
target: 'web',
mode: process.env.NODE_ENV === 'production' ? 'production': 'development',
entry: path.resolve(__dirname,'../src/client.js'),
output: {
path: path.resolve(__dirname,'../dist/public'),
filename: 'bundle_client.js'
},
module: {
rules: [
{
test: /.js$/,
loader: 'babel-loader',
exclude: '/node_modules/'
}
]
}
}
然后在scripts中配置下命令
"webpack:client": "webpack --config ./config/webpack.client.js --watch"
最后在输出的html中引入打包后的client.js
const html = `
<html>
<head></head>
<body>
<div id="root">${content}</div>
<script src="bundle_client.js"></script>
</body>
</html>
`
这样修改完后 重新 打包后,就能在页面上进行点击事件了
看下效果: