react服务端渲染-03

87 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 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>
    `

这样修改完后 重新 打包后,就能在页面上进行点击事件了

看下效果: