最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • react ssr 服务端渲染入门

    正文概述 掘金(枣仁,)   2021-03-04   438

    react  ssr 服务端渲染入门

    react ssr 服务端渲染入门

    前言

    为什么要用服务端渲染?

    1. 加快首屏渲染,减少白屏时间

    与传统的web项目直接获取服务端渲染好的HTML不同,单页面应用使用JavaScript在脚本客户端生成HTML来呈现内容,用户需要等待JS解析执行完成后才能看到页面,这就使得白屏加载时间变长,影响用户体验。

    1. SEO 友好

    对于单页面应用,当搜索引擎的爬虫爬取网站HTMl文件时,通常情况下单页面应用中没有任何的内容,仅有<div id="root"> </div>这么一句话,从而影响排名。

    因此,业界借鉴传统的服务端渲染的方案,提出在服务端执行前端框架(React/Vue/Angular)代码生成HTML,然后将渲染好的HTML直接返回给客户端。

    react  ssr 服务端渲染入门

    [图片引自 www.jianshu.com/p/a3bce57e7…

    技术原理

    以React为例,首先我们让React代码在服务端执行一次,使得用户下载的HTML已经包含了所有的页面展示内容(达到新增SEO的目的)。同时,用户不需要等到JavaScript代码全部执行完就可以看到页面效果,增强用户体验。之后,我们让React在客户端再次执行,为HTML页面中的内容添加数据及事件的绑定,页面就具备了React的各种交互能力。

    react  ssr 服务端渲染入门

    核心API

    服务端:使用 ReactDOMServer.renderToString | ReactDOMServer.renderToNodeStream 生成HTML,并且在首次请求下发。

    客户端:使用 ReactDOM.hydrate 根据服务端返回的HTML进行 hydrate 操作。React 会尝试在已有标记上绑定事件监听器(从服务端返回的HTMl是不带任何事件的)。

    在SSR项目中渲染组件

    技术栈: React + Koa2 + Webpack

    1. 使用koa搭建服务端环境

    新建文件夹,并且初始化项目

    mkdir ssr-demo && cd ssr-demo
    
    npm init -y
    

    安装Koa环境

    cnpm install --save koa
    

    在项目根目录创建app.js,监听8888端口,当请求根目录时,返回一些HTML

    // app.js
    const Koa = require('koa');
    const app = new Koa();
    
    app.use(async (ctx) => {
      ctx.body = `
      <html>
         <head>
             <title>ssr demo</title>
         </head>
         <body>
            <div style="color: red"> Hello World </>
         </body>
      </html>
      `
    })
    
    app.listen(8888);
    console.log('app is starting at port 8888');
    

    在终端输入命令启动服务 node app.js

    访问本地的 http://localhost:8888/,可以看到HTMl返回了。

    react  ssr 服务端渲染入门

    2.在服务端编写React代码

    我们已经启动了一个Node服务器,下一步我们需要在服务器上编写React代码(也可以是Vue或者是其他框架语言),我们创建一个React组件,并且在App中返回。

    安装React环境,创建src/components文件夹,新建home.js文件

    cnpm install --save-dev React
    
    mkdir src && cd src && mkdir components && cd components && touch home.js
    

    用jsx编写一个最简单的React组件

    import React from 'react'
    
    const home = () => {
      return <div> This is a React Component</div>
    }
    
    export default home;
    

    并且在app.js中引用

    const Koa = require('koa');
    const { renderToString } = require('react-dom/server');
    const Home = require('./src/components/home');
    const app = new Koa();
    
    app.use(async (ctx) => {
      ctx.body = renderToString(<Home />)
    })
    
    app.listen(8888);
    console.log('app is starting at port 8888');
    

    然而这段代码并不会成功运行成功。原因如下

    1. 当前是在Node环境下,Node不能识别import和export。这二者属于ESM语法,而Node遵循的是common.js规范

    2. Node不能识别JSX语法

    为了方便起见,我们直接使用Babel的@babel/preset-env和@babel/preset-react预设。Babel的预设是一系列插件的集合。包括了用来转化成Commonjs的 babel-plugin-transform-modules-commonjs 插件,也包括了转化JSX的 babel-plugin-transform-react-jsx 等一系列插件)

    @babel/register

    这是 koa 官方给出的@babel/register使用方法,当我们引入了@babel/register之后,就会在require方法中注入Babel钩子,并且在运行时进行即时编译。

    require('babel-core/register');
    // require the rest of the app that needs to be transpiled after the hook
    const app = require('./app');
    

    所以需要对我们目前的内容进行改造

    app.js

    require('@babel/register');
    
    const app = require('./server').default;
    
    app.listen(8888);
    console.log('app is starting at port 8888');
    

    新建server.js

    const Koa = require('koa');
    import React from 'react';
    const { renderToString } = require('react-dom/server');
    const Home = require('./src/components/home').default;
    const app = new Koa();
    
    app.use(async (ctx) => {
      ctx.body = renderToString(<Home />)
    })
    
    app.listen(8001);
    console.log('app is starting at port 8888');
    export default app;
    
    
    
    

    在项目根目录上创建babel的配置文件 babel.config.js

    module.exports = function(api) {
      api.cache(true);
      return {
        presets: [
          ['@babel/preset-env', {
            targets: {
              node: true,
            },
            modules: 'commonjs',
            useBuiltIns: 'usage',
            corejs: { version: 3, proposals: true },
          }],
          '@babel/preset-react',
        ],
      }
    }
    

    当然,别忘记了安装相关的依赖

    npm install --save-dev @babel/core @babel/preset-env @babel/preset-react @babel/register react-dom
    

    大功告成! 运行 node app.js

    react  ssr 服务端渲染入门

    3.同构的概念

    通过上面的例子,我们已经能够将React组件渲染到页面。为了讲明白同构的概念,下面我们为组件绑定一个点击事件。

    import React from 'react';
    
    const Home = () => {
      return <div> This is a React Component
        <button onClick={()=>{alert('click')}}>click</button>
      </div>
    }
    
    export default Home;
    

    重新运行代码,刷新页面(由于我们的工程里没有集成热更新,所以每次修改还需要重启并且刷新页面)。我们会发现,点击按钮后onClick事件并不会执行。这是因为renderToString()方法只渲染了组件的内容,并不会绑定事件(DOM的宿主是浏览器)。因此我们需要将React代码在服务端执行一遍,在客户端再执行一遍,这种服务端和客户端公用一套代码的方式就称之为同构。

    4.在客户端执行React代码

    之前我们说过,React代码在服务端执行的时候只能返回HTML页面,但是不具备任何交互。需要我们将React代码在客户端重新再执行一遍,确保页面能响应onClick等事件。React提供了 hydrate 方法。

    ReactDOM.hydrate(element, container[, callback])
    

    新建client-ssr.js

    import React from 'react'
    import {hydrate} from 'react-dom'
    import Home from './src/components/home'
    
    hydrate(
       <Home />,
      document.getElementById('app')
    )
    

    新建template.js

    export default function template(content = "") {
      let page = `<!DOCTYPE html>
                  <html lang="en">
                  <head>
                    <meta charset="utf-8">
                    <link rel="stylesheet" href="assets/style.css">
                  </head>
                  <body>
                    <div id="app">
                      ${content}
                    </div>
                    <script src="/asset/client-ssr.js"></script>
                  </body>
                  `;
      return page;
    }
    

    修改server.js 将template的内容作为结果返回

    const Koa = require('koa');
    import React from 'react';
    import template from './template';
    const { renderToString } = require('react-dom/server');
    const Home = require('./src/components/home').default;
    const app = new Koa();
    
    app.use(async (ctx) => {
      ctx.body = template(renderToString(<Home />)) 
    })
    
    app.listen(8001);
    console.log('app is starting at port 8888');
    export default app;
    

    重启,发现报错了!

    react  ssr 服务端渲染入门

    由于我们的client-ssr中是React的JSX语法,直接返回给浏览器是解析不了的,需要用babel解析成浏览器能识别的JavaScript。

    webpack打包

    安装webpack依赖和命令行工具

    cnpm install --save-dev webpack webpack-cli
    

    新建webpack配置文件,另外我们需要安装babel-loader去解析我们的JSX语法

    const path = require('path');
    
    module.exports = {
      mode: 'development',
      entry: {
        client: './client-ssr',
      },
      output: {
        path: path.resolve(__dirname, 'asset'),
        filename: "[name].js"
      },
      module: {
        rules: [
          { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" }
        ]
     }
    }
    

    终端运行 npx webpack,打包client-ssr.js文件。

    使用koa-static指定根目录

    到目前为止,我们的文件已经准备好了。但是在访问的时候会发现,我们在template.js中的/asset/client.js文件并没有拿到。所以我们需要告诉当前服务,项目的根目录在哪里,服务端才能正确返回我们需要的文件,这里使用 koa-static 中间件。

    修改server.js

    import Koa from 'koa';
    import serve from 'koa-static';
    import path from 'path';
    import React from 'react';
    import template from './template';
    import { renderToString } from 'react-dom/server';
    import Home from './src/components/home';
    
    const app = new Koa();
    
    app.use(serve(path.resolve(__dirname)));
    
    app.use(async (ctx) => {
      ctx.body = template(renderToString(<Home />)) 
    })
    
    export default app;
    

    重新启动服务器,点击click按钮,成功了!再次在客户端渲染后,我们的页面能正常相应click事件了。

    react  ssr 服务端渲染入门


    起源地下载网 » react ssr 服务端渲染入门

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元