大家好,我卡颂。
codesandbox
是前端工程师常常应用的 代码在线运行环境,页面如下:
他的利用场景很广,比方:
- 有代码逻辑要分享,分享个
codesandbox
链接 - 有新想法须要验证,又不想本地起个我的项目,用
codesandbox
- 技术文档演示
Demo
,用codesandbox
作为一个在线运行代码的编辑器,这么多人天天收费用,他服务器扛得住么?
毕竟,同样作为在线代码运行环境(次要是跑算法题)的 leetcode,如果同时刷题的人多了,提交后都还得排队:
codesandbox
是如何实现的?他会面临 leetcode
一样的服务器压力么?
欢送围观朋友圈、退出人类高质量前端交换群,带飞
codesandbox 的分类
这个问题的实质其实是问 —— 用户在 codesandbox
中写的代码,到底是在前端还是后端编译成动态资源的?毕竟,如果是在后端实现,会减少服务器压力。
比方,对于上面这段 React
代码:
// main.jsx
import {createRoot} from "react-dom/client";
import {Cpn} from "./Cpn";
function App() {
return (<Cpn />);
}
createRoot(document.getElementById("root")).render(<App />);
要想在浏览器中运行,波及几个前置工作:
- 须要编译
JSX
语法,比方将<App/>
编译为_jsx(App, {})
- 须要解析并提前下载所有依赖,比方这里的
react-dom
、react
包 - 须要解析模块依赖关系,比方
main.jsx
导入了Cpn.jsx
中的Cpn
组件。对于不反对ESM
的浏览器,须要将代码打包。对于反对ESM
的浏览器,须要解决引入门路 - 如果波及到其余资源,比方图片、文字、
HTML
文件,须要有相应的解决
上述工作,codesandbox
是在浏览器还是服务器实现的呢?
在这个例子中,这些工作都能在浏览器实现,比方:
- 对于所有第三方依赖,能够在浏览器中间接申请
CDN
- 波及编译的工作(比方编译
JSX
、模块依赖剖析),实质其实是字符串的解析,能够用浏览器版本的babel
实现
下面的例子是一个纯前端的 React
我的项目。但有些依赖服务端环境的我的项目没法采纳上述形式运行,比方:
- 应用了
Docker
的我的项目 - 相似
Next.js
这样的全栈我的项目
这种状况就须要一个实在的服务端环境。
两者的区别能够用下图概括:
- 纯前端我的项目:编译与执行都能在浏览器实现
- 全栈我的项目:我的项目编译在服务端进行,浏览器负责我的项目执行
他们别离对应 codesandbox
的两种运行环境:
Browser Sandbox
:基于浏览器的本地运行环境Cloud Sandbox
:基于MicroVM
的云端运行环境
当咱们通过模板创立 codesandbox
我的项目时,能够通过 右上角是否有 Cloud 标记 辨别两者:
能够发现:
- 纯前端我的项目(比方
React
我的项目、纯JS
我的项目)应用Browser Sandbox
- 须要服务端运行环境(比方
Docker
我的项目、全栈框架我的项目)应用Cloud Sandbox
对于 Cloud Sandbox
,他底层应用亚马逊开发的Firecracker
疾速启动轻量级的 MicroVM
,这也是AWS Lambda
底层应用的库。
所以,基于 Cloud Sandbox
启动的我的项目的确会占用服务端资源。具体来说,每个我的项目会调配:
- CPU:2 个虚构 CPU(vCPUs)
- 内存:2GB
- 存储:6GB
这块是 codesandbox
公司的外围业务。毕竟,收费试用称心后,可能就会上付费的 Pro
版(更多资源分配),或者团队定制版。商业模式与 Vercel
相似 —— 提供收费根底服务(自担局部资源费用),通过增值的云服务免费。
而前端开发日常应用 codesandbox
创立的我的项目,大多数并不是基于 Cloud Sandbox
,而是基于Browser Sandbox
启动的。这些我的项目并不会给 codesandbox
带来太多服务端压力。
两种 sandbox 的区别
有个很直观的形式辨别两种 Sandbox
—— 当咱们新建一个codesandbox
我的项目,在预览区域能够看到我的项目长期url
:
新开页面,拜访这个url
,如果申请的资源包含:
- 我的项目运行所需的动态资源
webpack
热更新相干代码
那代表这是个 Cloud Sandbox
我的项目。Cloud Sandbox
在云端启动后端服务与以后页面通信,就相似咱们本地开发时起的后端服务一样。
如果申请的资源包含:
- 我的项目运行所需的动态资源
sandbox
初始化相干代码
那代表这是个 Browser Sandbox
我的项目。
sandbox 初始化相干代码 是一个简化版的webpack
,他会在浏览器执行,下载依赖、编译代码,打包并执行代码。
咱们平时应用 codesandbox
时看到的如下初始化画面就代表 Browser Sandbox
在浏览器执行相干操作。
比方,下图是在通过 CDN
装置依赖(@babel/core
):
当依赖装置实现后,上面是编译代码:
Browser Sandbox 实现原理
Browser Sandbox
相干代码都是开源的,让咱们依照形象水平从上往下介绍他。
首先是封装最残缺的库 —— @codesandbox/sandpack-react
。这个 React
库提供了很多开箱即用的 codesandbox
模块。
比方:
SandPackCodeEditor
:codesandbox
左侧的代码编辑区域,底层采纳的是 codemirror 这个代码编辑器SandpackConsole
:codesandbox
中的控制台SandackPreview
:codesandbox
右侧的预览区域,会渲染一个iframe
,iframe
的地址对应了Browser Sandbox
的执行环境
各个组件通过 postMessage
与SandackPreview
渲染的 iframe
交互。
咱们会发现,codesandbox
的外围实际上蕴含三局部内容:
- 各种编辑器相干模块的实现(比方代码编辑局部、控制台、预览)
Browser Sandpack
运行环境,是一个独立的网页,在预览模块 (SandackPreview
) 中通过iframe
渲染- 1 与 2 之间通信的协定(即页面与
iframe
之间的通信协议)
@codesandbox/sandpack-react
实现了 1,他依赖的 @codesandbox/sandpack-client 实现了 3。
2 相干的源代码在 codesandbox-client/packages/app 中。将这个包的代码部署上线后,就能取得一个 Browser Sandpack
运行环境。
下面曾经简略介绍了 Browser Sandpack
的工作原理,再将他(2)与 1、3 联合起来的工作原理如下:
比方,用户抉择 React
作为我的项目模版:
编辑我的项目代码后,我的项目代码与 preset
(相似webpack
中的 preset
选项项,不同模版对应不同 preset
)会通过通信协议传递给Browser Sandpack
页面。
Browser Sandpack
页面通过内置的 mini webpack
与其余工具(比方babel
),编译并执行代码。
代码编译、执行的信息也会通过通信协议传递回各个须要的模块。比方,控制台模块能够依据 type
为console
的信息打印消息。
总结
codesandbox
有两种代码运行环境:
Browser Sandpack
:针对 编译与执行都能在浏览器实现 的纯前端我的项目Cloud Sandpack
:针对须要服务端运行环境的我的项目
这两种环境会体现为一个独立网站,这个网站会作为 iframe
嵌入在 codesandbox
编辑器的预览模块中。
预览模块通过定义好的通信协议与其余模块(比方代码编辑模块、控制台模块)通信。
对于Cloud Sandpack
,会占用肯定服务端资源。对于Browser Sandpack
,则不会占用什么服务端资源,因为他大部分逻辑都是在前端执行的。
这篇文章只有介绍了理念层面的常识,如果想深刻理解 Browser Sandpack
的实现原理,能够看看搭建一个属于本人的在线 IDE,写的很具体。