使用Node搭建reactSSR服务端渲染架构

使用Node搭建reactSSR服务端渲染架构是一个相对复杂的过程,需要以下步骤:

1. 创建基础项目

我们可以使用脚手架工具create-react-app创建一个基础的React项目。

npx create-react-app my-app --template typescript

之后需要安装一些依赖包,包括react、react-dom、react-router-dom以及其他一些常用的包。并且需要安装一些开发依赖包,如babel-plugin-import、@types/react等。

2. 配置服务端渲染环境

我们需要在项目根目录下创建一个server.js文件,并且在其中进行服务器的配置。在配置中需要引用react、react-dom、express等核心模块,同时还需要使用babel进行代码编译等。

import express from 'express';
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import App from './App'; // 项目根组件

const app = express();

// 配置路由,注意路由的“*”表示匹配所有路由
app.get('*', (req, res) => {
  const appString = ReactDOMServer.renderToString(<App />);
  res.send(`<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>React SSR example</title>
</head>
<body>
  <div id="root">${appString}</div>
  <script src="/static/js/bundle.js"></script>
</body>
</html>
`);
});

app.listen(3000, () => {
  console.log('Server is listening on port 3000');
});

需要注意的是,在用ReactDOMServer将React组件渲染成HTML字符串时,需要在服务器端进行组件的渲染。因此需要使用ReactDOMServer的renderToString函数,渲染完成后将渲染出的内容以字符串形式返回给客户端进行处理。

3. 配置Webpack打包

在服务端渲染架构中,我们需要将所有客户端代码打包成一个单独的文件,以供服务端渲染时使用。这个打包过程可以通过Webpack进行。

我们需要修改package.json文件中的启动脚本,以便在打包文件时可以一并打包服务端渲染代码:

"scripts": {
  "start": "npm run build && node server.js",
  "build": "react-scripts build && node build-server.js"
},

在根目录下创建一个build-server.js文件,并在其中进行Webpack打包的相关配置。

const path = require('path');
const webpack = require('webpack');

const webpackClientConfig = require('./node_modules/react-scripts/config/webpack.config.js')('development');
const webpackServerConfig = {
  ...webpackClientConfig,
  entry: {
    server: path.resolve(__dirname, './server.js')
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, './build')
  },
  target: 'node'
};

webpack([webpackClientConfig, webpackServerConfig]).run((err, stats) => {
  if (err) {
    console.error(err);
  } else {
    const info = stats.toJson();
    if (stats.hasErrors()) {
      console.error(info.errors);
      process.exit(1);
    } else {
      console.log(info);
    }
  }
});

在此文件中,我们首先获取了默认的Webpack配置(webpackClientConfig),并在此基础上针对服务端渲染进行了修改,包括:

  • 修改entry为server.js文件路径;
  • 修改output为输出到build文件夹下,文件名为[name].js,即使用entry的名字作为输出文件名;
  • 修改target为node,以保证打包后的JS文件可以在Node.js环境下执行。

4. 开始使用服务端渲染

完成以上的配置后,我们就可以使用服务端渲染来处理React组件的渲染了。

首先,在页面中引用我们打包生成的client.js文件:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>React SSR example</title>
</head>
<body>
  <div id="root"></div>
  <script src="/static/js/bundle.js"></script>
  <script src="/static/js/client.js"></script>
</body>
</html>

在client.js中,我们需要判断当前环境是否支持服务端渲染,如果支持,就使用ReactDOM.hydrate进行渲染,否则就使用ReactDOM.render进行客户端渲染。

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App'; // 项目根组件

const rootElement = document.getElementById('root');

if (rootElement.hasChildNodes()) {
  ReactDOM.hydrate(<App />, rootElement);
} else {
  ReactDOM.render(<App />, rootElement);
}

示例

示例一:使用服务器数据渲染组件

我们可以使用fetch等方式从服务器获取数据,并将数据传入React组件中进行渲染。

