Remix Website homepage
2024年1月31日

Remix 网站开源

Brooks Lybrand
开发者关系经理

今天,我们非常激动地宣布,这个网站本身现在已经开源!我们邀请您探索并学习源代码,甚至可以考虑贡献代码

我们为什么要开源

早在两年多前,Remix 框架就开源了。在过去的十年里,Ryan 和 Michael 一直在致力于开源软件。甚至 reactrouter.com 也是一个公开的存储库。毋庸置疑,我们是开源的坚定拥护者。

那么,为什么不是每个人都开源他们的网站呢?这其中是有充分理由的

  • 开源会增加潜在的数据或业务逻辑泄露的安全风险
  • 公开的存储库需要维护者花费更多的时间来分类问题、审查 PR,并参与关于功能请求和改进的讨论
  • 通常,开源软件的维护者会竭尽全力使他们的库和网站看起来很漂亮,而网站背后的代码却是一团乱麻,他们的初衷只是为了尽快完成,以便他们能够开始吸引用户(我不是在说我个人的经验 😅)

好吧,我们无论如何都要开源它。

我们认为利大于弊。开源我们的网站使我们能够提供一个真实的 Remix 网站供大家学习。它也给了我们一个更容易从社区中热心的开发者那里获得反馈和贡献的机会(感谢 Ryan Leichty 润色我们的文档)。此外,虽然我们的网站大部分都很简单直接,但我们确实做了一些很酷的事情。

网站概览

主页是如何工作的?!

我还是不知道。

Ryan Florence 写了它,现在你可以阅读1500 行的 ScrollExperience 组件的源代码。或者你可以像我一样多次滚动浏览它,看看所有酷炫的动画。

Remix run website scroll experience

不使用 SSG 的文档

我们网站的一个独特之处在于,我们在请求时对 文档进行服务器端渲染,而不是使用更常见的静态站点生成(在构建期间预渲染 HTML)策略。

我们这样做的主要原因是,我们不必每次修复错别字时都重建整个网站。事实上,Remix 文档根本不存在于此存储库中。您可以在 Remix 代码库中找到它们,就在 Remix 源代码旁边。我们将文档放在这里

  • 为了使其更接近它正在记录的代码
  • 为了使其易于贡献(在我们打开这些文档之前)
  • 因此,由于 git 历史,文档与特定版本的 Remix 耦合在一起

最后一点是我们对文档进行 SSR 而不是 SSG 的另一个主要原因。我们能够永久保留每个版本的 Remix 的文档。我们甚至可以在不重新部署的情况下渲染 dev 文档的最新版本。想象一下,每次有人提交更改时都为 每个 Remix 版本的 每个 文档进行重建。那将是巨大的工作量。

Remix docs version dropdown menu

我们能够通过在 loader 中从 GitHub 获取 markdown,并在路由中服务器渲染请求的文档页面来实现这一点。由于此内容不会频繁更改,我们利用 LRU 缓存在服务器上缓存结果 5 分钟。我们还发送一个带有 stale-while-revalidate 指令的 Cache-Control 标头以及响应,这样当有新文档时,将提供旧文档,同时新文档会在 CDN 中渲染并填充以供下次请求使用。

return json(
  { doc },
  {
    headers: {
      "Cache-Control": "max-age=300, stale-while-revalidate=604800",
    },
  },
);

如果你讨厌偶尔落后于最新技术 5 分钟,你可以直接阅读源文档本身,或者去看心理医生。

案例展示和资源

您可能已经注意到,我们最近开始在网站上添加更多页面

  • Remix 案例展示,以展示使用 Remix 构建更好网站的公司、组织、非营利组织和独立开发者
  • Remix 资源,以突出社区为社区构建的堆栈、模板和库

我们有很多计划来继续改进这些页面,并添加更多资源来帮助社区。然而,到目前为止,向这些页面贡献示例只能通过希望核心团队注意到您的项目并添加它来实现。我们很高兴能够改变这种状况,使 案例展示资源 贡献只需一个 PR 即可完成。

Vite!

Remix.run 已经使用了新的 Vite 插件。我们升级到 Vite 主要是为了试用新的插件,并确保它适用于实际的生产站点。开源 remix.run 意味着,当我们试用新功能时,更容易在生产网站上展示这些功能并分享这些知识。

以下是一些(简化的)示例,其中我们删除了 Remix 强加给我们的笨拙模式,而 Vite 使其变得非常简单。

加载博客文章的 markdown

- import path from "path";
- import fs from "fs";

- const dataPath = path.join(__dirname, "..", "data");
- const blogPath = path.join(dataPath, "posts");

+ const postContentsBySlug = Object.fromEntries(
+   Object.entries(
+     import.meta.glob("../../data/posts/*.md", { as: "raw", eager: true }),
+   ).map(([filePath, contents]) => [
+     filePath.replace("../../data/posts/", "").replace(/\.md$/, ""),
+     contents,
+   ]),
+ );

export async function getBlogPost(slug: string): Promise<BlogPost> {
  let cached = postsCache.get(slug);
-   if (cached) return cached;
-   let filePath = path.join(blogPath, slug + ".md");
-   let contents: string;
-   try {
-     contents = (await fs.promises.readFile(filePath)).toString();
-   } catch (e) {
+   let contents = postContentsBySlug[slug];
+   if (!contents) {
    throw new Response("Not Found", { status: 404, statusText: "Not Found" });
  }
}

从 yaml 文件加载作者数据

import yaml from "yaml";
+ import authorsYamlFileContents from "../../data/authors.yml?raw";

- const AUTHORS: BlogAuthor[] = yaml.parse(
-   fs.readFileSync(path.join(dataPath, "authors.yml")).toString(),
- )

+ const AUTHORS: BlogAuthor[] = yaml.parse(authorsYamlFileContents);

查看 Vite 迁移 PR,顺便也看看 将我们的服务器从 CJS 切换到 ESM 是多么容易。

如何贡献

这是我最兴奋的部分。

就我个人而言,我想在鼓起勇气之前 几年 就做出开源贡献。虽然这更多的是关于我自己,但我知道一件事会使事情变得更容易,那就是如果我贡献的是一个开源网站而不是一个库。为什么?因为我每天在工作中都在处理网站,这是我早已了解的。我没有编写库。事实上,编写库的 Web 开发者比编写网站的要少得多。

这就是为什么我很高兴能够开源我们的网站。我坚信,对于许多开发者来说,贡献一个带有公开存储库的网站要比贡献一个库简单得多。我希望这个公告能为你们中的许多人提供一个更容易的机会来完成你们的第一次开源贡献。

事实上,我们已经提前策划了一些 新手友好的问题,以便更容易入门。这些问题是我们特别标记为对新贡献者友好的问题。因此,无论你是经验丰富的开源贡献者还是只是想尝试一下,我们都很高兴在“拉取请求”选项卡中看到你的 GitHub 个人资料出现。

祝你贡献愉快,迫不及待地想一起构建一个更好的 remix.run。


获取最新的 Remix 新闻

成为第一个了解新 Remix 功能、社区活动和教程的人。