这么多人用Codesandbox,他服务器扛得住么?( 二 )


所以,基于Cloud Sandbox启动的项目确实会占用服务端资源 。具体来说,每个项目会分配:

  • CPU:2个虚拟 CPU(vCPUs)
  • 内存:2GB
  • 存储:6GB
这块是codesandbox公司的核心业务 。毕竟,免费试用满意后,可能就会上付费的Pro版(更多资源分配),或者团队定制版 。商业模式与Vercel类似 —— 提供免费基础服务(自担部分资源费用),通过增值的云服务收费 。
而前端开发日常使用codesandbox创建的项目,大多数并不是基于Cloud Sandbox,而是基于Browser Sandbox启动的 。这些项目并不会给codesandbox带来太多服务端压力 。
两种sandbox的区别有个很直观的方式区分两种Sandbox —— 当我们新建一个codesandbox项目,在预览区域可以看到项目临时url:
这么多人用Codesandbox,他服务器扛得住么?

文章插图
新开页面,访问这个url,如果请求的资源包括:
  • 项目运行所需的静态资源
webpack热更新相关代码
这么多人用Codesandbox,他服务器扛得住么?

文章插图
那代表这是个Cloud Sandbox项目 。Cloud Sandbox在云端启动后端服务与当前页面通信,就类似我们本地开发时起的后端服务一样 。
如果请求的资源包括:
  • 项目运行所需的静态资源 。
  • sandbox初始化相关代码 。

这么多人用Codesandbox,他服务器扛得住么?

文章插图
那代表这是个Browser Sandbox项目 。
「sandbox初始化相关代码」是一个简化版的webpack,他会在浏览器执行,下载依赖、编译代码,打包并执行代码 。
我们平时使用codesandbox时看到的如下初始化画面就代表Browser Sandbox在浏览器执行相关操作 。
比如,下图是在通过CDN安装依赖(@babel/core):
这么多人用Codesandbox,他服务器扛得住么?

文章插图
当依赖安装完成后,下面是编译代码:
这么多人用Codesandbox,他服务器扛得住么?

文章插图
Browser Sandbox实现原理Browser Sandbox相关代码都是开源的,让我们按照抽象程度从上往下介绍他 。
首先是封装最完整的库 —— @codesandbox/sandpack-react 。这个React库提供了很多开箱即用的codesandbox模块 。
这么多人用Codesandbox,他服务器扛得住么?

文章插图
比如:
  • SandPackCodeEditor:codesandbox左侧的代码编辑区域,底层采用的是codemirror[2]这个代码编辑器 。
  • SandpackConsole:codesandbox中的控制台 。
  • SandackPreview:codesandbox右侧的预览区域,会渲染一个iframe,iframe的地址对应了Browser Sandbox的执行环境 。

这么多人用Codesandbox,他服务器扛得住么?

文章插图
各个组件通过postMessage与SandackPreview渲染的iframe交互 。
我们会发现,codesandbox的核心实际上包含三部分内容:
  • 各种编辑器相关模块的实现(比如代码编辑部分、控制台、预览) 。
  • Browser Sandpack运行环境,是一个独立的网页,在预览模块(SandackPreview)中通过iframe渲染 。
  • 1与2之间通信的协议(即页面与iframe之间的通信协议) 。
@codesandbox/sandpack-react实现了1,他依赖的@codesandbox/sandpack-client[3]实现了3 。
2相关的源代码在codesandbox-client/packages/app[4]中 。将这个包的代码部署上线后,就能获得一个Browser Sandpack运行环境 。
上面已经简单介绍了Browser Sandpack的工作原理,再将他(2)与1、3结合起来的工作原理如下:
这么多人用Codesandbox,他服务器扛得住么?

文章插图
比如,用户选择React作为项目模版:
这么多人用Codesandbox,他服务器扛得住么?

文章插图
编辑项目代码后,项目代码与preset(类似webpack中的preset选项项,不同模版对应不同preset)会通过通信协议传递给Browser Sandpack页面 。
Browser Sandpack页面通过内置的mini webpack与其他工具(比如babel),编译并执行代码 。
代码编译、执行的信息也会通过通信协议传递回各个需要的模块 。比如,控制台模块可以根据type为console的信息打印消息 。


推荐阅读