PWA 最佳实践:网络字体还是本地字体?

PWA Best Practice: Web or Local Fonts?

我正在构建一个 preact PWA(渐进式 Web 应用程序),我不知道是应该将字体保留在外部以减小我的应用程序大小,还是将字体保留在本地以改进离线查看?最佳做法是什么?

2021 年 2 月更新:浏览器通常朝着 partitioning the HTTP cache, meaning that CDN-like URLs, such as Google Fonts, are less likely to result in cache hits due to an unrelated web app having previously requesting the same URL. This eliminates a common argument in favor of using fonts from a CDN. A project like fontsource 的方向发展可以自动传送开源字体的本地副本,虽然这需要更多工作,但如果您最关心性能,我可能会选择它。

我不认为使用第三方或第一方托管的网络字体会根据您的要求有所不同。可以在 Service Worker 内部使用缓存存储 API 来缓存一般的第一方或第三方请求,包括 Web 字体请求,并在离线时使用这些缓存资源。

有一些加载网络字体的一般最佳实践,Zach Leatherman 的 this article 是我的首选参考。不过,这些技术并不特定于构建具有离线功能的 PWA。

首选在文件夹 /fonts/

中的根网站文件中托管字体文件

我们不得不使用 https://www.dafont.com/ which provided a .ttf file, so will need to use any free converter tool to change that into a .woff file, in my case: https://convertio.co/ttf-woff/ 帮助的字体。

然后在 CSS 中声明新字体并在需要的地方使用:

@font-face {
    font-family: 'Custom Font';
    font-weight: 400;
    font-style: normal;
    font-display: swap;
    /* Read next point */
    unicode-range: U+000-5FF;
    /* Download only latin glyphs */
    src:    local('Custom Font'),
            url('/fonts/custom-font.woff') format('woff');
}
h1, h2, h3, h4, h5 {
    font-family: 'Custom Font', 'Helvetica', 'Arial', 'sans-serif';
}

我们的 PWA 需要一个 service worker 在本地存储文件以用于离线模式,所以我们调用 JS service-worker.js,它位于网站文件的根目录:

// When document is ready.
document.addEventListener('DOMContentLoaded', function () {
    // Steps followed from Google developer codelabs:
    // https://codelabs.developers.google.com/codelabs/offline/#5
    var registerServiceWorker = function registerServiceWorker() {
        if('serviceWorker' in navigator) {
            navigator.serviceWorker.register('/service-worker.js');
        }
    }

    registerServiceWorker();
});

在我们的 /service-worker.js 中,对于一个基本网站,所有这些文件都需要:

self.addEventListener('install', function(e) {
    e.waitUntil(
        caches.open('my-website-name').then(function(cache) {
            return cache.addAll([
                '/',
                '/favicon.ico',
                '/manifest.json',
                '/fonts/custom-font.woff',
                '/images/favicon/android-chrome-192x192.png',
                '/images/favicon/android-chrome-512x512.png',
                '/images/favicon/apple-touch-icon.png',
                '/images/favicon/favicon-16x16.png',
                '/images/favicon/favicon-32x32.png',
                '/images/favicon/maskable_icon.png',
                '/images/favicon/monochrome_icon.png'
            ]);
        })
    );
});
self.addEventListener('fetch', function(event) {
    event.respondWith(
        caches.match(event.request).then(function(response) {
            return response || fetch(event.request);
        })
    );
});

确保为此 /service-worker.js 文件更新 my-website-name,并通过添加 PWA 离线正常工作所需的所有其他网站文件来更新 cache.addAll 数组。

这基本上就是为您的 PWA 加载自定义字体文件的所有代码参考。