Remix Website homepage
2024 年 1 月 31 日

開放 Remix 網站原始碼

Brooks Lybrand
開發者關係經理

今天,我們非常興奮地宣布這個網站現在已開源!我們邀請您探索並從原始碼中學習,甚至可以考慮貢獻

我們為何要開源

兩年多前,Remix 這個框架開源了。Ryan 和 Michael 至今已投入 10 年時間開發開源軟體。即使是 reactrouter.com 也是一個公開的儲存庫。毋庸置疑,我們是開源的忠實信徒。

那麼,為什麼不是每個人都將他們的網站開源呢?這是有充分理由的:

  • 開源會增加潛在洩漏資料或商業邏輯的安全風險
  • 公開的儲存庫需要維護者花更多時間來分類問題、審查 PR,以及參與關於功能要求和改進的討論
  • 通常,OSS 維護者會投入所有精力使他們的函式庫和網站變得美觀,而網站背後的程式碼卻是為了盡快完成並開始獲取使用者而寫成的爛攤子(這不是個人經驗,或任何類似的 😅)

好吧,無論如何我們還是要開源它。

我們相信利大於弊。開源我們的網站讓我們能夠提供一個真實的 Remix 網站來學習。它也給了我們一個機會,可以更輕鬆地獲得來自社群中善良開發者的回饋和貢獻(感謝 Ryan Leichty 潤飾了我們的文件)。此外,雖然我們的網站大多相當簡單,但我們確實做了一些很酷的事情。

網站導覽

首頁是如何運作的?!

我還是不知道。

Ryan Florence 寫了它,現在你可以閱讀 1500 行的 ScrollExperience 元件原始碼。或者你可以像我一樣多次滾動瀏覽它,以查看所有酷炫的動畫。

Remix run website scroll experience

沒有 SSG 的文件

我們網站的獨特功能之一是,我們會在請求時進行伺服器端渲染我們的文件,而不是使用更常見的靜態網站生成(在建置期間預先渲染 HTML)策略。

我們這樣做的主要原因是,我們不必每次修正錯字時都重建整個網站。事實上,Remix 文件根本不存在於此儲存庫中。您可以在 Remix 程式碼庫中,Remix 原始碼旁邊找到它們。我們將文件放在這裡:

  • 為了使其與其記錄的程式碼緊密相連
  • 為了使其易於貢獻(在我們開放這些文件之前)
  • 因此,歸功於 git 歷史,文件會與特定版本的 Remix 耦合

最後一點是我們伺服器端渲染文件而不是靜態生成它們的另一個主要原因。我們能夠永久保留每個 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 是多麼容易 交換我們的伺服器從 CJS 到 ESM

如何貢獻

這是我最興奮的部分。

就我個人而言,我想在鼓起勇氣之前多年就為開源做出貢獻。雖然這更能說明我,但我知道有一件事會讓它更容易,那就是我貢獻到開源網站而不是函式庫。為什麼?因為我在工作時整天都在開發網站,這是我已經知道的事情。我沒有寫函式庫。事實上,撰寫網站的網頁開發人員遠多於撰寫函式庫的網頁開發人員。

這就是為什麼我很高興開源我們的網站。我堅信,對於許多開發人員來說,轉向為具有公共儲存庫的網站做出貢獻比為函式庫做出貢獻要簡單得多。我希望這個公告能為你們中的許多人提供一個更簡單的機會,讓你們做出有史以來的第一個開源貢獻。

事實上,我們已經策劃了許多良好的入門議題,讓入門更容易。這些問題是我們特別標記為對新貢獻者友好的問題。因此,無論您是經驗豐富的 OSS 貢獻者還是只是想嘗試一下,我們都很高興在「提取請求」標籤中看到您的 GitHub 個人資料。

祝您貢獻愉快,迫不及待想一起建立更好的 remix.run。


取得有關最新 Remix 新聞的更新

成為第一個了解新 Remix 功能、社群活動和教學課程的人。