这是你新的软件工程工作的第一天,你超级兴奋地要向代码库提出你的第一个拉动请求,但在这之前,你必须让你的本地环境启动和运行。这个艰苦的过程可能会花费你一整天或一周的时间。你将需要在多个云提供商那里建立账户,并访问环境变量,你将花费相当多的时间编辑过时的文档。而现在,你已经失去了为团队作出贡献的火花。
或者
你正在寻找一个开源项目来做贡献。你关注文档,但它已经过时了,难以理解,所以你放弃了对贡献的追求。
或者
你想尝试一个新的框架,了解它在幕后是如何工作的,但要做到这一点,你必须npm安装500万个不同的东西,而你并不那么感兴趣,所以你决定改为狂看HBO的《继承》。
这是发生在所有级别的软件工程师身上的三种非常常见的经历,不管是刚参加工作还是刚参加一个开源项目。那么,解决方案是什么呢?
软件工程行业承认,第一次拉取请求的时间或第一次贡献的时间可能很费时和麻烦。因此,该行业创造了许多解决方案,如CodeSandbox和Replit的浏览器内沙盒解决方案。对于大型项目,基于云的开发环境,如GitPod和GitHub Codespaces,可以简化入职和协作。使用GitHub Codespaces或GitPod等工具的一个主要障碍是缺乏关于如何配置它们以自动运行你的项目的知识,这是可以理解的,因为这些概念在软件工程行业还比较新。幸运的是,你有我,而且你找到了这篇博文。免责声明:我在GitHub工作,是一名开发者倡导者。然而,有一部分的我对建立开发容器的过程感到有些畏惧。比如,什么是开发容器?我应该只是复制和粘贴一个吗?在花了一些时间真正了解了开发容器之后,我觉得它们更容易接近了。
在这篇博文中,我将指导你为一个静态的Next.js/TypeScript网络应用程序设置一个开发容器,以便它能自动在GitHub Codespace中运行。
我的新开源项目
与此相关的是,我很高兴地告诉大家,我已经开始和Josh Goldberg一起维护我的第一个开源项目–开放贡献项目。我们的目标是倡导和解释企业对开源的贡献。这是一个用Next.js和TypeScript建立的静态文档网站。我们欢迎在设计、文档和代码方面的贡献,特别是来自初学者的贡献。请看下面的资料库。
我设置了一个开发容器,并启用了GitHub Codespaces来简化开放贡献项目的开发过程。如果你在GitHub Codespaces中启动Open Contributions项目,它将安装所需的依赖项,运行项目,并启动项目的浏览器预览。你可以在这里或通过点击下面的按钮来试试!
什么是GitHub Codespaces?
GitHub Codespaces 是一个基于云的开发环境。这有助于开发人员更快地上手,在任何设备上进行编码,并在一个一致的环境中进行编码。GitHub Codespaces的用户界面可以类似于你最喜欢的IDE–如Visual Studio Code、Visual Studio、Jupyter Notebook或JetBrains,但它在你的浏览器中打开。你可以通过创建配置文件来为GitHub Codespaces定制你的项目。这些配置文件为你项目的所有用户创建了一个可重复的Codespace配置。如果你不设置任何自定义配置,你的项目将使用默认的内置GitHub Codespaces配置。
你可以从以下资源中了解更多关于GitHub Codespaces的信息:
- 概述和GitHub Codespaces入门 – GitHub文档
- 彻底改变你的开源工作流程:GitHub Codespaces是维护者必备的三大理由
- 10件你不知道的可以使用GitHub Codespaces的事情
- 编写GitHub Codepsaces的初学者指南
- 通过Codespaces进行技术面试
什么是开发容器?
GitHub Codespace是建立在利用开发容器的虚拟机之上的,或称 dev 容器,本质上是提供全面开发环境的 Docker 容器。你可以配置一个开发容器来提供统一的开发者体验。你可以用这三个文件配置一个开发容器: devcontainer.json
、 Dockerfile
和 docker-compose.yml
。对于像我们这样的小型静态Next.js/Typescript项目,我们只需要 devcontainer.json
文件。
你可以从以下资源中了解更多关于开发容器的信息:
- 开发容器简介 – GitHub 文档
- 开发容器规范指南
- 为什么人们在容器内进行编码?
- 如何用开发容器和GitHub Codespaces实现开发环境的自动化
- 我是如何使用开发容器为ChatGPT启用GitHub Codespaces的?
了解Codespace生命周期属性
在本指南中,我使用了一些Codespace生命周期属性,所以我想我应该简要介绍一下它们是什么以及为什么我们要使用它们。Codespace生命周期属性是特殊的属性,在创建和管理Codespace环境的特定点上自动运行。你可以使用它们在环境的生命周期中的特定点上执行定制任务。
下面是一些常用的Codespace生命周期属性:
- preCreateCommand:在创建Codespace之前运行,用于通过安装任何必要的软件或依赖性来设置环境。
- onCreateCommand:在Codespace创建后立即运行,用于执行任何需要的额外设置任务。
- postCreateCommand:在环境被创建后运行,用于执行任何最终的配置任务。
- updateCommand:更新环境,通常用于安装任何新的软件或自上次创建环境以来被添加的依赖项。
- updateContentCommand:更新环境的内容,通常用于更新环境中的文件或数据。
- postAttachCommand: 在这里,”attach” 意味着连接到一个现有的和已经创建的Codespace。这个命令在用户连接到Codespace之后运行,用于执行每次连接Codespace时应该执行的任何任务,例如启动一个开发服务器。
为Next.js/TypeScript代码库构建开发容器的步骤
第1步:为你的项目创建一个Codespace
让我们通过选择 “Code”> “Codespaces”> “Create Codespace on [default branch].”,在GitHub Codespace中打开我们的项目。
第2步:添加一个预制的开发容器
首先,打开命令面板。我们可以使用这些选项中的任何一个访问命令面板:
- 按这个键盘快捷键组合Shift+Command+P(Mac)或Ctrl+Shift+P(Windows/Linux)。
- 从应用程序菜单中,点击 View > Command Palette
- 按F1键
然后,在命令面板中,选择 “Add dev container configuration files”。
第3步:创建一个新的配置
然后,我们将看到两个选项:
- 修改你的活动配置
- 创建一个新的配置
由于我们还没有一个配置好的开发容器,我们要选择 “Create a new configuration”。
第4步:选择Node.js和TypeScript模板
接下来的步骤将引导我们进入预定义的开发容器列表,所以我们不必从头开始! 目前,”Node.js & TypeScript” 开发容器是最适合Next.js/TypeScript项目的开始。
第5步:选择你喜欢的Node.js版本
下一个屏幕将提示我们选择我们喜欢的Node.js版本。我选择了20,但你应该选择最适合你的项目的任何版本。
第6步:跳过那些功能! 创建开发容器
下一步是添加功能。在我们的例子中,我们不需要任何功能,所以我们可以按 “OK”。按 “OK” 会给你的项目添加一个.devcontainer目录,其中有一个devcontainer.json文件,我们可以进一步定制。
下面是我们最初的devcontainer.json文件应该是什么样子:
// For format details, see https://aka.ms/devcontainer.json. For config options, see the // README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node { "name": "Node.js & TypeScript", // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile "image": "mcr.microsoft.com/devcontainers/typescript-node:0-20" // Features to add to the dev container. More info: https://containers.dev/features. // "features": {}, // Use 'forwardPorts' to make a list of ports inside the container available locally. // "forwardPorts": [], // Use 'postCreateCommand' to run commands after the container is created. //"postCreateCommand": "yarn install", // Configure tool-specific properties. // "customizations": {}, // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. // "remoteUser": "root" }
第7步:自动安装项目的依赖项
作为本地设置的一部分,我运行 pnpm install
来安装我的项目依赖。 pnpm
是一个Node.js包的包管理器。它被设计成快速、节省磁盘空间和功能丰富。它在磁盘上为每个包创建一个实例,并使用符号链接来链接到其他项目中安装的包。
你的项目可能使用不同的命令和软件包管理器来安装项目依赖。也许,你的项目使用的是yarn或npm,所以你不想逐字逐句地复制我的这个步骤。相反,你可以把我在这一步的建议作为一个指导性的例子! 如果你使用 npm install
或 yarn install
来安装你的项目依赖,用你的项目所需的命令替换 pnpm install
。
总之,我想把这个步骤自动化,这样项目贡献者就不必手动运行 pnpm install
,所以我用我的dev容器来自动完成。在我的 devcontainer.json
文件中,我添加了一个名为的属性:
"updateContentCommand": "pnpm install"
这将使我的Codespace能够安装最新的项目依赖。我考虑过将 pnpm install
命令委托给一个不同的 Codespace 生命周期属性,但我想要 updateCommentCommand
的好处。使用这个生命周期属性的最大好处是,它不会在每次创建环境时安装所有的依赖项,而只会安装自上次创建环境后添加的新依赖项。
第8步:自动运行本地开发服务器
因为我的项目是静态的,没有太多复杂的东西,所以在安装完所需的依赖项后,我需要用命令 pnpm dev
启动我的本地环境。同样,我不希望项目贡献者手动输入这个。我希望当他们在GitHub Codespaces中打开我的项目时,项目就已经开始运行了,所以我在我的开发容器中通过在 devcontainer.json
文件中添加以下几行来实现这部分的自动化:
"postAttachCommand": "pnpm dev"
这句话是说在Codespace的所有东西都设置好后,用户连接到Codespace,启动开发服务器。请记住,运行你的本地开发服务器的命令可能有所不同。也许你需要使用npm run dev
或 yarn start
。在复制和粘贴之前请仔细检查!
第9步:选择你的转发端口
现在我们在上面的步骤中自动运行我们的本地开发服务器,我们现在可以为Codespaces选择一个特定的端口,将容器中的流量转发到你本地机器上的一个端口。在下面的例子中,我选择了3000端口。
"forwardPorts": [3000]
因此,GitHub Codespaces 将生成一个遵循这一命名惯例的URL:
https://<your-github-handle>-<a-codespaces-id-which-combines-a-words-and-random-characters>-<your-port-number>.preview.app.github.dev/
对我来说,它生成了这个URL:
https://blackgirlbytes-ubiquitous-couscous-777759vgvpjcrv4q-3000.preview.app.github.dev/
你有能力改变你的端口的可见性! 要了解更多关于转发端口的信息,请查看以下资源:
第10步: 获取浏览器预览
我最喜欢GitHub Codespace的部分是,只要在devcontainer.json文件中加入以下几行,就可以在Codespace中直接打开浏览器预览:
"portsAttributes": { "3000": { "label": "Application", "onAutoForward": "openPreview" } }
第11步:自动添加扩展
我们可以配置一个项目来自动安装GitHub Codespaces中的扩展。我们可以通过右键点击任何扩展,选择 “Add to devcontainer.json” 来实现。
我添加了以下扩展:
- Code spell checker
- ES Lint
- Markdown-lint
- Remote-containers
在这之后,它应该在我们的devcontainer.json文件中添加以下对象:
"customizations": { "vscode": { "extensions": [ "streetsidesoftware.code-spell-checker", "dbaeumer.vscode-eslint", "esbenp.prettier-vscode", "DavidAnson.vscode-markdownlint", "ms-vscode-remote.remote-containers" ] } }
第12步:使之成为同步的
使用 waitFor
属性使我们能够对Codespace的生命周期和特定命令的时间有更多的控制。例如,我在devcontainer.json文件中使用了以下配置:
"waitFor": "onCreateCommand"
这告诉Codespace创建过程等待onCreateCommand完成,然后再进入Codespace生命周期的下一个步骤。这确保了在运行其他命令之前环境已经设置好了。
注意事项
实际上,我的 devcontainer.json
文件中根本就没有onCreateCommand,所以我添加这一行并没有意义。也许,如果我添加下面这一行,可能会更有意义:
"waitFor": "updateContentCommand"
我还在广泛学习GitHub Codespaces,所以这是我犯的一个错误,我想纠正。
第13步:最后的devcontainer.json文件
让我们确认一下最终的结果吧! 在我的 .devcontainer
目录中,我有一个 devcontainer.json
,内容如下:
// For format details, see https://aka.ms/devcontainer.json. For config options, see the // README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node { "name": "Node.js & TypeScript", "image": "mcr.microsoft.com/devcontainers/typescript-node:0-18", "waitFor": "onCreateCommand", "updateContentCommand": "pnpm install", "postAttachCommand": "pnpm dev", "customizations": { "vscode": { "extensions": [ "streetsidesoftware.code-spell-checker", "dbaeumer.vscode-eslint", "esbenp.prettier-vscode", "DavidAnson.vscode-markdownlint", "ms-vscode-remote.remote-containers" ] } }, "portsAttributes": { "3000": { "label": "Application", "onAutoForward": "openPreview" } }, "forwardPorts": [3000] }
第14步:试运行!
我们可以测试我们的改动,以确保GitHub Codespaces能够安装所需的依赖,安装所需的扩展,运行我们的本地开发服务器,并通过完全重建容器打开浏览器预览。
为了重建容器,我们需要访问命令面板。我们可以使用这些选项中的任何一个来访问命令面板:
- 按这个键盘快捷键组合 Shift+Command+P (Mac) **OR **Ctrl+Shift+P (Windows/Linux)
- 在应用程序菜单中,点击View > Command Palette
- 按下F1
然后,在命令面板中,选择 “Codespaces: Full Rebuild Container”。
视频演练
我现场直播了自己通过建立一个开发容器的步骤和规划这篇博文。请看!
分享你的学习成果
如果你尝试过开发容器,或者掌握了使用GitHub Codespaces的任何很酷的技巧和窍门,请在下面发表评论!(via Rizèl Scarlett)
评论留言