【React】《React 学习手册 (第2版) 》笔记-Chapter12-React 服务器端渲染

十二、React 服务器端渲染
  1. 我们可以采用同构方式渲染 React,以便支持浏览器以外的平台。这意味着,我们可以在服务器端渲染 UI,然后再发给浏览器。借助服务器端渲染,可以提升性能、增进可移植性、提高安全性。

  2. 同构(isomorphic)和普适(universal)这两个术语通常都指在客户端和服务器端都可以运行的应用。虽然二者往往可以互换,但还是有点儿区别的。同构应用指可在多个平台上渲染的应用,而普适代码指同一套代码可在多个环境中运行。

  3. 有了 Node.js,我们可以在其他应用,例如服务器端应用、CLI 应用,甚至是原生应用中重用为浏览器编写的代码。

  4. 不是所有 JavaScript 代码不经一点改动就能在两端运行。

    • Node.js 和浏览器不同,没有内置 fetch 函数。
    • 在 Node.js 中,我们可以使用 npm 中的 isomorphic-fetch,也可以使用内置的 https 模块。
      // 既然我们已经使用了 fetch 句法,那就用 isomorphic-fetch:
      npm install isomorphic-fetch
      
    • 然后,只需导入 isomorphic-fetch,其他代码无需改动:
      const fetch = require("isomorphic-fetch");const userDetails = response => {const login = response.login;console.log(login);
      };fetch("https://api.github.com/users/moonhighway").then(res => res.json()).then(userDetails);
      
  5. JSX 会编译成 JavaScript。Star 组件就是一个函数而已。这个组件可以直接在浏览器渲染,也可以捕获输出的 HTML 字符串,在其他环境中渲染。ReactDOM 提供的 renderToString 方法可以把 UI 渲染为 HTML 字符串:

    // 在浏览器中直接渲染 HTML
    ReactDOM.render(<Star />);// 把 HTML 渲染为字符串
    let html = ReactDOM.renderToString(<Star />);
    
  6. 我们可以构建同构应用,在不同的平台中渲染组件,还可以通过一定的架构方式,跨多个平台全局重用 JavaScript 代码。另外,使用其他编程语言,例如 Go 或 Python 也可以构建同构应用,不限于只能使用 Node.js。

  7. 使用 ReactDOM.renderToString 方法可以在服务器端渲染 UI。

  8. 构建应用时,客户端渲染通常是首选方案。我们伺服 Create React App 生成的 build 文件夹,在浏览器中运行 HTML,通过 script.js 文件加载所需的 JavaScript 代码。

    • 但是这个方案有点儿耗时。用户可能要等一会儿才能看到内容加载出来,具体等待事件取决于网络速度。
    • Create React App 搭配 Express 服务器可以实现一种混合客户端和服务端渲染的体验。
  9. 改动客户端的代码,首先要做的改动是,把 ReactDOM.render 换成 ReactDOM.hydrate。

    • 这两个函数的作用相同,只不过 hydrate 把内容添加到一个由 ReactDOMServer 渲染的容器中。操作顺序是这样的:
      1. 渲染应用的静态版本,让用户知道应用在做事,“加载了”页面。
      2. 请求动态 JavaScript 代码。
      3. 把静态内容替换为动态内容。
      4. 用户点击,交互正常。
    • 这其实就是在服务端渲染之后把内容再输送给应用。再输送是指先加载静态 HTML 内容,然后加载 JavaScript。这样做能让用户在感官上体验到性能的顺畅。
  10. 接下来要设置项目的服务器。我们将使用轻量级 Node 服务器 Express。

    • 先安装:
      npm install express
      
    • 然后,创建一个服务器文件夹,命名为 server,再新建一个文件 index.js,保存在该文件夹中。我们在这个文件中构建一个服务器,让它伺服 build 文件夹,另外预先加载静态 HTML 内容。
      import express from "express";
      const app = express();app.use(express.static("./build"));
      
      • 这段代码导入服务器,静态伺服 build 文件夹。
    • 接着,使用 ReactDOM 提供的 renderToString 函数,以静态 HTML 字符串的形式渲染应用:
      import React from "react"; 
      import ReactDOMServer from "react-dom/server";
      import { Menu } from "../src/Menu.js";const PORT = process.env.PORT || 4000;app.get("/*", (req, res) => {const app = ReactDOMServer.renderToString(<Menu />);const indexFile = path.resolve("./build/index.html");fs.readFile(indexFile, "utf8", (err, data) => {return res.send(data.replace('<div id="root"></div>',`<div id="root">${app}</div>`));});
      });app.listen(PORT, () =>console.log(`Server is listening on port ${PORT}`)
      );
      
      • 我们要把 Menu 组件传给 renderToString 函数,因为这是我们想静态渲染的组件。
      • 然后,我们要从构建好的客户端应用中读取静态的 index.html 文件,把应用的内容写入 div 元素,并把这部分内容作为请求的响应。
  11. 完成以上操作后,我们要配置 webpack 和 Babel。虽然 Create React App 自身就能编译和构建,但是我们要为服务器端设置和实施一些不同的规则。

    • 首先安装几个依赖:
      npm install @babel/core @babel/preset-env babel-loader nodemon npm-run-all webpack webpack-cli webpack-node-externals
      
    • 安装好 Babel 之后,创建 .babelrc 文件,写入下述预设规则:
      {"presets": ["@babel/preset-env", "react-app"]
      }
      
    • 接下来,为服务器增加一个 webpack 配置文件,名为 webpack.server.js:
      const path = require("path");
      const nodeExternals = require("webpack-node-externals");module.exports = {entry: "./server/index.js",target: "node",externals: [nodeExternals()],output: {path: path.resolve("build-server"),filename: "index.js"},module: {rules: [{test: /\.js$/,use: "babel-loader"}]}
      };
      
    • babel-loader 的作用是转换 JavaScript 文件,而 nodeExternals 则负责扫描 node_modules 文件夹,找到所有 node_modules 名称,构建一个外部函数,告诉 webpack 不要打包这些模块及其子模块。
    • 另外,你可能会遇到一个有关 webpack 的错误,这是由 Create React App 安装的版本与我们自己安装的版本发生冲突导致的。这个冲突的解决方法是,在项目根目录中创建 .env 文件,写入下述内容:
      SKIP_PREFLIGHT_CHECK=true
      
    • 最后,可以添加几个 npm 脚本,运行开发相关的命令:
      "scripts": {// ..."dev:build-server": "NODE_ENV=development webpack --config webpack.server.js --mode=development -w","dev:start": "nodemon ./server-build/index.js","dev": "npm-run-all --parallel build dev:*"
      },
      
      • dev:build-server:设置环境变量 development,使用新服务器配置运行 webpack。
      • dev:start:使用 nodemon 运行服务器文件,监听变动。
      • dev:并行运行前两个进程。
    • 现在,执行 npm run dev 命令,两个进程都会运行。你会看到应用运行在 localhost:4000 地址上。这个应用将按顺序加载内容,先预渲染 HTML,再渲染 JavaScript 构建包。
  12. 在服务器端渲染生态环境中,还有一个使用广泛的强大工具,即 Next.js。Next.js 旨在帮助工程人员更轻松地编写服务器端渲染的应用。这个工具提供的功能有直观的路由、静态优化、自动分拆代码等。

  13. 基于 React 的另一个受欢迎的网站生成工具是 Gatsby。Gatsby 为创建内容驱动型网站提供了一种简单直观的方式。Gatsby 的默认设置足够智能,性能、可访问性、图像处理等都不用我们自己操心。

    • Gatsby 可以创建的项目类型很多,不过通常用于构建内容驱动型网站。也就是说,对博客或静态内容网站而言,Gatsby 是个不错的选择,尤其是对 React 熟悉的人。此外,Gatsby 也可以处理动态内容,例如从 API 中加载数据、与框架集成等。
  14. 如果你想构建移动应用,可以使用 React Native;如果你想使用声明式句法获取数据,可以使用 GraphQL;如果你想构建内容类网站,可以进一步探索 Next.js 和 Gatsby。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/30553.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flink Time 详解

