Github Codespaces vs. Gitpod:选择最佳在线代码编辑器
Gitpod和Github Codespaces都是基于Visual Studio Code的在线代码编辑器,附带 Linux 开发环境服务器,用于运行终端任务;简单来说,两者都是基于云的代码编辑器,并且可以免费使用。
注意:Github Codespaces 仅在 beta 阶段免费供个人使用,未来可能会发生变化,对于 Github 团队和组织,有现收现付定价设置。要访问个人 Github 代码空间,您需要注册beta.
如果您作为团队或组织在注册 Codespaces 时遇到问题,请发送电子邮件至codespaces@github.com
本文详细介绍了我使用 Gitpod 和 Github Codespaces 的个人经历,这些是我的观点,并非绝对的事实,您的经历可能与我的不同。
为什么选择在线IDE?
我对Gitpod有更多的经验,因为它的存在时间比Github Codespaces长得多,但是,我在在线代码编辑器和 IDE 方面的经验要长得多。
我第一次使用在线代码编辑器是 2016 年的Cloud9(这是在 Cloud9 被亚马逊收购并成为 AWS Cloud9 之前)。当时 Cloud9 是一项免费服务并且随时可供个人使用,我非常喜欢该服务的便利性,以至于我在短时间内完全从本地编程切换到在线编程。所有好事都结束了,到 2019 年 12 月,Cloud9 宣布他们将关闭其独立服务,取而代之的是,Cloud9 将作为 AWS 的一部分提供,因此,就在我无法访问 Cloud9 之前,我开始寻找替代方案, ranging from Eclipse Che, Red Hat CodeReady Workspaces, Codeanywhere to StackBlitz, out of all the alternatives the most competent of them was Gitpod.
在线 vscode 革命
我寻找替代品的主要原因是当时我正试图使用 Chromebook 来完成我的所有工作。当我发现 Gitpod 时,我喜欢它的一般用户体验,它类似于 vscode,但有一些额外的附加功能在在线环境中更有意义,例如能够在开发时打开网站的小预览等等......另外,在线编辑器是在 Chromebook 上编码的唯一方法(现在已经改变。Chrome OS 现在支持 Linux 作为子系统),所以,🤷u200d♂️。
Gitpod 与 Codespaces
Gitpod 自己已经写了一篇关于他们对 Github Codespaces 的好处的文章,你可以在这里找到它gitpod.io/gitpod-vs-github-codespaces。我将简要概述两者之间的差异,注意他们夸大了它们的差异和好处的地方,解释如何充分利用每项服务,然后给出我个人对这两种服务的看法。
Gitpod 提出的第一点是它是"Ready in a flash"
Gitpod 通过为您的项目持续预构建工作区来消除较长的初始化和构建时间。因此,它允许您随时从任何上下文立即开始编码或调试。
这在技术上是正确的,至少在某种程度上是正确的。 Gitpod 的实际构建过程比 Github Codespaces 花费_slightly_ 长,或者至少感觉是这样,我没有,也不打算提供任何确切的经验性能数据,因为这两种服务都在不断变化,事实上,在我写这篇文章的前一周,Github 介绍了github.dev。
供您参考:github.dev是一个基于vscode 的在线网页编辑器,这个和Github Codespaces 的区别是Codespaces 自带终端,而这个没有
在 Gitpod 的防御中,它可以预先构建一个与 Github Codespaces 不同的工作空间,因此您可以立即开始编码,而无需等待漫长的构建过程完成。
Gitpod 提出的另一点是它具有“3x more power”,
通过利用容器和 Kubernetes 等云技术,Gitpod 通过在共享的高性能云服务器上运行的可扩展工作空间实现一流的资源效率。
这可能是他们提出的最重要的一点,因为我无法验证他们的服务器配置,也无法验证他们用于测试的计划最终在实际使用中更便宜,特别是因为 Github 只发布了定价方案Github Teams 和 Enterprise,不得用于个人用途。
注意: 在与@GeoffreyHuntley来自@gitpod讨论后,我已经确认 “[他们] 目前提供具有 64gb 内存和 16vCPU 和工作区的机器分时共享资源一种可爆的方式。每个工作空间的资源消耗都有上限”。 Gitpod 正在努力在未来几个月内分享有关其服务器端配置的更多信息。
截至 2021 年 8 月 30 日,Gitpod 有 8 个计划*,其中 2 个是自托管选项。他们是,
计划
价格(每用户/月)
特征
开源
自由的
50 小时/月 + 私人和公共回购
专业开源
自由的
没有时间限制+私人和公共回购
个人的
9 美元
100 小时/月 + 4 个并行工作区 + 30 分钟超时
专业的
25 美元
全部在个人 + 8 个并行工作区 + 无限小时 + 团队
释放
39 美元
全部在 Professional + 16 个并行工作区 + 1 小时超时 + 3 小时超时提升
学生
9 美元
All in Unleashed,但对于“那些仍在学习绳索的人”
自托管开源
自由的
10 个注册用户 + 公共和私人回购 + GitLab、GitHub 和 Bitbucket + 无限预构建 + 共享工作区 + 快照 + 管理仪表板
自托管专业
自由的
自托管开源+ 从第 11 个用户开始
对于 Github Codespaces,定价* 是,
产品
库存单位
测量单位
价格
代码空间计算
2芯
1小时
0.18 美元
4芯
1小时
0.36 美元
8芯
1小时
0.72 美元
16芯
1小时
1.44 美元
32芯
1小时
2.88 美元
代码空间存储
贮存
1 GB/月
0.07 美元
*这两项服务的定价方案中都包含更多详细信息,我建议您仔细阅读这些信息以获取详细和最新的信息。
**注意:**您必须为您的 Codespaces 存储支付上述工作空间存在的时间,这包括您没有积极使用工作空间的时间。据我所知,Gitpod 不需要支付存储费用。
来源:Gitpod,GitHub Codespaces。
在最后一点Gitpod 中,他们以类似表格的形式列出了他们提供的一些好处,我坦率地说,他们遗漏了很多细节,所以,我会以实物方式回答更详细的方式。
Gitpod
Github 代码空间
细节
定价(托管)
开源免费
$$$
同样,这是不确定的,因为它得出的结论是 Gitpod 的价格更便宜,这不是很准确,而且相当具有误导性
执照
开源
所有权
这就是 Gitpod 获胜的地方,他们的代码实际上是开源,实际上他们的扩展商店使用开源OpenVSX 扩展商店,但是,OpenVSX 商店最终既是好处也是坏处.
GitHub 集成
是的
是的
Gitpod 对 Github 有很好的支持,但 Codespaces 有更好的集成。 Gitpod 需要Open in Gitpod 链接、Gitpod 扩展或小书签,但 Github Codespaces 可以直接使用,点击任何打开的绿色代码空间下拉菜单即可.
GITLAB 集成
是的
不
准确的。 Gitpod 原生集成到 GitLab 中,并为每个用户提供“在 Gitpod 中打开”按钮,类似于 Codespaces 为 Github 所做的。
位桶集成
是的
不
准确的
GCP 上的自托管
是的
不
准确的
AWS 上的自托管
是的
不
准确的
Kubernetes 上的自托管
是的
不
准确的
预建
是的
不
准确的
快照
是的
不
据我所知,它是准确的。在 Github Codespaces 测试版中,您不能共享工作空间的快照,本质上,每个用户都被迫从头开始构建每个存储库,以用于他们的用例。至少据我所知,我不确定此限制是否适用于 Github 团队和/或组织。
VS 代码扩展
是的*
是的
Gitpod 使用 OpenVSX 存储,问题是 OpenVSX 存储最终对 Gitpod 既有利又不利。 VS Code 是开源的,但它的 store 是闭源的,所以,Gitpod(在 TypeFox 中孵化的时候)创建了Open VSX store(包括Theia IDE)并将其赠送给Eclipse基础,一个开源替代品,问题是 OpenVSX 商店中缺少一堆扩展,范围从Github Copilot到Live Share甚至一些你期望的开源扩展但是,开发人员现在可以毫不费力地自动将扩展部署到 OpenVSX。在这种情况下,我认为 Github Codespaces 具有更好的扩展存储,因为它直接使用与本地安装 VS Code 将使用的相同的专有扩展存储。
IPAD 支持
是的
是的
准确的
虚拟桌面 (VNC)
是的
是的
准确的
多IDE支持
是的*
不
这是准确的。 Gitpod 允许您将其服务的基础从 VS Code 更改为Theia(VS Code 已弃用的完全开源变体)、JetBrains和[E-macs]zwz1002。我个人只使用过 VS Code IDE,所以我不能说使用其他 IDE 的体验,但可以使用该选项。
工作区设置
Gitpod 和 Github Codespaces 都有基于 Docker 的配置文件来配置你的整个环境。在 Gitpod 上,他们的配置系统使用一个.gitpod.yml
文件来存储您的工作区配置信息和一个.gitpod.Dockerfile
文件,该文件设置一个 docker 映像,您可以使用它来运行您的工作区。默认情况下,Gitpod 使用标准 docker 镜像作为工作区的基础,标准镜像具有开发人员所需的大多数默认工具和程序,此外,您还可以在其上构建以添加一些小的附加功能。
.gitpod.yml
文件存储基本配置信息,范围从开放端口到安装后脚本。您的基本.gitpod.yml
文件如下所示:
# Commands to start on workspace startup
tasks:
- init: yarn install
command: yarn build
# Ports to expose on workspace startup
ports:
- port: 8000
onOpen: open-preview
对于我使用 Gitpod 的大多数项目,我设置了一个像这样的.gitpod.yml
文件
# .gitpod.yml
image:
file: .gitpod.Dockerfile
# List the ports you want to expose and what to do when they are served. See https://www.gitpod.io/docs/43_config_ports/
ports:
- port: 3000
onOpen: open-preview
- port: 3001
onOpen: ignore
github:
prebuilds:
# enable for the master/default branch (defaults to true)
master: true
# enable for all branches in this repo (defaults to false)
branches: true
# enable for pull requests coming from this repo (defaults to true)
pullRequests: true
# enable for pull requests coming from forks (defaults to false)
pullRequestsFromForks: true
# add a "Review in Gitpod" button as a comment to pull requests (defaults to true)
addComment: true
# add a "Review in Gitpod" button to pull requests (defaults to false)
addBadge: false
# add a label once the prebuild is ready to pull requests (defaults to false)
addLabel: prebuilt-in-gitpod
# List the start up tasks. You can start them in parallel in multiple terminals. See https://www.gitpod.io/docs/44_config_start_tasks/
tasks:
- init: >
npm install -g pnpm &&
pnpm install -g ultra-runner &&
pnpm install
command: >
npm install -g pnpm &&
pnpm install -g ultra-runner &&
pnpm build
Gitpod 预构建部分为每个分支设置预构建,并拉取请求,并留下带有预构建链接的评论,查看 Gitpod 预构建](https://www.gitpod.io/docs/prebuilds)的[文档以了解更多信息。
但是,有趣的是在任务部分。init
任务在工作区启动时运行一次,command
任务在工作区启动时运行,然后在每次工作区重新启动时运行。
真正的问题是init
任务即使在启动时运行,也不存储环境变量,也不链接全局安装的包,据我所知,这是因为每个终端环境都基于提供的 Gitpod docker 映像。如果 gitpod.yml 文件中没有指定 docker 镜像,则使用标准的“workspace-full”镜像。我建议阅读Gitpod 的文档关于此事。
注意:根据@GeoffreyHuntley来自@gitpod“[It's] 建议 [that] 构建自己的 docker 映像并安装任何软件一旦您的项目复杂性值得,您需要作为构建 docker 映像的一部分。除此之外,[他们] 还在进行更改以实施完整工作空间备份,这将快照整个环境以消除这种摩擦”.
.gitpod.Dockerfile
是直接为您提供管理员访问权限的文件,使您能够在工作空间中安装/执行任何您想要的操作。根据我的经验,您很可能不需要在此处更改任何内容,除了VNC用途,即使那样,文档也非常清楚。
# .gitpod.Dockerfile
FROM gitpod/workspace-full:latest
# Install custom tools, runtime, etc. using apt-get
# For example, the command below would install "bastet" - a command-line tetris clone:
#
# RUN sudo apt-get -q update &&
# sudo apt-get install -yq bastet &&
# sudo rm -rf /var/lib/apt/lists/*
#
# More information: https://www.gitpod.io/docs/config-docker/
另一方面,为 Github Codespaces 设置工作区是动手操作。选择一个默认容器很容易*,您只需遵循 VS Code](https://code.visualstudio.com/docs/remote/containers)上的[文档,真正的问题是 Github Codespaces 的设置非常庞大。
对于 Codespaces,您需要创建一个.devcontainer.json
文件并将其存储在.devcontainer/
文件夹中。.devcontainer.json
文件是一个 json 文件,其中包含设置工作区所需的信息。.devcontainer.json
文件如下所示:
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.162.0/containers/typescript-node
{
"name": "Node.js & TypeScript",
"build": {
"dockerfile": "Dockerfile",
// Update 'VARIANT' to pick a Node version: 10, 12, 14
"args": {
"VARIANT": "16"
}
},
// Set *default* container specific settings.json values on container create.
"settings": {
"npm.packageManager": "pnpm"
},
// Add the IDs of extensions you want to be installed when the container is created.
"extensions": [
"bierner.jsdoc-markdown-highlighting",
"yzhang.markdown-all-in-one",
"shd101wyy.markdown-preview-enhanced",
"visualstudioexptteam.vscodeintellicode"
],
// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [3000],
// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "pnpm install",
// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "node"
}
您还需要创建一个存储在.devcontainer/
文件夹中的Dockerfile
。Dockerfile
包含 docker 信息,因此您可以在此处设置工作区所需的任何配置,如下所示:
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.187.0/containers/typescript-node/.devcontainer/base.Dockerfile
# [Choice] Node.js version: 16, 14, 12
ARG VARIANT="16-buster"
FROM mcr.microsoft.com/vscode/devcontainers/typescript-node:0-${VARIANT}
# [Optional] Uncomment this section to install additional OS packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
# && apt-get -y install --no-install-recommends <your-package-list-here>
# [Optional] Uncomment if you want to install an additional version of node using nvm
# ARG EXTRA_NODE_VERSION=10
# RUN su node -c "source /usr/local/share/nvm/nvm.sh && nvm install ${EXTRA_NODE_VERSION}"
# [Optional] Uncomment if you want to install more global node packages
# RUN su node -c "npm install -g <your-package-list -here>"
RUN su node -c "npm install -g pnpm"
这个例子是基于我的一个 Github 项目okikio/native,这是为你自己的项目设置工作空间的一个很好的起点。
_注意:Github Codespaces 配置可能会让您失望的主要事情是您无法在 docker 配置中安装本地包(我说的是
node_modules
)。当然,这可能是我缺乏使用 Docker 的经验,但到目前为止,我一直无法让它正常工作。_
供您参考: Gitpod 团队计划添加对 Github Codespaces
devcontainer.json
格式的支持,因此,将来,您可能能够轻松地在 Github Codespaces 和 Gitpod 之间切换而不会破坏流汗。
协作
我个人没有在 Gitpod 或 Github Codespaces 上与任何人合作过,但每项服务都提供了一种与他人合作的方式。一方面,Gitpod 允许您与其他人共享正在运行的工作空间和快照(工作空间的副本),另一方面,Github Codespaces 允许您使用 Live Share 在同一个项目上进行协作。
我觉得 Live Share 是一个更好的协作工具,当然使用 Gitpod 你可以与其他人共享工作空间,但是使用 Codespaces,你可以在同一个项目上工作,而不会跳过一个节拍,从技术上讲,它与与其他人共享工作空间非常相似开发人员,所以...我将把这件事的最终判断留给你。
文档
Github Codespaces 有非常详细的文档,但它的内容非常密集并且有点压倒性。另一方面,Gitpod 的文档更简单,更侧重于基础知识,包括文档和简短的截屏视频。这是开始使用基于云的开发环境的好方法。 Github Codespaces 基本上假设您已经非常有经验,而 Gitpod 假设您是在线开发环境世界的新手,并在此基础上慢慢构建。
VNC
Gitpod 和 Github Codespaces 都支持 VNC。根据我的经验,两者在 VNC 的工作方式方面大致相同,但是,使用 VNC 设置 Gitpod 更容易。
虚拟网络计算 (VNC) 是一个图形桌面共享系统,它使用远程帧缓冲协议 (RFB) 来远程控制另一台计算机。它将键盘和鼠标输入从一台计算机传输到另一台计算机,通过网络传递图形屏幕更新。阅读更多关于维基百科
不久前,我尝试尝试是否可以在我的 Windows 笔记本电脑上设置Webkit(Safari 的浏览器引擎)......我失败了,我不知道如何在 Windows 上构建 Webkit 源代码(它非常困难),所以,我尝试了下一个最好的东西,“云”,它也失败了,但有趣的是,原因完全不同。
对于这个实验,我使用了 Github Codespaces(在之前的实验中我已经尝试过使用 Gitpod 和 VNC,所以,我想这次我会尝试 Github Codespaces)。我能够使 VNC 正常工作,但无法设置 Webkit,因为 Docker 在 Webkit 使用的一些库方面存在问题。在我放弃之前,我尝试了大约 16 个小时。我最终找到了另一种选择,Playwright。
Playwright是一个用于在多个浏览器上测试 web 应用程序的端到端框架,它是测试 web 应用程序的好工具。
在试用 Playwright 时,我发现它只能在 Windows 上运行(这是因为 Webkit 和 Docker 的库问题)。
让我们回到最初的话题,VNC。在我的实验中,我发现在 Github Codespaces 上设置 VNC 很困难,而且上述工作区的构建过程很长,我实际上是计时的,使用 VNC 的 Github Codespaces 的构建过程大约需要 6 分钟,而在 Gitpod 上它要快得多(我不记得确切花了多长时间,但我记得不到 5 分钟),此外,Gitpod 的文档更容易消化,并且可以开始使用。
对于 Gitpod 上的 VNC,请查看gitpod.io/blog/native-ui-with-vnc。
对于 Github Codespaces 上的 VNC,请查看github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/desktop-lite.md。
烦恼
在 Gitpod 工作区中,每个终端都是从给定的 Gitpod docker 映像构建的,或者如果找不到 Gitpod 标准映像“workspace-full”,理论上这听起来很棒,但是,根据我的经验,它最终是一个解决的巨大痛苦。比如我发现如果你用nvm(node version manager)安装新版本的node,比如说v16替换Gitpod标准镜像节点,v14,你创建的每一个新终端都会使用node set的版本在标准图像中,这似乎是一个非常小的问题,但它可能会导致一堆问题,并且随着时间的推移会让你非常恼火,而且它只会减慢你的开发速度。如工作区设置部分中所述,可以通过构建自己的 docker 映像或键入.gitpod.yml
文件来缓解此问题,
tasks:
# Replace version with version you want installed
- init: >
nvm install v16 &&
'nvm alias default v16' >> /home/gitpod/.bashrc
nvm list
查看更多关于Stackoverflow
网络问题
通过使用 Gitpod 和 Github Codespaces,您会变得依赖互联网,如果您无法访问互联网,则无法使用这两种服务。对于大多数开发人员来说,这并不是一个真正的问题,因为在大多数情况下,他们需要访问互联网才能将更改提交到 Github、Bitbucket 等......
对于您无法访问 Internet 的情况,假设您的 ISP 在某个地方出现问题,并且您在几天内无法访问(我是根据个人经验在这里发言),那么您将根本无法进行任何编程。
对于那些担心互联网连接的人来说,最好的办法是确保您始终拥有一个本地副本,其中已经安装了所有工具和依赖项,因此,当您无法访问时,您至少可以取得一些进展。
对于您可能失去连接一两分钟的小实例,Github Codespaces 和 Gitpod 会保留所有打开文件的本地副本,并在重新建立连接时将它们合并到在线副本中,所以不用担心。
警告:需要注意的一点是,如果您在使用 Gitpod 时长时间无法访问互联网,则必须将您的工作区固定在他们的仪表板中,否则您可能会在 14 天后失去工作区,并且必须重新开始。这实际上不适用于 Github Codespaces,因为您必须主动删除一个工作区,Codespaces 会关闭一个工作区,但它不会为您删除它。如果您找不到工作空间,并且上次使用工作空间的时间少于 14 天,您将单击
View All Workspaces
按钮
杂项
Gitpod 和 Github Codespaces 之间的一个小区别在于,Github Codespaces 支持使用您本地安装的 VS Code 版本来使用您熟悉和喜爱的 VS Code 继续开发,以及将远程端口转发到 localhost 端口等等,所有这些都是 Github Codespaces允许开发人员在与本地开发非常相似的环境中进行开发,除了资源使用较少(因为大部分处理都发生在远程服务器上),并且对互联网的依赖程度稍高,请阅读Github 的文档了解更多信息。
Gitpod 支持类似的东西,如果您将 Gitpod 应用程序安装为 PWA(据我所知,只有 Edge 允许您强制将网站安装为应用程序),然后您可以将服务器上的远程端口转发到您计算机的本地主机端口,在Gitpod 的文档上阅读更多相关信息。
供您参考: Gitpod 正在努力支持本地 VS 代码,因此,当您阅读本文时,它可能已经上线了。
我不知道这对开发者来说有多重要,但 Github Codespaces 会自动在 VS Code 和自身之间同步设置。要在 Gitpod 中使用此功能,您需要对 VS Code 安装进行一些设置,阅读 Gitpod](https://github.com/gitpod-io/gitpod/issues/3733#issuecomment-813917147)打开的[问题以了解更多信息。
什么时候使用 Github Codespaces?
Github Codespaces 是一个易于使用且可靠的 VS Code 服务,它与 Github 的集成非常方便且难以正确量化,其扩展支持是顶级的,其编码体验难以传递,尤其是对于已经使用 Github 的其他服务。 Github Codespaces 非常适合需要高资源工作空间并且无需在其他平台上自托管的开发人员。
Github Codespaces 很好,但它并不是适合所有人的完美解决方案。 Github 的计费模式有点费劲,因为工作空间存储不是免费的,所以,如果你想专业地使用 Github Codespaces,你最终可能会在无意中付出相当多的费用,另外,取决于你使用每个 Github Codespace 的小时数,你的每月的账单可能是一个相当痛苦的药丸。
什么时候使用Gitpod?
Gitpod 是一个易于使用且非常可靠的 VS Code 服务,它的开源设计允许您参与其中,甚至可以在问题出现时修复它们。 Gitpod 非常适合开源项目、需要可靠且一致的月度定价方案的项目、寻找非专有 VS Code 工作区的开发人员或想要使用 Bitbucket、Gitlab 等的开发人员。和/或使用AWS、GCP 等上的自托管选项... 确实 Gitpod 很棒,原因与 Github Codespaces 相同,只是 Gitpod 与 Github 的集成少了一点,这使得 Github Codespaces 与 Github 一起使用的体验更好。
结论
这两种服务都很棒,因为它们通过 Web 为开发人员带来了一致且可靠的 VS Code 体验。然而,它们并不是每个人的完美解决方案,因为它们都有自己的起起落落。
我已经陈述了我对这两种服务的个人体验,我建议使用您认为最适合您的一种。就个人而言,我经常在两种服务之间切换,但是,我更喜欢 Github Codespaces。我发现它对我来说是最好的选择,因为它可以同步我的设置,支持本地 VS Code,并且与 Github 和 VS Code 扩展有很好的集成(我什至可以在 Github Codespaces 中使用Github Copilot)。
**注:**我实际上是使用 Github Codespaces 和Github Copilot来写这篇文章的。当我说它是一个优秀的写作伴侣时,相信我,它几乎就像 Gmail 自动完成功能,但更好,因为它还可以识别代码语法,并且可以相当有效地应用它们。
Github Copilot的替代品是Tabnine。我实际上并没有使用它,但我觉得它值得一提,因为它适用于 Gitpod.
为了对这两种服务进行更中立和客观的比较,我建议阅读Nader Dabit 在 FreeCodeCamp 上比较两者的文章。
2021 年 9 月 9 日更新: 添加缺少的 selfhost 和开源 Gitpod 计划;从@GeoffreyHuntley从@gitpod获取有关服务器配置的报价;添加 Tabnine 作为 Github Copilot 的替代品;为 Gitpod 的终端节点版本问题添加可能的 Docker 或.gitpod.yml
修复;修复拼写和语法问题
本文的想法来自推文由Nik Molnar @nikmd23和Stephan Meijer @meijer_s。
图片由Okiki Ojo拍摄,您可以在Dropbox上找到图片。
另外,发表在Hackernoon和dev.to
更多推荐
所有评论(0)