服务器端渲染(SSR)与React从头开始
#javascript #网络开发人员 #react #前端

Woovi的核心功能是我们的付款链接。这是一种在网络上任何地方销售的简便方法,您不需要网站或其他任何东西。只需发送链接并获得付款即可。

为什么使用服务器端渲染?

如何确保通过网络共享此链接的良好用户体验?我想显示与该费用相关的QR码,并且在网上将其发送到任何地方时,它应显示与该HTML页面相关的OGS和Metatags。

您没有一个客户端渲染页面,因为您在访问页面之前无法存储这些引用。

这就是为什么我们选择SSR通过CSR进行付款链接的原因。我们要确保在网络上的任何位置,如果您共享链接,则应显示:付款链接的正确标题,QR码作为OG映像和任何其他动态元数据。

An example of OG tag in WhatsApp

启动服务器

最初的步骤是创建我们的入口点,从该页面渲染的位置。在这种情况下,我们将使用koude0框架。

// index.ts
import Router from '@koa/router';
import Koa from 'koa';
import bodyparser from 'koa-bodyparser';

const router = new Router();
const app = new Koa();

router.get('/(.*)', async (ctx) => {
  ctx.status = 200;
  ctx.body = 'OK';
});

app.use(bodyparser());
app.use(router.routes());
app.use(router.allowedMethods());

export default app;

我们在这里做的是:创建一个新的端点,该端点捕获所有请求并用OK主体返回200。如果用户击中了//foo/bar,它将得到相同的响应。

现在,要运行服务器并打开端口以访问服务器,您可以在下面运行代码:

// index.ts
import http from 'http';

const currentHandler = app.callback();
const server = http.createServer(app.callback());

server.listen(4000, (error) => {
  console.log(error);
});

现在,我们可以运行所有这些服务器到达端口4000。如果要测试,请使用koude6或您想要的任何其他方式构建它,例如ts-node

渲染UI

现在,我们需要的是渲染我们的反应组件的一种方法,对吗?因此,想法是使用react-dom/server提供的解决方案并处理它。让我们看看下面的代码:

// index.ts
import Koa from 'koa';
import Router from '@koa/router';
import http from 'http';
import { renderToPipeableStream } from 'react-dom/server';

import { App } from './App';

const router = new Router();
const app = new Koa();

router.get('/(.*)', async (ctx) => {
  let didError = false;
  try {
    // Wraps into a promise to force Koa to wait for the render to finish
    return new Promise((_resolve, reject) => {
      const { pipe, abort } = renderToPipeableStream(
        <App />,
        {
          bootstrapModules: ['./client.js'],
          onShellReady() {
            ctx.respond = false;
            ctx.status = didError ? 500 : 200;
            ctx.set('Content-Type', 'text/html');
            pipe(ctx.res);
            ctx.res.end();
          },
          onShellError() {
            ctx.status = 500;
            abort();
            didError = true;
            ctx.set('Content-Type', 'text/html');
            ctx.body = '<!doctype html><p>Loading...</p><script src="clientrender.js"></script>';
            reject();
          },
          onError(error) {
            didError = true;
            console.error(error);
            reject();
          }
        },
      );

      setTimeout(() => {
        abort();
      }, 10_000);
    })
  } catch (err) {
    console.log(err);
    ctx.status = 500;
    ctx.body = 'Internal Server Error';
  }
});

app.use(router.routes());
app.use(router.allowedMethods());

const server = http.createServer(app.callback());

server.listen(3000, () => {
  console.log('Server listening on port 3000');
});

我们在这里做的是:使用onShellReady函数,我们将块插入可写的流并完成响应。它将解析悬念组件并为最终用户显示。

我们需要将此流程包装到Promise中,以确保KOA等到诺言的解决方案,这意味着可写的流的分辨率,返回正确的HTML代码。

App组件是您的根项目,在示例的情况下,我只是编写一个Hello, world!,因为您可以看到here。但是您可以插入任何想要的东西。

您可以看到here代码。

综上所述

使用此简单的设置,您可以手中有一个功能强大的工具,为我们的最终用户提供更好的体验,为他们提供更好的SEO,快速的加载时间以及SSR在某些特定情况下为我们带来的其他有用的东西。

但是一个有效的问题是:为什么不使用像Handlebars这样的模板?对于Woovi内部的用例,模板不会帮助我们,因为我们需要两个核心点:重新使用我们的设计系统并确保在我们的付款链接中使用GraphQL。

在Woovi内部,我们的整个代码库是使用Relay client framework通过GraphQl管理的。为了确保最终用户的最佳UX可能,我们在付款链接中提供了一些有用的功能,例如支付费用后的实时更新。所有这些都由我们的GraphQl处理,在我们的用例中,模板无法解决。

这是关于我们如何在内部处理SSR的东西的概述。要成为生产的代码,有一些需要完成的渐进的事情。

关于我们

Woovi是一家创业公司,使购物者能够按照自己的要求付款。为了实现这一目标,Woovi为商人提供即时付款解决方案接受订单。

如果您想面临良好的挑战,例如使用从头开始使用服务器端渲染 + graphql创建强大的解决方案,请加入我们!

我们是hiring