Remix Website homepage
2024年1月31日

Remix 网站开源

Brooks Lybrand
开发者关系经理

今天,我们非常高兴地宣布,这个网站现在是开源的!我们邀请您探索并学习源代码,也许还可以考虑贡献

我们为什么要开源

在两年前,Remix 框架开源了。Ryan 和 Michael 已经从事开源软件开发 10 年了。甚至reactrouter.com也是一个公共仓库。不用说,我们非常相信开源。

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

  • 开源会带来额外的安全风险,例如可能泄露数据或业务逻辑。
  • 公共仓库需要维护人员花费更多时间来分类问题、审查 PR 以及参与有关功能请求和改进的讨论。
  • 通常,开源软件维护人员会尽其所能使他们的库和网站变得漂亮,而网站背后的代码则是一团乱麻,其编写目的只是为了完成任务,以便他们可以开始吸引用户(并不是在说我自己的经历或任何类似的事情 😅)。

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

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

网站概览

首页是如何工作的?!

我仍然不知道。

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

Remix run website scroll experience

无需 SSG 的文档

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

我们这样做的主要原因是为了避免每次修复错别字时都需要重新构建整个网站。事实上,Remix 文档根本不存在于此仓库中。您可以在Remix 代码库中找到它们,就在 Remix 源代码旁边。我们将文档保留在此处

  • 以便使其靠近它所记录的代码。
  • 以便于贡献(在我们公开这些文档之前)。
  • 因此,文档与特定版本的 Remix 相关联,这要归功于 Git 历史记录。

最后一点是我们选择 SSR 而不是 SSG 的另一个主要原因。我们能够永远保留每个 Remix 版本的文档。我们甚至可以渲染开发文档的最新版本,而无需重新部署。想象一下,每次有人提交更改时,都需要为每个 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 开发人员远少于编写网站的 Web 开发人员。

这就是我为何如此兴奋地开源我们的网站的原因。我坚信,对于许多开发者来说,转向为具有公共存储库的网站做出贡献比为库做出贡献要简单得多。我希望此公告能为你们许多人提供一个更容易的机会,从而做出你们有史以来的第一次开源贡献。

事实上,我们已经整理了一些适合新手的问题,以便于入门。这些是我们专门标记为对新贡献者友好的问题。因此,无论您是经验丰富的开源软件贡献者还是刚刚开始尝试,我们都非常高兴看到您的 GitHub 个人资料出现在“拉取请求”选项卡中。

祝您贡献愉快,期待与您一起构建一个更好的 remix.run。


获取 Remix 最新资讯的更新

抢先了解 Remix 的新功能、社区活动和教程。