服务端渲染-简介
2020-07-28 11:15:282020-10-16 17:32:50
什么是SSR
SSR
(server side rendering),服务端渲染。当后端/服务器接收到网络请求后,生成(渲染)HTML
字符串,将它们直接发送到浏览器
与之对立的则是CSR
(client side rendering),客户端渲染。后端不提供完整的html
页面,而是提供一些api
使得前端可以获取json
数据,然后前端拿到json
数据之后再在前端进行html
页面拼接,然后展示在浏览器上。这种是客户端渲染。这样前端就可以专注UI
的开发,后端专注逻辑开发。典型的应用是SPA
CSR
和SSR
最大的区别在于前者的页面渲染是JS
负责进行的,而后者是服务器端直接返回HTML让浏览器直接渲染
为什么要有SSR
传统CSR的弊端不容小觑:
- 首屏加载缓慢
- 对于SEO无能为力
怎么做SSR
原理(基于React.js)
编写一个简单的
React
组件使用
react-dom/server
中的renderToString
编译虚拟DOM
将转换后的
DOM
插入html
中返回给前端// containers/Home.js import React from 'react'; const Home = () => { return ( <div> <div>This is sanyuan</div> </div> ) } export default Home // server/index.js import express from 'express'; import { renderToString } from 'react-dom/server'; import Home from './containers/Home'; const app = express(); const content = renderToString(<Home />); app.get('/', function (req, res) { res.send( ` <html> <head> <title>ssr</title> </head> <body> <div id="root">${content}</div> </body> </html> ` ); }) app.listen(3001, () => { console.log('listen:3001') })
此时已实现一个简单的SSR,但对于一些常见的场景如事件绑定无效,这时就需要进行了同构。所谓同构,通俗的讲,就是一套React
代码在服务器上运行一遍,到达浏览器又运行一遍。服务端渲染完成页面结构,浏览器端渲染完成事件绑定。这样的话就需要浏览器去拉取额外的JS文件,由JS来完成一些复杂的事情
使用
react-dom
关联DOM
与JS
使用
webpack
打包JS
开启
express
的静态服务// client/index. js import React from 'react'; import ReactDom from 'react-dom'; import Home from '../containers/Home'; ReactDom.hydrate(<Home />, document.getElementById('root')) // webpack.client.js const path = require('path'); const merge = require('webpack-merge'); const config = require('./webpack.base'); const clientConfig = { mode: 'development', entry: './src/client/index.js', output: { filename: 'index.js', path: path.resolve(__dirname, 'public') }, } module.exports = merge(config, clientConfig); //webpack.base.js module.exports = { module: { rules: [{ test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/, options: { presets: ['@babel/preset-react', ['@babel/preset-env', { targets: { browsers: ['last 2 versions'] } }]] } }] } } // package.json "scripts": { "dev": "npm-run-all --parallel dev:**", "dev:start": "nodemon --watch build --exec node \"./build/bundle.js\"", "dev:build:server": "webpack --config webpack.server.js --watch", "dev:build:client": "webpack --config webpack.client.js --watch" } // server/index.js const app = express(); app.use(express.static('public'));
三方框架
Ref: