CSR
(Client Side Rendering)就是在浏览器从服务器中获取到的只是一个带有空 div 标签的 html 文件,然后执行 js 文件生成 dom 和操作 dom,日常中开发的后台管理类的系统大多都是 CSR 的模式。
SSR
(Server Side Rendering)是在服务端已经完成渲染工作,浏览器从服务器获得的是完整的网页的 dom 字符串。不同于以前通过后端模板等方案生成页面,现在的 React、Vue、Svelte 等优秀框架都有 SSR 的解决方案。
关于这个问题尤大在 Vue SSR 指南中也给出了答案。
SSR 对比 CSR 的优点:
当然 SSR 对比 CSR 也有一些缺点:
所以在选择技术栈的时候可以根据项目需求去选择,如果对 SEO 和加载速度有要求的时候就可以使用 SSR。反之如果没有 SEO 或首屏加载优化等需求,使用 SSR 也可能是一种负担。
more:
如果单纯的想对个别数据变动不频繁的页面做 SEO,可以考虑预渲染的方案,毕竟 SSR 的成本是相对较高的。
XMLSerializer
API 进行处理最后生成静态 html 字符串。下图来自 Vue 官网,详细展示了 SSR 项目的构建流程,虽然 React 和 Vue 的实现方式略有不同,但是整体思路也是如此:
由上图也可以初步新建如下的文件目录:
.
├── build
│ ├── base.config.js
│ ├── client.config.js
│ └── server.config.js
├── entry
│ ├── server-entry.jsx
│ └── client-entry.jsx
├── server
│ └── app.js
└── web├── components│ └── Test.jsx├── index.jsx└── pages└── Index.jsx
webpack 构建主要是把 web 目录下的文件分别通过 client 和 server 的配置打包成两份代码,这里不再介绍客户端代码的打包,主要介绍一下服务端代码的打包。
const WebpackChain = require('webpack-chain');
const nodeExternals = require('webpack-node-externals');
const {resolvePath,isDev
} = require('./utils');
module.exports = {getServerConfig: function() {const chain = new WebpackChain();chain.entry('server').add(resolvePath('entry/server-entry.js')).end().output.path(resolvePath('dist/server')).filename('[name].js').libraryTarget('commonjs2').end().when(isDev, function(chain) {chain.watch(true);}).target('node').externals(nodeExternals({allowlist: [/.(css|less|sass|scss)$/]}));return chain.toConfig();}
}
可以看到,服务器端打包和客户端的打包有一点区别:
node
,webpack 将在类 Node.js 环境编译代码。(使用 Node.js 的 require
加载 chunk,而不加载任何内置模块,如 fs
或 path
)。每个target都包含各种 deployment(部署)/environment(环境)特定的附加项,以满足其需求。在开始编写代码之前,我们需要了解react实现服务端渲染必须的几个 API,参考 ReactDOMServer
function Comp () {return ( 123)
}
renderToString( ); // 返回 123
可读流
ReactDOM.hydrate()
已经具有此服务器渲染标记的节点,React 将保留它并仅附加事件处理程序,从而使您获得非常出色的首次加载体验。在 SSR 应用中使用hydrate
替代render