duuliy

手写SSR

2022-6-11

前提

写一篇全网最简单的手写ssr的文章,能看见,都靠缘分,毕竟本人很懒, 然后纯手打,传递概念,也没有商业用途,拜托喜欢挑刺命名啊等等的吹毛求疵,喜欢pua大佬离我远点,我谢谢你了,别看。。。
还有来找我博客网站的bug的大佬,我就是用hexo生成,有bug我就不改,就问你气不气?哈哈哈哈😂

关于SSR

相信很多人做seo都会用到SSR吧,对,曾今几年前我也做过2个nuxt.js 的项目,但是没有研究过原理。如今出现了SSG,ISR,DPR,不了解查一下,不缀述了。

关于SSR框架

Universal/nuxt/next/ice/VitePress 等等,轮子造的非常好对吧,商用的产品也不少,但是跟umi一样,打包后都会有框架代码,大堆api,至少也有几天的学习成本吧,
最最最重要的喜欢折腾的程序员喜欢极客,喜欢高定。。。但是诸多概念,设计,模型,性能,扩展性…..等等等,产出一个可以满足公司商用的SSR框架,可比单纯的一个
webpack脚手架可难多了,可是想成为专家,架构师,由兴趣驱动来做这件事不也相当nice吗?

手写SSR原理

由于我比较熟悉react,所以在react上面+ssr来记录下原理吧。

前置知识点:ReactDom.hydrate, react-dom/server/renderToString

先总结原理:
1.把client代理利用webpack+hydrate 打包起来,为水合js作准备。
2.利用renderToString在server生成html,为水合基座页面。

client:


// index.js
function App() {
  return <p>利用水合反应向react的SSR注入js</p>
&#125;

ReactDom.hydrate(App, document.getElementById('root'))

// webpack.client.js
const path = require('path')

module.exports = &#123;
  mode: "development",
  entry: './src/index.js',
  output: &#123;
    filename: 'dist.js',
    path: path.resolve(__dirname, 'public')
  &#125;,
  module: &#123;
    rules: [
      &#123;
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules/,
        options: &#123;
          presets: ['@babel/preset-react', ['@babel/preset-env']]
        &#125;
      &#125;
    ]
  &#125;
&#125;

server:

// index.js
import path from 'path'
import React from 'react'
import &#123; renderToString &#125; from 'react-dom/server'
import express from 'express'

const app = express()
app.use(express.static('public'))

const App=()=>&#123;
  return '服务端渲染静态内容'
&#125;


app.get('/', (req, res) => &#123;
  const content = renderToString(<App />)
  res.send(`
    <html>
      <head>
        <meta charset="utf-8"/>  
      </head>
      <body>
        <div id="component">$&#123;content&#125;</div>
        <div id="root"></div> 
        <script src="/bundle.js"></script>
      </body>
    </html>`)
&#125;)  
app.listen(8888, () => &#123;
  console.log(666)
&#125;)

//webpack.server.js
// 参考webpack.client.js ,server也需要用babel处理的

接下来跑起来或者用nginx试试吧

扩展

妥妥跟mvvm一样,属于系统内架构。

欢迎有兴趣的伙伴来联系我,我们可以一起拓展,来写:

  1. SSG,ISG,DPR 模式,搭配monorepo,搭配微服务等。
  2. 开源基础模式。
  3. 针对行业,高定商用框架。

也许在未来我也会一个人去做这件事…