about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEric Bailey <git@esb.lol>2024-09-19 17:57:15 -0500
committerGitHub <noreply@github.com>2024-09-19 17:57:15 -0500
commit22410a3cee459761a9eb2d1a52de99557a424797 (patch)
tree2ce6a0341707abc710dc76459e0e946a1153be2c
parentc8184e823dc79d1ff1f71571bae5cb7611f61d5d (diff)
downloadvoidsky-22410a3cee459761a9eb2d1a52de99557a424797.tar.zst
[Neue] Parallel font loading on web (#5411)
* Parallel font loading

(cherry picked from commit 10e2b05b575bbbf8b0ca5b4a336817cd902d712b)

* Handle failures

* Rely on font-face and preload tags for font loading (#5431)

* Cache fonts for a year
-rw-r--r--bskyweb/cmd/bskyweb/server.go5
-rw-r--r--bskyweb/static/media/Inter-Black.66e9a87f1c921e844ed4.otfbin0 -> 619772 bytes
-rw-r--r--bskyweb/static/media/Inter-BlackItalic.27b9f0ad06fd13a7b9da.otfbin0 -> 592516 bytes
-rw-r--r--bskyweb/static/media/Inter-Bold.8d330503e1d034ad68de.otfbin0 -> 626056 bytes
-rw-r--r--bskyweb/static/media/Inter-BoldItalic.bb17e63f9baa0d861a20.otfbin0 -> 604316 bytes
-rw-r--r--bskyweb/static/media/Inter-ExtraBold.ff2581a193bf6b7e0b06.otfbin0 -> 627736 bytes
-rw-r--r--bskyweb/static/media/Inter-ExtraBoldItalic.0e50b40728d24d40fdf4.otfbin0 -> 603412 bytes
-rw-r--r--bskyweb/static/media/Inter-Italic.95778eb0c75dc956257e.otfbin0 -> 586752 bytes
-rw-r--r--bskyweb/static/media/Inter-Medium.296aa2d65964269836b3.otfbin0 -> 622088 bytes
-rw-r--r--bskyweb/static/media/Inter-MediumItalic.0e57e17a6311368e2114.otfbin0 -> 599652 bytes
-rw-r--r--bskyweb/static/media/Inter-Regular.1f5ed03b6dd9fd1f9982.otfbin0 -> 605092 bytes
-rw-r--r--bskyweb/static/media/Inter-SemiBold.2277990330981b8409bb.otfbin0 -> 624244 bytes
-rw-r--r--bskyweb/static/media/Inter-SemiBoldItalic.f62fea3df3a521d6c8a7.otfbin0 -> 602496 bytes
-rw-r--r--bskyweb/static/media/MaterialIcons.f20305dee9d396fea5c7.ttfbin0 -> 356840 bytes
-rw-r--r--bskyweb/templates/base.html98
-rw-r--r--src/App.native.tsx5
-rw-r--r--src/App.web.tsx5
-rw-r--r--src/alf/fonts.ts19
-rw-r--r--web/index.html99
19 files changed, 216 insertions, 15 deletions
diff --git a/bskyweb/cmd/bskyweb/server.go b/bskyweb/cmd/bskyweb/server.go
index 2d75a2b72..fd80a5ed1 100644
--- a/bskyweb/cmd/bskyweb/server.go
+++ b/bskyweb/cmd/bskyweb/server.go
@@ -210,6 +210,11 @@ func serve(cctx *cli.Context) error {
 				maxAge = 7 * (60 * 60 * 24) // 1 week
 			}
 
+			// fonts can be cached for a year
+			if strings.HasSuffix(path, ".otf") {
+				maxAge = 365 * (60 * 60 * 24) // 1 year
+			}
+
 			c.Response().Header().Set("Cache-Control", fmt.Sprintf("public, max-age=%d", maxAge))
 			return next(c)
 		}
diff --git a/bskyweb/static/media/Inter-Black.66e9a87f1c921e844ed4.otf b/bskyweb/static/media/Inter-Black.66e9a87f1c921e844ed4.otf
new file mode 100644
index 000000000..44d1779af
--- /dev/null
+++ b/bskyweb/static/media/Inter-Black.66e9a87f1c921e844ed4.otf
Binary files differdiff --git a/bskyweb/static/media/Inter-BlackItalic.27b9f0ad06fd13a7b9da.otf b/bskyweb/static/media/Inter-BlackItalic.27b9f0ad06fd13a7b9da.otf
new file mode 100644
index 000000000..6fc475e41
--- /dev/null
+++ b/bskyweb/static/media/Inter-BlackItalic.27b9f0ad06fd13a7b9da.otf
Binary files differdiff --git a/bskyweb/static/media/Inter-Bold.8d330503e1d034ad68de.otf b/bskyweb/static/media/Inter-Bold.8d330503e1d034ad68de.otf
new file mode 100644
index 000000000..58a38073e
--- /dev/null
+++ b/bskyweb/static/media/Inter-Bold.8d330503e1d034ad68de.otf
Binary files differdiff --git a/bskyweb/static/media/Inter-BoldItalic.bb17e63f9baa0d861a20.otf b/bskyweb/static/media/Inter-BoldItalic.bb17e63f9baa0d861a20.otf
new file mode 100644
index 000000000..e67935aa5
--- /dev/null
+++ b/bskyweb/static/media/Inter-BoldItalic.bb17e63f9baa0d861a20.otf
Binary files differdiff --git a/bskyweb/static/media/Inter-ExtraBold.ff2581a193bf6b7e0b06.otf b/bskyweb/static/media/Inter-ExtraBold.ff2581a193bf6b7e0b06.otf
new file mode 100644
index 000000000..66cd95228
--- /dev/null
+++ b/bskyweb/static/media/Inter-ExtraBold.ff2581a193bf6b7e0b06.otf
Binary files differdiff --git a/bskyweb/static/media/Inter-ExtraBoldItalic.0e50b40728d24d40fdf4.otf b/bskyweb/static/media/Inter-ExtraBoldItalic.0e50b40728d24d40fdf4.otf
new file mode 100644
index 000000000..f269814a6
--- /dev/null
+++ b/bskyweb/static/media/Inter-ExtraBoldItalic.0e50b40728d24d40fdf4.otf
Binary files differdiff --git a/bskyweb/static/media/Inter-Italic.95778eb0c75dc956257e.otf b/bskyweb/static/media/Inter-Italic.95778eb0c75dc956257e.otf
new file mode 100644
index 000000000..f78848b98
--- /dev/null
+++ b/bskyweb/static/media/Inter-Italic.95778eb0c75dc956257e.otf
Binary files differdiff --git a/bskyweb/static/media/Inter-Medium.296aa2d65964269836b3.otf b/bskyweb/static/media/Inter-Medium.296aa2d65964269836b3.otf
new file mode 100644
index 000000000..f44f89ada
--- /dev/null
+++ b/bskyweb/static/media/Inter-Medium.296aa2d65964269836b3.otf
Binary files differdiff --git a/bskyweb/static/media/Inter-MediumItalic.0e57e17a6311368e2114.otf b/bskyweb/static/media/Inter-MediumItalic.0e57e17a6311368e2114.otf
new file mode 100644
index 000000000..1970f5721
--- /dev/null
+++ b/bskyweb/static/media/Inter-MediumItalic.0e57e17a6311368e2114.otf
Binary files differdiff --git a/bskyweb/static/media/Inter-Regular.1f5ed03b6dd9fd1f9982.otf b/bskyweb/static/media/Inter-Regular.1f5ed03b6dd9fd1f9982.otf
new file mode 100644
index 000000000..2d0bd1d64
--- /dev/null
+++ b/bskyweb/static/media/Inter-Regular.1f5ed03b6dd9fd1f9982.otf
Binary files differdiff --git a/bskyweb/static/media/Inter-SemiBold.2277990330981b8409bb.otf b/bskyweb/static/media/Inter-SemiBold.2277990330981b8409bb.otf
new file mode 100644
index 000000000..52c84550b
--- /dev/null
+++ b/bskyweb/static/media/Inter-SemiBold.2277990330981b8409bb.otf
Binary files differdiff --git a/bskyweb/static/media/Inter-SemiBoldItalic.f62fea3df3a521d6c8a7.otf b/bskyweb/static/media/Inter-SemiBoldItalic.f62fea3df3a521d6c8a7.otf
new file mode 100644
index 000000000..b725bfc88
--- /dev/null
+++ b/bskyweb/static/media/Inter-SemiBoldItalic.f62fea3df3a521d6c8a7.otf
Binary files differdiff --git a/bskyweb/static/media/MaterialIcons.f20305dee9d396fea5c7.ttf b/bskyweb/static/media/MaterialIcons.f20305dee9d396fea5c7.ttf
new file mode 100644
index 000000000..9d09b0feb
--- /dev/null
+++ b/bskyweb/static/media/MaterialIcons.f20305dee9d396fea5c7.ttf
Binary files differdiff --git a/bskyweb/templates/base.html b/bskyweb/templates/base.html
index f7acd4614..b0c3c2195 100644
--- a/bskyweb/templates/base.html
+++ b/bskyweb/templates/base.html
@@ -13,7 +13,105 @@
 
   <!-- Hello Humans! API docs at https://atproto.com -->
 
+  <link rel="preload" as="font" type="font/otf" href="/static/media/Inter-Regular.1f5ed03b6dd9fd1f9982.otf">
+  <link rel="preload" as="font" type="font/otf" href="/static/media/Inter-Italic.95778eb0c75dc956257e.otf">
+  <link rel="preload" as="font" type="font/otf" href="/static/media/Inter-Medium.296aa2d65964269836b3.otf">
+  <link rel="preload" as="font" type="font/otf" href="/static/media/Inter-MediumItalic.0e57e17a6311368e2114.otf">
+  <link rel="preload" as="font" type="font/otf" href="/static/media/Inter-SemiBold.2277990330981b8409bb.otf">
+  <link rel="preload" as="font" type="font/otf" href="/static/media/Inter-SemiBoldItalic.f62fea3df3a521d6c8a7.otf">
+  <link rel="preload" as="font" type="font/otf" href="/static/media/Inter-Bold.8d330503e1d034ad68de.otf">
+  <link rel="preload" as="font" type="font/otf" href="/static/media/Inter-BoldItalic.bb17e63f9baa0d861a20.otf">
+  <link rel="preload" as="font" type="font/otf" href="/static/media/Inter-ExtraBold.ff2581a193bf6b7e0b06.otf">
+  <link rel="preload" as="font" type="font/otf" href="/static/media/Inter-ExtraBoldItalic.0e50b40728d24d40fdf4.otf">
+  <link rel="preload" as="font" type="font/otf" href="/static/media/Inter-Black.66e9a87f1c921e844ed4.otf">
+  <link rel="preload" as="font" type="font/otf" href="/static/media/Inter-BlackItalic.27b9f0ad06fd13a7b9da.otf">
+
   <style>
+    @font-face {
+      font-family: "Inter-Regular";
+      src: local("Inter-Regular"), url(/static/media/Inter-Regular.1f5ed03b6dd9fd1f9982.otf) format("font/otf");
+      font-weight: 400;
+      font-style: normal;
+      font-display: swap;
+    }
+    @font-face {
+      font-family: "Inter-Italic";
+      src: local("Inter-Italic"), url(/static/media/Inter-Italic.95778eb0c75dc956257e.otf) format("font/otf");
+      font-weight: 400;
+      font-style: italic;
+      font-display: swap;
+    }
+    @font-face {
+      font-family: "Inter-Medium";
+      src: local("Inter-Medium"), url(/static/media/Inter-Medium.296aa2d65964269836b3.otf) format("font/otf");
+      font-weight: 500;
+      font-style: normal;
+      font-display: swap;
+    }
+    @font-face {
+      font-family: "Inter-MediumItalic";
+      src: local("Inter-MediumItalic"), url(/static/media/Inter-MediumItalic.0e57e17a6311368e2114.otf) format("font/otf");
+      font-weight: 500;
+      font-style: italic;
+      font-display: swap;
+    }
+    @font-face {
+      font-family: "Inter-SemiBold";
+      src: local("Inter-SemiBold"), url(/static/media/Inter-SemiBold.2277990330981b8409bb.otf) format("font/otf");
+      font-weight: 600;
+      font-style: normal;
+      font-display: swap;
+    }
+    @font-face {
+      font-family: "Inter-SemiBoldItalic";
+      src: local("Inter-SemiBoldItalic"), url(/static/media/Inter-SemiBoldItalic.f62fea3df3a521d6c8a7.otf) format("font/otf");
+      font-weight: 600;
+      font-style: italic;
+      font-display: swap;
+    }
+    @font-face {
+      font-family: "Inter-Bold";
+      src: local("Inter-Bold"), url(/static/media/Inter-Bold.8d330503e1d034ad68de.otf) format("font/otf");
+      font-weight: 700;
+      font-style: normal;
+      font-display: swap;
+    }
+    @font-face {
+      font-family: "Inter-BoldItalic";
+      src: local("Inter-BoldItalic"), url(/static/media/Inter-BoldItalic.bb17e63f9baa0d861a20.otf) format("font/otf");
+      font-weight: 700;
+      font-style: italic;
+      font-display: swap;
+    }
+    @font-face {
+      font-family: "Inter-ExtraBold";
+      src: local("Inter-ExtraBold"), url(/static/media/Inter-ExtraBold.ff2581a193bf6b7e0b06.otf) format("font/otf");
+      font-weight: 800;
+      font-style: normal;
+      font-display: swap;
+    }
+    @font-face {
+      font-family: "Inter-ExtraBoldItalic";
+      src: local("Inter-ExtraBoldItalic"), url(/static/media/Inter-ExtraBoldItalic.0e50b40728d24d40fdf4.otf) format("font/otf");
+      font-weight: 800;
+      font-style: italic;
+      font-display: swap;
+    }
+    @font-face {
+      font-family: "Inter-Black";
+      src: local("Inter-Black"), url(/static/media/Inter-Black.66e9a87f1c921e844ed4.otf) format("font/otf");
+      font-weight: 900;
+      font-style: normal;
+      font-display: swap;
+    }
+    @font-face {
+      font-family: "Inter-BlackItalic";
+      src: local("Inter-BlackItalic"), url(/static/media/Inter-BlackItalic.27b9f0ad06fd13a7b9da.otf) format("font/otf");
+      font-weight: 900;
+      font-style: italic;
+      font-display: swap;
+    }
+
     /**
      * Extend the react-native-web reset:
      * https://github.com/necolas/react-native-web/blob/master/packages/react-native-web/src/exports/StyleSheet/initialRules.js
diff --git a/src/App.native.tsx b/src/App.native.tsx
index b780880b3..2ec666e2c 100644
--- a/src/App.native.tsx
+++ b/src/App.native.tsx
@@ -55,7 +55,7 @@ import {TestCtrls} from '#/view/com/testing/TestCtrls'
 import {Provider as VideoVolumeProvider} from '#/view/com/util/post-embeds/VideoVolumeContext'
 import * as Toast from '#/view/com/util/Toast'
 import {Shell} from '#/view/shell'
-import {ThemeProvider as Alf, useFonts} from '#/alf'
+import {ThemeProvider as Alf} from '#/alf'
 import {useColorModeTheme} from '#/alf/util/useColorModeTheme'
 import {NuxDialogs} from '#/components/dialogs/nuxs'
 import {useStarterPackEntry} from '#/components/hooks/useStarterPackEntry'
@@ -156,13 +156,12 @@ function InnerApp() {
 
 function App() {
   const [isReady, setReady] = useState(false)
-  const [loaded] = useFonts()
 
   React.useEffect(() => {
     initPersistedState().then(() => setReady(true))
   }, [])
 
-  if (!isReady || !loaded) {
+  if (!isReady) {
     return null
   }
 
diff --git a/src/App.web.tsx b/src/App.web.tsx
index 075ce964a..fa5f1de93 100644
--- a/src/App.web.tsx
+++ b/src/App.web.tsx
@@ -46,7 +46,7 @@ import {Provider as VideoVolumeProvider} from '#/view/com/util/post-embeds/Video
 import * as Toast from '#/view/com/util/Toast'
 import {ToastContainer} from '#/view/com/util/Toast.web'
 import {Shell} from '#/view/shell/index'
-import {ThemeProvider as Alf, useFonts} from '#/alf'
+import {ThemeProvider as Alf} from '#/alf'
 import {useColorModeTheme} from '#/alf/util/useColorModeTheme'
 import {NuxDialogs} from '#/components/dialogs/nuxs'
 import {useStarterPackEntry} from '#/components/hooks/useStarterPackEntry'
@@ -146,13 +146,12 @@ function InnerApp() {
 
 function App() {
   const [isReady, setReady] = useState(false)
-  const [loaded, error] = useFonts()
 
   React.useEffect(() => {
     initPersistedState().then(() => setReady(true))
   }, [])
 
-  if (!isReady || (!loaded && !error)) {
+  if (!isReady) {
     return null
   }
 
diff --git a/src/alf/fonts.ts b/src/alf/fonts.ts
index 264e51fa8..7f6bde5fa 100644
--- a/src/alf/fonts.ts
+++ b/src/alf/fonts.ts
@@ -1,6 +1,6 @@
 import {useFonts as defaultUseFonts} from 'expo-font'
 
-import {isNative, isWeb} from '#/platform/detection'
+import {isWeb} from '#/platform/detection'
 import {Device, device} from '#/storage'
 
 const FAMILIES = `-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Liberation Sans", Helvetica, Arial, sans-serif`
@@ -35,15 +35,16 @@ export function setFontFamily(fontFamily: Device['fontFamily']) {
 }
 
 /*
- * Unused fonts are commented out, but the files are there if we need them.
+ * IMPORTANT: This is unused. Expo statically extracts these fonts, but we load
+ * them manually so that we can parallelize the loading along with the JS
+ * bundle.
+ *
+ * See `#/alf/util/useFonts` for the actually used hooks.
+ *
+ * All used fonts MUST be configured here. Unused fonts are commented out, but
+ * the files are there if we need them.
  */
-export function useFonts() {
-  /**
-   * For native, the `expo-font` config plugin embeds the fonts in the
-   * application binary. But `expo-font` isn't supported on web, so we fall
-   * back to async loading here.
-   */
-  if (isNative) return [true, null]
+export function DO_NOT_USE() {
   return defaultUseFonts({
     // 'Inter-Thin': require('../../assets/fonts/inter/Inter-Thin.otf'),
     // 'Inter-ThinItalic': require('../../assets/fonts/inter/Inter-ThinItalic.otf'),
diff --git a/web/index.html b/web/index.html
index 1f2309809..6e1fa9061 100644
--- a/web/index.html
+++ b/web/index.html
@@ -17,7 +17,106 @@
     <link rel="preconnect" href="https://bsky.social">
     <link rel="preconnect" href="https://bsky.network">
     <title>%WEB_TITLE%</title>
+
+    <link rel="preload" as="font" type="font/otf" href="/static/media/Inter-Regular.1f5ed03b6dd9fd1f9982.otf">
+    <link rel="preload" as="font" type="font/otf" href="/static/media/Inter-Italic.95778eb0c75dc956257e.otf">
+    <link rel="preload" as="font" type="font/otf" href="/static/media/Inter-Medium.296aa2d65964269836b3.otf">
+    <link rel="preload" as="font" type="font/otf" href="/static/media/Inter-MediumItalic.0e57e17a6311368e2114.otf">
+    <link rel="preload" as="font" type="font/otf" href="/static/media/Inter-SemiBold.2277990330981b8409bb.otf">
+    <link rel="preload" as="font" type="font/otf" href="/static/media/Inter-SemiBoldItalic.f62fea3df3a521d6c8a7.otf">
+    <link rel="preload" as="font" type="font/otf" href="/static/media/Inter-Bold.8d330503e1d034ad68de.otf">
+    <link rel="preload" as="font" type="font/otf" href="/static/media/Inter-BoldItalic.bb17e63f9baa0d861a20.otf">
+    <link rel="preload" as="font" type="font/otf" href="/static/media/Inter-ExtraBold.ff2581a193bf6b7e0b06.otf">
+    <link rel="preload" as="font" type="font/otf" href="/static/media/Inter-ExtraBoldItalic.0e50b40728d24d40fdf4.otf">
+    <link rel="preload" as="font" type="font/otf" href="/static/media/Inter-Black.66e9a87f1c921e844ed4.otf">
+    <link rel="preload" as="font" type="font/otf" href="/static/media/Inter-BlackItalic.27b9f0ad06fd13a7b9da.otf">
+
     <style>
+      @font-face {
+        font-family: "Inter-Regular";
+        src: local("Inter-Regular"), url(/static/media/Inter-Regular.1f5ed03b6dd9fd1f9982.otf) format("font/otf");
+        font-weight: 400;
+        font-style: normal;
+        font-display: swap;
+      }
+      @font-face {
+        font-family: "Inter-Italic";
+        src: local("Inter-Italic"), url(/static/media/Inter-Italic.95778eb0c75dc956257e.otf) format("font/otf");
+        font-weight: 400;
+        font-style: italic;
+        font-display: swap;
+      }
+      @font-face {
+        font-family: "Inter-Medium";
+        src: local("Inter-Medium"), url(/static/media/Inter-Medium.296aa2d65964269836b3.otf) format("font/otf");
+        font-weight: 500;
+        font-style: normal;
+        font-display: swap;
+      }
+      @font-face {
+        font-family: "Inter-MediumItalic";
+        src: local("Inter-MediumItalic"), url(/static/media/Inter-MediumItalic.0e57e17a6311368e2114.otf) format("font/otf");
+        font-weight: 500;
+        font-style: italic;
+        font-display: swap;
+      }
+      @font-face {
+        font-family: "Inter-SemiBold";
+        src: local("Inter-SemiBold"), url(/static/media/Inter-SemiBold.2277990330981b8409bb.otf) format("font/otf");
+        font-weight: 600;
+        font-style: normal;
+        font-display: swap;
+      }
+      @font-face {
+        font-family: "Inter-SemiBoldItalic";
+        src: local("Inter-SemiBoldItalic"), url(/static/media/Inter-SemiBoldItalic.f62fea3df3a521d6c8a7.otf) format("font/otf");
+        font-weight: 600;
+        font-style: italic;
+        font-display: swap;
+      }
+      @font-face {
+        font-family: "Inter-Bold";
+        src: local("Inter-Bold"), url(/static/media/Inter-Bold.8d330503e1d034ad68de.otf) format("font/otf");
+        font-weight: 700;
+        font-style: normal;
+        font-display: swap;
+      }
+      @font-face {
+        font-family: "Inter-BoldItalic";
+        src: local("Inter-BoldItalic"), url(/static/media/Inter-BoldItalic.bb17e63f9baa0d861a20.otf) format("font/otf");
+        font-weight: 700;
+        font-style: italic;
+        font-display: swap;
+      }
+      @font-face {
+        font-family: "Inter-ExtraBold";
+        src: local("Inter-ExtraBold"), url(/static/media/Inter-ExtraBold.ff2581a193bf6b7e0b06.otf) format("font/otf");
+        font-weight: 800;
+        font-style: normal;
+        font-display: swap;
+      }
+      @font-face {
+        font-family: "Inter-ExtraBoldItalic";
+        src: local("Inter-ExtraBoldItalic"), url(/static/media/Inter-ExtraBoldItalic.0e50b40728d24d40fdf4.otf) format("font/otf");
+        font-weight: 800;
+        font-style: italic;
+        font-display: swap;
+      }
+      @font-face {
+        font-family: "Inter-Black";
+        src: local("Inter-Black"), url(/static/media/Inter-Black.66e9a87f1c921e844ed4.otf) format("font/otf");
+        font-weight: 900;
+        font-style: normal;
+        font-display: swap;
+      }
+      @font-face {
+        font-family: "Inter-BlackItalic";
+        src: local("Inter-BlackItalic"), url(/static/media/Inter-BlackItalic.27b9f0ad06fd13a7b9da.otf) format("font/otf");
+        font-weight: 900;
+        font-style: italic;
+        font-display: swap;
+      }
+
       /**
        * Extend the react-native-web reset:
        * https://github.com/necolas/react-native-web/blob/master/packages/react-native-web/src/exports/StyleSheet/initialRules.js