diff --git a/src/components/Contributors/index.tsx b/src/components/Contributors/index.tsx
index 4d94945de28..a3c3a55ec83 100644
--- a/src/components/Contributors/index.tsx
+++ b/src/components/Contributors/index.tsx
@@ -17,22 +17,35 @@ type AllContributorsRc = {
contributors: (Contributor & { contributions?: string[] })[]
}
-// Read `.all-contributorsrc` (bot-maintained) once at module load.
-const raw = readFileSync(join(process.cwd(), ".all-contributorsrc"), "utf-8")
-const { contributors: rawContributors } = JSON.parse(raw) as AllContributorsRc
-
-// Trim to the fields the card actually renders and shuffle once per SSG worker.
-const shuffledContributors: Contributor[] = shuffle(
- rawContributors.map(({ login, name, avatar_url, profile }) => ({
- login,
- name,
- avatar_url,
- profile,
- }))
-)
+let shuffledContributors: Contributor[] | undefined
+
+// Read `.all-contributorsrc` (bot-maintained) on first render and cache.
+// Deferred (not module-load) so non-Next bundlers like Storybook can import
+// this module without evaluating Node's `fs`.
+const getShuffledContributors = (): Contributor[] => {
+ if (!shuffledContributors) {
+ const raw = readFileSync(
+ join(process.cwd(), ".all-contributorsrc"),
+ "utf-8"
+ )
+ const { contributors: rawContributors } = JSON.parse(
+ raw
+ ) as AllContributorsRc
+
+ shuffledContributors = shuffle(
+ rawContributors.map(({ login, name, avatar_url, profile }) => ({
+ login,
+ name,
+ avatar_url,
+ profile,
+ }))
+ )
+ }
+ return shuffledContributors
+}
const Contributors = ({ contributors }: ContributorsProps = {}) => (
-
+
)
export default Contributors