import React from 'react';

interface UserInfo {
  id: number;
  name: string;
  age: number;
}

interface Props {
  userId: number;
}

interface State {
  user: UserInfo | null;
  loading: boolean;
}

export default class User extends React.Component<Props, State> {
  constructor(props: Props) {
    super(props);

    this.state = {
      user: null,
      loading: true
    };
  }

  componentDidMount() {
    const id = this.props.userId;
    fetch(`/api/user?id=${id}`)
      .then(response => response.json())
      .then(data => {
        this.setState({ user: data, loading: false });
      });
  }

  render() {
    if (this.state.loading) {
      return (
        <div>Loading...</div>
      );
    } else {
      return (
        <div>
          User Info:
          <ul>
            <li>ID: {this.state.user?.id}</li>
            <li>Name: {this.state.user?.name}</li>
            <li>Age: {this.state.user?.age}</li>
          </ul>
        </div>
      );
    }
  }
}

在服务端,我们需要使用axios等方式获取数据,并把数据渲染到HTML字符串中。

import axios from 'axios';
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import User from './User'; // 我们刚才创建的User组件

const app = express();

app.get('/user/:id', async (req, res) => {
  const response = await axios.get(`/api/user?id=${req.params.id}`);
  const user = response.data;
  const appString = ReactDOMServer.renderToString(<User userId={user.id} />);

  res.send(`<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>React SSR example</title>
</head>
<body>
  ${appString}
</body>
</html>
`);
});

在以上代码中,我们首先使用axios进行数据请求,获取到用户信息后,将其传入User组件中,并用ReactDOMServer.renderToString将组件渲染成HTML字符串。最后将HTML字符串返回给客户端。

示例二:使用react-router进行页面路由

使用react-router进行页面路由非常方便,但在服务端渲染中需要进行特殊处理,以保证客户端在进行路由切换时可以正确地进行服务端渲染。

import React from 'react';
import { Route, Switch } from 'react-router-dom';

import Home from './pages/Home';
import About from './pages/About';
import Contact from './pages/Contact';

export default class App extends React.Component {
  render() {
    return (
      <Switch>
        <Route exact path="/" component={Home} />
        <Route exact path="/about" component={About} />
        <Route exact path="/contact" component={Contact} />
      </Switch>
    );
  }
}

对于上述代码,我们需要在服务端根据浏览器请求的URL来选择渲染哪个组件。同时还需要根据客户端路由的路径,来正确地选择渲染哪个页面,以保证服务端渲染和客户端渲染时输出的DOM树相同。

import React from 'react';
import ReactDOMServer from 'react-dom/server';
import { StaticRouter } from 'react-router-dom';

import App from './App'; // 我们刚才创建的根组件

app.get('*', (req, res) => {
  const context = {};

  const appString = ReactDOMServer.renderToString(
    <StaticRouter location={req.url} context={context}>
      <App />
    </StaticRouter>
  );

  if (context.url) {
    res.redirect(301, context.url);
  } else {
    res.send(`<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>React SSR example</title>
</head>
<body>
  <div id="root">${appString}</div>
  <script src="/static/js/bundle.js"></script>
  <script src="/static/js/client.js"></script>
</body>
</html>
`);
  }
});

在上述代码中,我们使用了StaticRouter组件来渲染路由,其中的location和context参数分别表示当前浏览器请求的URL、和服务端渲染上下文对象。其中上下文对象主要用于重定向或修改HTTP响应码等操作。

最后,如果context.url存在,则表示需要重定向到另一个URL,可通过res.redirect函数实现。否则,如果context.url不存在,则表示当前路径可以正常渲染,使用ReactDOMServer.renderToString将根组件渲染成HTML字符串后返回给客户端。

以上就是Node搭建reactSSR服务端渲染架构的完整攻略。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:使用Node搭建reactSSR服务端渲染架构 - Python技术站

