###环境依赖 node v14.18.1+
npm v6.14.15+
###部署启动
- 安装全部变量 nodemon 2.0.15
- npm install //安装node运行环境
- npm run dev
###特性 1、React 2、Redux 3、SSR 4、Express 5、路由
###V1.0.0 版本内容更新
- 新功能 ccccccccc
- 新功能 ddddddddd
名词解释:
TTFP
: 首屏展示事件
CSR
弊端:TTFP、SEO
解决:把单页面应用改成服务器端渲染的应用
现在主流的服务端渲染框架:Nuxt.js(Vue) Next.js(React)
本教程主要内容:从0开始搭建React技术栈下的SSR框架
安装
$: mkdir server
$: cd server
$: npm init
$: npm install express --save
node对ES6的支持是非常好的
服务器渲染就是页面在服务器已经被渲染好了,服务器知识把它返回。
传统的React应用是客户端渲染,是由js渲染出来的。
CSR
浏览器发送请求
服务器返回HTML
浏览器发送bundle.js请求
服务器返回bundle.js
浏览器执行bundle.js中的React代码
SSR
浏览器发送请求
服务器运行React代码生成页面
服务器返回页面
在服务器端写React的代码
首先要安装React
npm install react --save
此刻还不能运行react的代码,默认node下只支持conmon.js模块。
但是React的语法是esModule的语法。
就算你的代码写成如下也不能在服务器端运行,因为在react里面我们用了jsx的语法。这种语法也通过webpack编译打包之后才能正常的运行。但是此刻我们的项目里面根本没有做任何webpack的配置。
// import React from "react";
const React = require("react");
const Home = () => {
return <div>home</div>;
};
module.exports = {
default: Home,
};
// export default Home;
服务器端webpack的配置
package.json
"scripts": {
"start": "node ./src/index.js"
},
$: npm install webpack webpack-cli ---save
webpack.server.js
const Path = require("path");
const nodeExternals = require("webpack-node-externals");
module.exports = {
target: "node",
mode: "development",
entry: "./src/index.js",
output: {
filename: "bundle.js",
path: Path.resolve(__dirname, "build"),
},
externals: [nodeExternals()], // 防止react代码里面有node modules的模块不用处理,比如 express
module: {
rules: [
{
test: /\.js?$/,
loader: "babel-loader",
exclude: /node_modules/,
options: {
presets: [
"react",
"stage-0",
[
"env",
{
targets: {
browsers: ["last 2 versions"],
},
},
],
],
},
},
],
},
};
因为我们现在已经引入了webpack打包所以以下代码就可以改写
const express = require("express")
改写为
import express from "express";
const React = require("react");
const Home = () => {
return <div>home</div>;
};
export default Home;
//客户端渲染 // React代码在浏览器上执行,消耗的是用户浏览器的性能 //服务器端渲染 // React代码在服务器上执行,消耗的是服务器端的性能
解决在修改代码之后页面自动刷新
watch 是监听,就是监听 webpack 配置的 entry 入口文件以及该文件的依赖文件,只要检测到有变化 webpack都会帮你重新的编译一次。
"build": "webpack --config webpack.server.js --watch"
服务器自动重启
$: sudo npm install nodemon -g
"start": "nodemon build && node \"./build/bundle.js\"" , // nodemon会监听 build目录是否有变化,如果有变化就重新执行 node ./build/bundle.js 【\" 转译】
"start": "node ./build/bundle.js",
$: npm install npm-run-all -g
同构:一套React代码,在服务器端执行一次,再客户端再执行一次
const React = require("react");
const Home = () => {
return (
<div>
<div>welcome to my home!!</div>
<button
onClick={() => {
alert("click");
}}
>
click
</button>
</div>
);
};
export default Home;
以下警告hydrate
安装路由
commit提交详情
https://github.com/supermanklk/custom-ssr-server/commit/05db3201383f8ef9073f8d8c97fa8f629e9b0dae
$:npm install react-router-dom --save
服务器渲染只发生在我们第一次进入页面的时候
只有我们访问的第一个页面才会发生服务器渲染,之后所有的页面以及路由都是被浏览器接管
componentDidMount 不会在服务器渲染中执行
componentWillMount 会在服务器渲染中执行
react-router-dom 针对ssr渲染数据获取的解决方案:
https://v5.reactrouter.com/web/guides/server-rendering
1、 favicon处理,浏览器会偷偷发一个请求 favicon的请求,这个请求会到我们的接口里面,解决就是在public下面放一个图标。
2、多级路由问题处理
使用
区别
matchPath是匹配的外层路由, matchRoutes会匹配嵌套路由。
ps:目前 react-router-dom v6 已经支持 matchRoutes 了,之前是用的第三方的 react-router-config的 matchRoutes。
为什么在服务器做了数据渲染,打开页面会先白一会之后再出现数据。 而把页面javascript禁止掉就瞬间出来了?
闪白屏的效果图 http://faith-2021-001.oss-cn-hangzhou.aliyuncs.com/20220119/1642568511227845.gif
1、服务器ssr渲染时候已经加载了要渲染的数据 2、到客户端页面会重新渲染,此刻拿到的store是客户端的,此刻会空,因此页面会白 3、接下来客户端再渲染,拿到数据再渲染
数据脱水
/Users/xxxxxxxx/Desktop/xxxxxx/xxxxxx/server/src/store/index.js
export const getClientStore = () => {
// 数据脱水
// 我们把存储在window上的数据直接拿来用
const defaultStore = window.context.state;
return createStore(reducer, defaultStore, applyMiddleware(thunk));
};
数据注水
/Users/xxxxx/Desktop/xxxxxx/xxxxxxxx_project/server/src/server/utils.js
return `
<html>
<head></head>
<body>
<h1>ssr</h1>
<div id='root'>${content}</div>
<!--数据注水 -->
<script>
window.context = {
state: ${JSON.stringify(store.getState())}
}
</script>
<script src='./index.js'></script>
</body>
</html>
`;
1、如果一个组件始终在页面展示,比如header组件,不管怎样切换路由,都会被展示,那么该组件的数据请求只需要在server端请求就可以,就是loadData。
2、如果一个页面路由分为 【新闻、音乐、主页】, 那么他们都要在server和client执行,原因是如果首次渲染访问了音乐,那么此刻新闻就没被渲染,切换到新闻的时候就是本地client加载数据了。
SEO
1、title与 description的真正作用? 目前三代浏览器 title与 description 对网站的搜索引擎优化占了很少一部分的作用,它们的用处主要是用户搜到之后通过【更丰富的标题】与【更加详细的描述】增加点击率
2、如何做好SEO
文字优化
1、原创,中文翻译英文,翻译德语,翻译中文。
链接优化
1、链接上都是一类的网站, 比如你的教育网站,链接到游戏网站就不好。 链接分为外链与内链。 内链都是和网站相关的, 增加外链,别人的网站上有你的网站链接。
多媒体
1、图片高清、原创。 现在浏览器其实已经有识别媒体的能力。
3、通过 react-helmet 动态title与description
https://github.com/nfl/react-helmet
客户端使用
import React from "react";
import {Helmet} from "react-helmet";
class Application extends React.Component {
render () {
return (
<div className="application">
<Helmet>
<meta charSet="utf-8" />
<title>My Title</title>
<link rel="canonical" href="http://mysite.com/example" />
</Helmet>
...
</div>
);
}
};
Server Usage 服务器使用