Flink在处理实时数据流时&#xff0c;时间是一个核心概念。Flink支持多种时间语义&#xff0c;以满足不同业务场景的需求。以下是对Flink中时间概念的详细解释&#xff1a; 一、时间概念概述 在Flink中&#xff0c;时间主要分为三种类型&#xff1a; 事件时间&#xff08;Eve…

技术差异,应用场景;虚拟机可以当作云服务器吗

虚拟机和云服务器是现在市面上常见的两种计算资源提供方式&#xff0c;很多人把这两者看成可以相互转换或者替代的物品&#xff0c;实则不然&#xff0c;这两种资源提供方式有许多相似之处&#xff0c;但是也有不少区别&#xff0c;一篇文章教你识别两者的技术差异&#xff0c;…

【全文档】软件项目经理需要掌握的文档有哪些?

软件项目经理在项目管理过程中需要编写多种文档&#xff0c;以下是常见的十五个文档&#xff1a; 项目计划&#xff1a; 详细描述了项目的范围、时间、成本、资源、沟通计划等关键信息&#xff0c;是项目管理的核心文档。 需求文档&#xff1a; 记录了项目的业务需求、功能需求…

vue3第二阶段的开发文档

1 2.1 案例——学习计划表 2.1.1 准备工作 在开发“学习计划表”案例之前&#xff0c;需要先完成一些准备工作&#xff0c;具体步骤如下。 ① 打开命令提示符&#xff0c;切换到 D:\vue\chapter02 目录&#xff0c;在该目录下执行如下命令&#xff0c;创建 项目。 np…

