乐趣区

关于前端工程化:完全-Serverless-文档型动态站点强行变身超薄-SPA

道歉 ,用 Serverless 做这个题目次要是借势炒作。本文内容跟 Serverless 其实 没半毛钱关系

然而 2X 作者 为啥要起这个名字博眼球呢?

家喻户晓,Serverless 的概念并不像字面意义上那样的“无服务”,而是将中心化的服务端利用打散成为一个个函数式的服务,节约了前端编码到产品上线两头服务部署的操作老本。实质上是一种 云计算执行模型(Cloud Computing Execution Model)

聪慧的童鞋应该看完题目 和开篇第一张图 就猜到了我药里到底卖的什么葫芦 —— 本文内容其实是对于 SSG(Static Site Generation,动态站点生成) 的一个解决方案。介绍一下鄙人最近是如何将一个 Mongo + Egg + React + Node 架构的动静站点(外部非开源版本图表库官网)降 (mo) 级(gai)为纯动态 SPA(开源图表库 Cloud Charts 的官网站点)并部署在 github pages 上的(注:思考国内拜访问题,目前托管在 gitee 和 netlify)。

为了凸显计划的独特之处,顺便为开源我的项目引引流,未免要先阐明一下我所遇到的需要场景的复杂度和非典型性:

1. 需要介绍

1.1 背景

略微 介绍一下咱们目前正在折 (guan) 腾(shui)的一个 Github 开源我的项目:阿里云 Cloud Charts —— 又一个开源的信息可视化图表库。

家喻户晓,这绝壁 又双叒叕 是一群无良技工在 反复造轮子!这里是一段辛辣的讥刺)。

一段不正经的补充阐明:

  1. Cloud Charts 的前身是一套长期服务、利用于阿里云混合云场景的数据可视化解决方案(非开源版本),在日常工作中切实不便了很多不相熟前端工作的研发童鞋进行业务实际
  2. 咱们推出开源版本的其中一个目标,在于寻找更多适宜积淀的业务场景和更多气味相投的优良的小伙伴 -(^_^)/ 没错~ 就是你!

1.2 需要

在保护 Cloud Charts 开源我的项目的同时,咱们也须要将其内网版本的文档、示例、教程等材料同步搬运到公网,以不便公网用户对我的项目的理解和应用。

而对于 Cloud Charts 的开源版本(TXD Widgets),咱们曾经实现了一套用于托管相干文档和数据的官网站点(团体内网)。这个外部站点是基于 MongoDB + Egg.js + React.js 模式开发和保护的,最重要的一个特点是依附一个后盾管理系统,不便开发图表库的童鞋可能及时保护和公布图表库我的项目的性能个性和对应的教程、示例、API 文档等内容。

为了防止手动搬运内容、文档到外网所产生的费劲且繁琐的工作,更为了能将站点的原生性能、特点尽可能透出给外网用户,咱们心愿将这套站点(前台页面性能和内容)部署到外网。

通过一番探讨和思虑,咱们决定将原站点通过一系列工作流构建为一个 SPA 利用,不便疾速公布和更新到 github pages 类型的动态页面服务中(真 -Serverless ????????????)。

2. SSG 惯例计划钻研

针对两种支流的 SSG 模型进行剖析,咱们能够看到其各自的优缺点:

(1)基于构建时的 SSR(无头浏览器渲染后爬取动态内容)

  • 劣势

    • SEO 敌对
    • FCP 敌对(尤其当动静站点数据申请较大时)
  • 有余

    • 无奈无效还原对前端路由性能
    • 页面“爬取”工作耗时(尤其当动静站点的页面层级简单时)

(2)XPress 类型(如 VuePress Next 等框架)

  • 劣势

    • 开源框架较多、社区生态齐备
    • 提供部署到 github pages 等服务的能力
  • 有余

    • 与公司技术体系差别较大,须要框架迁徙和大量代码重构
    • 图表 API & 在线 Demo 等内容的输入是个超重的体力活

3. 另类计划的提出

内网站点的性能、复杂度如下图所示。

联合后面的相干剖析,咱们须要另辟蹊径,找到一条符合国情特色的倒退路线。通过肯定的业务形象和一段时间的技术尝试,咱们最终造成了一整套站点迁徙的技术计划。

