ICEBREAKER / NOTES
返回归档

在Serverless部署proxy助力前端开发

探讨Serverless架构下的前端部署方式

#! https://zhuanlan.zhihu.com/p/402874502head image

在 Serverless 部署 proxy 助力前端开发

前言

我们前端开发人员,在开发中,经常会遇到跨域问题。

跨域问题实际上是浏览器自个加的限制,主要目的就是为了保障用户信息的安全,详见浏览器的同源策略

例如,前端页面在本地起在8080端口,起的后端部署在本地3000 端口,8080 发送 xhr 到 3000,结果就因为跨域策略挂了。

这时候我们通常会使用 2 种方式来帮我们解决:

  • 一种 服务端设置 CORS 策略来帮我们解决 (下文不涉及 jsonp )
    CORS 全称 Cross-Origin Resource Sharing,跨域资源共享
    它由众多的请求头组成,详见 MDN
  • 另一种 就是在开发时候,使用正向代理 (proxy) , 来帮助我们解决跨域问题。

这 2 种方式都是服务端的解决方案。

值得一提的是, Chrome 新的默认 Referrer-Policy : strict-origin-when-cross-origin , 在请求的 credentials mode 是 include (XMLHttpRequest.withCredentials) 的情况下,Access-Control-Allow-Origin: * 默认是禁止的,必须显式声明

前端代理

刚刚也说过浏览器的同源策略,是自己给自己的一个限制,

所以我们可以在服务端自定义 http 请求,来绕过这一层限制,这就是使用正向代理的本质。

以前端最熟悉的 webpack-dev-server 配置为例:

js
// webpack.config.js
module.exports = {
  //...
  devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        pathRewrite: { '^/api': '' }
      },
      '/baidu': {
        target: 'https://www.baidu.com',
        changeOrigin: true
      }
    }
  }
}

原理实际上非常简单,同源请求在 webpack-dev-server 的 http-proxy-middleware 中转化成服务端 http 请求,代理到目标域名那去罢了。

一图以蔽之:

webpack-dev-server proxy 原理

serverless 上构建 proxy

假如我们要把,本地的 webpack-dev-server 的 proxy 效果,直接部署到公网上,该怎么办呢?

最快的方式,就是,依靠 serverless framework , 直接把整个站 (包括前后端),部署到腾讯 SCF 平台,来作为我们线上网站的代理

主要有 2 种做法:

一种以使用 网站和 SCF 不同域名的方式来部署

另一种使用 网站和 SCF 相同域名的方式来部署

下面简称 多域名模式, 和 单域名模式

多域名模式

废话不多说,直接上图

多域名模式

这里我们把网站的静态资源,上传到 COS 上,再同步到 CDN。

这样我们的网站实际部署在 CDN 上,给 CDN 配置域名之后,我们也只需要设置我们 SCF 绑定的 API网关 的 cors 策略,把我们的域名加进去就可以。

这样用户从 CDN 获取页面和静态资源后,再向 SCF绑定的API网关域名发送跨站请求,以此达到代理的目的。

单域名模式

单域名模式就有些不同点了,还是看图

单域名模式

这里我们把网站的,除了作为入口的index.html, 其他的静态资源都上传到 COS 上,再同步到 CDN 那。

SCF 当然可以去返回静态资源,就是有点浪费算力。

这里我们把 index.html 放入了 SCF 内部,这样用户直接访问 API网关 的地址,就可以通过 static 中间件 + history fallback(router history mode) , 把页面返回给前端。

这里的 CDN 需要配置 CORS 策略,把 API网关 所绑定的自定义域名,设置进 CDN->高级配置 中的 HTTP响应头配置 规则里。

在图上可以看到,用户在访问 SCF 中的页面,以及向SCF发送请求的时候,都是走的同源的请求。

模式总结

可以看到,这 2 种模式都各有优劣,

  1. 对于我们部署静态网站或者资源来说,CDN 还是必不可少的,毕竟不同网络节点多,速度快,可以有效减少用户等待时间。
  2. 都需要配置 CORS 策略,只不过多域名模式,CORS 策略需要在 API 网关,或者SCF 内部代码中设置,单域名模式 , 其他静态资源的 CORS 策略 需要在CDN那里配置。

这篇文章最终写下来,实际上是探讨的在 Serverless 架构中,如何部署前端的方式。

假如我们使用的是服务端渲染 (SSR),可以看做成 单域名模式 的一种衍生,CDN作为动静分离的一种方式,内部动态的部分,还是放在SCF内部,交给它做渲染。

参考配置和实现代码

yaml
component: scf
name: sit-history-proxy

inputs:
  src:
    src: ./
    exclude:
      - .env
      - node_modules/**
      - yarn.lock
  type: web
  name: ${name}-function
  region: ap-shanghai
  runtime: Nodejs12.16
  installDependency: true
  entryFile: src/app.js
  eip: true
  environment:
    variables:
      NODE_ENV: production
  events:
    - apigw:
        parameters:
          protocols:
            - http
            - https
          environment: release
          endpoints:
            - path: /
              method: ANY

附代码

阅读设置

正文字号

设置会保存在当前浏览器。