深入理解预处理

1.预定义符号 C语言设置了⼀些预定义符号&#xff0c;可以直接使用&#xff0c;预定义符号也是在预处理期间处理的。 __FILE__ //进⾏编译的源⽂件 __LINE__ //⽂件当前的⾏号 __DATE__ //⽂件被编译的⽇期 __TIME__ //⽂件被编译的时间 __STDC__ //如果编译器遵循ANSI C&…

3. ceph-mimic版本部署

ceph-mimic版本部署 一、ceph-mimic版本部署1、环境规划2、系统基础环境准备2.1 关闭防火墙、SELinux2.2 确保所有主机时间同步2.3 所有主机ssh免密2.4 添加所有主机解析 3、配置ceph软件仓库4、安装ceph-deploy工具5、ceph集群初始化6、所有ceph集群节点安装相关软件7、客户端…

AI-“国外一开源,国内就创新”!

大模型领域中美差距有多大&#xff1f; 近年来&#xff0c;人工智能技术在全球范围内迅速发展&#xff0c;特别是在大型语言模型和机器学习方法方面取得了突破性进展。在这个领域&#xff0c;计算能力的提升也推动了技术的革命性进步。 作为世界上两大的重要经济体&#xff0…

Java程序之简单求和

题目&#xff1a; 求saaaaaaaaaaaa...a的值&#xff0c;其中a是一个数字。要求输入a的值和加数的个数n&#xff0c;例如&#xff1a;a2&#xff0c;n5&#xff0c;此时s222222222222222&#xff0c;输出s的值。 源代码&#xff1a; package Question5;import java.util.Scann…

LeetCode322.零钱兑换(一)

LeetCode刷题记录 文章目录 &#x1f4dc;题目描述&#x1f4a1;解题思路⌨C代码 &#x1f4dc;题目描述 给你一个整数数组 coins &#xff0c;表示不同面额的硬币&#xff1b;以及一个整数 amount &#xff0c;表示总金额。 计算并返回可以凑成总金额所需的 最少的硬币个数 。…

Macbook M1 Fusion安装Debian/Linux

背景 本人主力工作电脑已经迁移到苹果芯片m1的macbook上&#xff0c;曾经尝试使用Fusion安装CentOS、OpenEuler、Ubuntu的一些版本&#xff0c;都没有安装成功。最近开始研究Linux/Unix系统编程&#xff0c;迫切需要通过VMware Fusion安装一台Linux操作系统的虚拟机。 Linux安…

u8g2 使用IIC驱动uc1617 lcd 字符显示只显示上半部分,不显示下半部