咱们发现,动静站点要构建动态站点,最次要也是最重要的一环就是数据服务的动态化(即:数据接口的内容构建为可动态托管的前端资源)。

如上图所示,整个过程能够分为:数据动态化、静态数据加载、图片资源本地化、SPA 构建打包 共 4 个环节。上面的篇幅咱们将一一环节开展介绍,展示每个环节的具体内容、遇到的问题和相应解法。

4. 各环节姿态合成

4.1 数据资源的动态化

因为官网状态是比拟结构化的内容页面,咱们针对不同页面的特点、不同数据的关联关系,撰写了相应的浏览器脚本来模仿用户的点击、切换和跳转等行为。同时将 exceed 的数据申请记录下来(注:exceed 是一个 http 申请工具库,本质上是对 axios 的业务包装 – npm 地址),通过肯定解决后转存为本地数据(对敏感数据记录和字段进行过滤,将“申请参数 - 数据返回”以对应关系存储为本地 JSON 文件)。

动态化的数据格式形如:

// demo.json
[
  // 单个申请的动态化数据
  {
    // 查问的条件(申请的参数)params: {
      api: 'fetchAll',
      params: {module: 'studio'},
      data: {page: 1, size: 0},
    },
    // 查问的后果(申请的返回)response: {
      status: 0,
      message: 'success',
      data: [...],
    }
  },
  ...
]

4.2 加载静态数据

(1)页面挂载静态数据

SPA 页面加载时,先将动态化的数据加载到页面的 js 作用域中,便于数据查询方法的生产:

// 将静态数据解析为字典模式以不便查问(字典键值对的查问效率远高于列表)function parseGlobalData(list) {var globalData = {};
  list.forEach(function (x) {var key = objectToKey(x.params);
    if (!globalData[key]) {globalData[key] = x.response;
    }
  });
  return globalData;
}

// 将申请参数(一个 obj)转为字符串(base64),便于作为字典键值对中的键名
function objectToKey(obj) {return btoa(JSON.stringify(Object.entries(obj).sort()));
}

// 将静态数据挂载到页面的 js 全局变量
function appendGlobalData(data) {if (!window.staticGlobalData) {window.staticGlobalData = {};
  }
  window.staticGlobalData = Object.assign({},
    window.staticGlobalData,
    parseGlobalData(data)
  );
}

(2)革新 exceed.fetch 办法以生产全局数据

内网站点的数据是应用 exceed 类库申请后端接口进行异步加载的。在外网版本中,咱们应用 Proxy 的形式重写了 exceed.fetch 办法以从本地读取数据(后面环节产生的动态化数据)。原理示意如下:

// 判断是否为外网站点
if (isStaticSite()) {
  const handler = {apply: (target, thisCtx, [params]) => loadLocalData(params),
  };
  
  // 代理 exceed.fetch 办法以生产全局变量中的数据
  exceed.fetch = new Proxy(eceed.fetch, handler);
}

// 从全局变量中查问数据的办法
function loadLocalData(params) {const key = objectToKey(params);
  return window.staticGlobalData[key];
}

4.3 图片资源的本地化

在实现数据的本地化后,通过 nodejs 脚本实现能够匹配出官网所用到的全副图片资源(CDN 地址),对公网不能拜访的图片资源(如内网语雀、OSS 服务上的资源)进行本地化转存。

4.4 SPA 构建打包

  • 将内网站点的前端 router 革新为兼容 SPA 的模式
  • 另起一个 SPA 我的项目用于构建公网版本
  • 通过 nodejs 脚本实现将内网站点须要透出局部模块的源码“一键”同步到 SPA 工程中
  • 通过 SPA 工程构建最终的线上环境代码

5. 后果展现

Cloud Charts 官网地址

内、外版本的站点比拟成果如下(仅不便展现局部首页内容):

能够看到,内网版本中图表库须要的重要功能模块都被原滋原味地还原、构建到外网站点中了(不可对外输入的局部在 SPA 构建时曾经做了无效的过滤解决)。

6. 计划总结 & 改良方向

写在前面:本文次要介绍 SSG 的技术计划和一些关键环节的奇技淫巧。SSG 的过程中其实还有很多细节问题,如:如何在一套代码中保护内、外网不同版本的内容差别等。感兴趣的童鞋欢送留言探讨。

退出移动版