(0)
上一篇 2023年6月8日
下一篇 2023年6月8日

相关文章

  • node.js回调函数之阻塞调用与非阻塞调用

    当我们在node.js中执行一个耗时操作时,例如读取文件、请求网络数据等,会出现执行时间较长的情况,这会导致整个程序阻塞,影响程序的性能。为了解决这个问题,Node.js采用了回调函数的机制来实现非阻塞调用。 阻塞调用 阻塞调用是指应用程序在执行一个函数时,必须等待该函数执行完成,才能继续执行后面的代码。当我们在node.js中进行文件读取时,如果使用阻塞调…

    node js 2023年6月8日
    00
  • Nodejs中session的简单使用及通过session实现身份验证的方法

    一、什么是session session,即会话,在Node.js中属于Web应用的内部机制,它记录了用户在应用程序中的会话状态。服务器在给客户端返回响应时,会随之返回一个sessionID,该ID会在客户端被记录下来。客户端之后每次访问服务器时,都会携带着这个sessionID一同发送给服务器,以识别当前访问者的身份。 二、Nodejs中session的简…

    node js 2023年6月8日
    00
  • node制作一个视频帧长图生成器操作分享

    下面是“node制作一个视频帧长图生成器操作分享”的完整攻略。 1. 安装依赖 首先,需要保证已经在本地安装了node.js和npm,然后在项目根目录下使用以下命令安装依赖: npm install –save canvas video-frame 其中,canvas是用于绘制长图的库,video-frame则是用于提取视频帧的库。 2. 编写代码 接下来…

    node js 2023年6月8日
    00
  • 深入分析Web应用程序前端的组件化

    深入分析Web应用程序前端的组件化 Web应用程序前端的组件化是现代Web开发的重要概念,它可以让Web应用程序的开发更加简单、高效、可维护。下面是深入分析Web应用程序前端的组件化的完整攻略: 1. 理解组件化 1.1 组件的定义 组件是一种可在Web应用程序中重复使用的封装好的代码块,通常包含了HTML、CSS和JavaScript等前端技术提供的各种元…

    node js 2023年6月8日
    00
  • node.js readline和line-reader逐行读取文件方法

    当我们需要逐行读取文件时,可以使用node.js的readline和line-reader模块。下面是具体的攻略: 使用readline模块逐行读取文件 readline模块是node.js中用来逐行读取文件的核心模块,其基本用法如下: const readline = require(‘readline’); const fs = require(‘fs’…

    node js 2023年6月8日
    00
  • JavaScript iframe 实现多窗口通信实例详解

    JavaScript iframe 实现多窗口通信实例详解 当我们在一个页面中嵌入多个 iframe 元素时,它们之间的通信就变得比较复杂。但是,我们可以使用 JavaScript 来实现 iframe 之间的通信。在本文中,我们将深入讨论如何使用 JavaScript,通过 iframe 实现多窗口通信的过程和相关的示例代码。 iframe 与 JavaS…

    node js 2023年6月8日
    00
  • nodejs实现生成文件并在前端下载

    要实现nodejs生成文件并在前端下载,主要需要以下几个步骤: 安装必要的依赖包 在nodejs项目中,我们需要使用到两个依赖包,一个是express,一个是fs。其中,express用于创建服务器和处理HTTP请求,fs用于文件系统操作。 可以在命令行中运行以下命令安装: npm install express fs –save 创建HTTP服务器 在n…

    node js 2023年6月8日
    00
  • Node输出日志的正确方法示例

    下面是Node输出日志的正确方法示例完整攻略。 标准输出和错误输出 在Node中输出日志有两种方式:标准输出和错误输出。标准输出是指程序运行时输出的一般信息,而错误输出是指程序运行时产生的错误信息。两者都可以用Node的console对象进行输出,具体方法如下: // 标准输出 console.log(‘This is a log message.’); /…

    node js 2023年6月8日
    00
合作推广
合作推广
分享本页
返回顶部