Next.js 在 Serverless 中从踩坑到破茧重生
作者
杨苏博,偏后端的全栈开发,目前负责腾云扣钉的 Cloud Studio 产品。在团队中负责接技术架构设计与 Review、Cloud Studio 编辑器内核设计与开发、部分核心插件设计与开发;对 WebIDE 领域中的 VS Code 和 Theia IDE 有深入研究与丰富实践;多年 Serverless 领域从业经验,是 Serverless First Malagu 开源框架的作者;热爱开源,敢于创新。
前言
Next.js 是由 Vercel 团队研发的一款全栈应用开发框架。我们使用 Next.js 开发前端页面以及一些轻量级的后端 API。前端和后端都用 Javascript 技术栈,并且是前后端一体化的(在同一个项目中开发前后端)。另一个被大家所熟知的特性是它的服务端渲染能力,对 SEO 友好。
Vercel 自身是一个用户体验极佳的 Serverless 平台,支持包括 Next.js 在内的几十框开发框架一键部署到 Vercel 平台。Vercel 平台自身拥有极强的适配扩展能力,第三方框架可以按照 Vercel 平台的适配规则自主进行适配。
作为 Vercel 亲儿子的 Next.js 可以完美适配 Vercel 平台,通过 Next.js + Vercel,让开发和部署体验都能拥有极致的体验。Vercel 团队信奉着 “吃自己的狗粮” 原则,Vercel 自身很多应用都是基于自己的工具和平台开发的。
美中不足
Next.js + Vercel 看起来是如此的完美:通过 Vercel CLI 一键部署 Next.js 到 Vercel。另外,Next.js 也能很方便地运行在云主机上。但是 Vercel 作为国外的 Serverless 平台,对于国内用户,总是存在种种难以逾越的限制。如何将 Next.js 完美运行在国内的 Serverless 平台变得尤为重要。
国内 Serverless 平台官方在如何让 Next.js 运行起来各显神通。让 Next.js 在 Serverless 平台上运行不难,而要做到像 Vercel 一样的极致部署运行体验却很有挑战。
在尝试将 Next.js 部署到国内 Serverless 平台的时候,比如腾讯云函数、阿里云函数计算,可能会遇到如下一些坑:
运行适配困难
Next.js 的运行需要一个 HTTP Server,而事件函数提供的是一个简单签名函数,无法直接运行,需要将事件函数模拟成一个近似 HTTP Server 的代理服务;
代码体积过大
一个最简单的 Next.js 应用的代码体积为 245 MB 左右,打包压缩后是 54 MB 左右,而函数代码体积限制一般是在 50 MB 以内(阿里云函数计算通过 OSS 方式上传代码可以超过 50 MB 的限制,但不能超过 100 MB)。代码体积过大往往带来一系列副作用:
代码上传时间长,且容易失败,部署成本变大(通过 NFS 和 Layer 解决);
依赖更多云服务,如使用对象存储服务部署代码包,又或者把体积大的 node_modules 目录上传到 NFS 服务上,然后挂载到函数上。总之,让应用架构变复杂;
冷启动时间变长,函数在第一次运行的时候,需要先加载远端的代码,如果代码包越大,则冷启动时间越长;
不过,通过腾讯云的 Web 函数和阿里云函数计算的 Custom Runtime,可以解决第一个问题,因为它允许我们运行一个真正的 HTTP Server。而第二个问题要困难很多,虽然其中部分问题可以通过一定手段缓解,比如冷启动,可以通过预置并发解决,但是又会让运行成本变得难以接受。所以解决问题的根本还是在代码体积上。
为什么 Next.js 项目代码体积大
为了分析这个问题,我们需要先了解 Next.js 的架构。Next.js 是一种 React 的服务端渲染框架,集成度极高,框架自身集成了 Webpack、SWC、Babel、Express 等,使得开发者仅依赖 Next、React 和 React-dom 就可以方便地构建自己的 SSR React 应用,我们甚至可以不用关心路由。Next.js 的高度集成性,易于实现代码分割、路由跳转、热更新、服务端渲染和前端渲染。
在 Next.js 项目中,不仅仅包含了运行时所需要的依赖,还包含了本地开发、构建所需要的开发时依赖,而且开发时依赖体积又大,而我们常见的解决方案是简单粗暴打包所有的依赖,从而导致 Next.js 项目代码偏大。
Vercel 官方如何打包部署 Next.js
Vercel 官方打包部署 Next.js 方案比较复杂。Vercel 平台底层基础设施是集成了 AWS Lambda,Next.js 本质是部署在 AWS Lambda 平台上。为了能让 Next.js 能在 Lambda 上运行,Vercel 官方提供了一个专门用于构建 Next.js 项目的构建器:@vercel/next
。该构建器的逻辑大致是把 Next.js 中的每一个 API 和服务端渲染的页面都分别构建输出为一个函数,这一系列函数都归属与 Vercel 平台上的一个应用。所以这样就保证了每个函数的代码体积足够的小。
Next.js 打包部署到国内 Serverless 平台最佳实践
解决函数适配困难:我们可以通过 Web 函数或者 Custom Runtime 来解决,不推荐使用自定义镜像方式,因为自定义镜像冷启动很严重。并在其中运行一个 HTTP Server,且简单适配 Next.js。Next.js 官方有示例。
解决代码包体积过大问题:剔除掉运行时不需要的可选依赖和开发依赖,剔除方式如下:
npm install --omit optional --omit dev
# 或者
yarn install --ignore-optional --prod
说明:因为 swc 构建工具是通过可选依赖安装的,在运行时不需要,所以我们需要把可选依赖也剔除。
通过以上方式构来的代码体积由原来的 54 MB 减小到了 18 MB。另外,值得一提的是阿里云函数计算 Custom Runtime 内置的 Node.js 版本为 v10.16.2,而 Next.js 最新版本要求必须是 Node.js 12.22.0+。所有直接部署在函数计算的 Custom Runtime 上的 Next.js 应用无法运行,此时我们就需要自行将 Node.js 的二进制下载到我们自己的代码中(也可以通过 Layer 实现),然后指定新的 PATH 环境变量。
如果每次部需要做上面的操作是不是很繁琐,而且还需要自己写适配入口代码,以及 Web 函数和 Custom Runtime 所必须的 bootstrap 文件,且该文件必须拥有可执行权限,额外安装新版 Node.js 运行时。其实,这些能力在 Cloud Studio 云开发平台中已经内置提供了。一个原生的 Next.js 应用,使用 Cloud Studio 云开发平台可以一键部署到腾讯云函数或者阿里函数计算,对业务代码零侵入,零门槛。只需如下几步:
1.登录进入 Cloud Studio 的 Dashboard 页面
2.选择 Next.js 模板,并创建一个工作空间
3.切换到 Cloud Studio 云部署套件视图
4.选择腾讯云部署选项,并微信扫描登录
5.点击【开始部署】按钮,一键部署 Next.js 应用
6.点击【访问】按钮,即刻预览部署后的效果
说明:同样的 Next.js 应用,无需做任何修改,采用上述一样的步骤,一键部署到阿里云函数计算。
Cloud Studio 是基于浏览器的集成式开发环境(IDE),为开发者提供了一个永不间断的云端工作站。其包含代码高亮、自动补全、Git 集成、终端等 IDE 的基础功能,同时支持实时调试、插件扩展等,可以帮助开发者快速完成各种应用的开发、编译与部署工作。用户在使用 Cloud Studio 时无需安装,随时随地打开浏览器就能使用。
目前 Cloud Studio 支持部署到腾讯云函数和阿里云函数计算。并且支持 15+ 前后端框架的一键部署。
写在最后
开始胡乱打包,到后面的精致打包,让代码体积变小,从而避免了一些列的坑。至于我们为什么不采用像 Vercel 那样的极致方案,原因有三点:实现成本太高、对 Next.js API 深度依赖,维护成本高和构建成多个函数管理成本极大(我们不可能想 Vercel 一样提供一个高阶平台)。通过 Cloud Studio 云开发平台,我们可以一键部署 Next.js 等流行框架,对框架零改造。
关于我们
更多关于云原生的案例和知识,可关注同名【腾讯云原生】公众号~
福利:
①公众号后台回复【手册】,可获得《腾讯云原生路线图手册》&《腾讯云原生最佳实践》~
②公众号后台回复【系列】,可获得《15个系列100+篇超实用云原生原创干货合集》,包含Kubernetes 降本增效、K8s 性能优化实践、最佳实践等系列。
③公众号后台回复【白皮书】,可获得《腾讯云容器安全白皮书》&《降本之源-云原生成本管理白皮书v1.0》
④公众号后台回复【光速入门】,可获得腾讯云专家5万字精华教程,光速入门Prometheus和Grafana。
【腾讯云原生】云说新品、云研新术、云游新活、云赏资讯,扫码关注同名公众号,及时获取更多干货!!
Next.js 在 Serverless 中从踩坑到破茧重生的更多相关文章
- 对称加密算法在C#中的踩坑日常
前言 有幸接触了一下传说中的对称加密算法3DES 感觉这些加密算法与我的工作是想去甚远的,一般没什么机会接触这些东西 今次了解了一下3DES这个对称算法 原理算不上明白,算是踩了C#中的一些坑吧 C# ...
- 避坑手册 | JAVA编码中容易踩坑的十大陷阱
JAVA编码中存在一些容易被人忽视的陷阱,稍不留神可能就会跌落其中,给项目的稳定运行埋下隐患.此外,这些陷阱也是面试的时候面试官比较喜欢问的问题. 本文对这些陷阱进行了统一的整理,让你知道应该如何避免 ...
- 前端坑多:使用js模拟按键输入的踩坑记录
坑 一开始在Google搜索了一番,找到了用jQuery的方案,代码量很少,看起来很美好很不错,结果,根本没用-- 我反复试了这几个版本: var e = $.Event('keyup') e.key ...
- python学习过程中的踩坑记录<若干,随时更新>
问题1:python中print的连串输出与java不一样? 输入print(code +"+++"); --在代码中写入,界面未报错,但是告诉你不行 会报错,如图: 解决办法: ...
- Vue中axios踩坑之路-POST传参
https://blog.csdn.net/call_me_fly/article/details/79012581
- router路由去掉#!的踩坑记
项目中在研究去掉router#!的过程中的踩坑过程.
- vue.js 踩坑第一步 利用vue-cli vue-router搭建一个带有底部导航栏移动前端项目
vue.js学习 踩坑第一步 1.首先安装vue-cli脚手架 不多赘述,主要参考WiseWrong 的 Vue 爬坑之路(一)-- 使用 vue-cli 搭建项目 2.项目呈现效果 项目呈现网址:w ...
- 『vue踩坑日常』 在index.html中引入静态文件不生效
Vue日常踩坑日常 -- 在index.html中引入静态文件不生效问题 本文针对的是Vue小白,不喜勿喷,谢谢 出现该问题的标志如下 控制台warning(Resource interpreted ...
- 微信小程序使用pako.js的踩坑笔记
问题 今天组长跟我们讨论了个问题,说是文章存储占用有点大,消耗宽带流量费,让我看看能不能找个方法解决一下(文章存储的是html字符串).第一反应是没什么头绪,能想到的就是将相同的字符串替换成一个标识之 ...
随机推荐
- spring-boot-learning-spring Security
SpringSecurity的简单原理: 一旦启用了Spring Security,Spring IoC容器就会为你创建一个名称为springSecurityFilterChain 的Spring B ...
- C语言 | 栈的应用 | 非递归栈实现快排
/* 非递归栈实现快排 */ #include <stdio.h> #include <math.h>> #include <malloc.h> #inclu ...
- vue重构--H5--canvas实现粒子时钟
上一篇文章讲解了如何用js+canvas实现粒子时钟,本篇文章 ,主要是使用vue重构,让它在vue也能使用. 我们使用简单的方式重构,不使用vue工程,先加入vue cdn的地址,如下: <s ...
- 【uniapp 开发】如何给边框添加阴影效果
css的box-shadow是用来添加边框阴影效果的. 属性值详解: 1.inset 可选值,默认阴影在盒子外 使用inset后,阴影在盒子内,即使指定边框或者透明边框,阴影依然存在. 2. 这是头两 ...
- 输入n,然后输入n个数,使它升序输出
#include<iostream> using namespace std; int main() { int n,i,j,m,k; cin>>n; int a[n]; f ...
- python---快速排序的实现
def quick_sort(alist, start, end): """快速排序""" # 递归退出 if start >= en ...
- data_loader读取器
import random import numpy as np import pandas as pd import cv2 def date_loader(image_dir, file_name ...
- 在Blazor中实现拖放(drag and drop)
前言 我在实现一个含有待办列表功能的页面时,发现了一个好看的设计,它将待办分为--"待办","正在进行",和"已完成"三种状态,并且将待办通 ...
- No package XXX available 解决方法
当前yum源找不到所需包,安装epel源即可 yum install -y epel-release EPEL 的全称叫 Extra Packages for Enterprise Linux.EPE ...
- OpenHarmony标准设备应用开发(二)——布局、动画与音乐
(以下内容来自开发者分享,不代表 OpenHarmony 项目群工作委员会观点) 邢碌 上一章我们讲解了应用编译环境准备,设备编译环境准备,开发板烧录,将一个最简单的 OpenAtom OpenHar ...