使用u8g2 使用硬件iic驱动某些page为4个字节 带灰度的lcd显示屏幕的时候有时候只显示上半部&#xff0c;下半部不显示&#xff0c;例如uc1617等。 原因&#xff1a; 以uc1617为例&#xff0c;链接https://github.com/olikraus/u8g2/blob/master/csrc/u8x8_d_uc1617.c 在u8x8…

libmodbus 疑问:对象结构体是如何关联的

1. 主要结构体 结构体 modbus_t &#xff1a; 包含 int slave&#xff08;从机地址&#xff09;、timeout、 backend&#xff08;各种操作&#xff09;; backend_data 等 结构体modbus_backend_t&#xff1a; build_request_basis、set_slave、receive、send、connect 等操作 …

项目监督与控制

1.什么是项目过程度量&#xff1f;其方法有哪些&#xff1f; 项目过程度量是一种对项目执行过程中的活动和性能进行量化测量的方法。它涉及到收集、分析和解释项目数据&#xff0c;以便更好地理解项目的进度、质量和效率。过程度量的目的是提供关于项目健康状况的客观信息&…

爬虫的法律风险是什么?以及合法使用爬虫技术的建议。

爬虫的法律风险是什么&#xff1f; 网络爬虫技术&#xff0c;虽然在数据获取方面具有巨大优势&#xff0c;但其使用过程中可能引发的法律风险也不容忽视。这些风险主要包括违反数据保护法规、侵犯知识产权、构成不正当竞争等。下面将详细探讨网络爬虫的法律风险&#xff0c;并在…

【防火墙策略】实际使用

限制主机仅能从堡垒机登录&#xff0c;并设置开机自动加载防火墙规则。 1、 配置/etc/rc.local新增 /sbin/iptables-restore /etc/sysconfig/iptables 2、授权 chmod x /etc/rc.d/rc.local3、检查/etc/sysconfig/iptables文件是否存在&#xff0c;否则执行 ll /etc/sysconfi…

C/C++ 包管理工具汇总

在C/C中&#xff0c;包管理工具主要用于帮助开发者更方便地管理项目依赖的库和头文件。以下是一些常用的C/C包管理工具&#xff1a; vcpkg&#xff1a;由微软开发&#xff0c;支持Windows、macOS和Linux。vcpkg通过Git仓库维护一个庞大的库集合&#xff0c;可以轻松地安装、卸载…

代码随想录第28天|回溯算法

491. 非递减子序列 思路: 不可以排序, 否则会改变元素的顺序对收获的结果有要求, num.size() > 2, 且 num[i - 1] < num[i]需要进行去重, 不能使用排序后的方法去重每一层可用 unordered_set 去重组合问题, for 遍历需要标记起始位置 bug: 一定要先判断元素是否重复, …

使用CAPL创建系统变量之sysDefineNamespace

目录 0 前言 1 使用CAPL创建系统变量 0 前言 最近在项目中发现可以通过CAPL来创建系统变量&#xff0c;这样方法在一定程度上提高了代码的统一性和测试的便利性。想要加入HIL自动化测试群的小伙伴欢迎评论区留言或私信&#xff0c;让我们一起进步&#xff01; 1 使用CAPL创建…

染发膏粪大肠菌群检测 化妆品毒理学检测 功效测试

染发膏中粪大肠菌群的检测 染发膏中的粪大肠菌群检测是为了确保产品的卫生安全&#xff0c;因为粪大肠菌群通常存在于动物的肠道中&#xff0c;它们的存在可能表明产品受到了外部环境的污染。根据国家标准GB/T 7918.3-1987&#xff0c;对化妆品中粪大肠菌群的检测方法进行了规范…

【html】爱心跳动动画:CSS魔法背后的故事

效果展示&#xff1a; 代码介绍&#xff1a; 爱心跳动动画&#xff1a;CSS魔法背后的故事 在前端开发中&#xff0c;CSS不仅仅是一种用于控制网页样式的工具&#xff0c;它也是一种表达创意和想象力的艺术手段。今天&#xff0c;我要为大家介绍一段使用CSS实现的爱心跳动动画…