Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: Service worker (custom Astro integration) #242

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

decrek
Copy link
Member

@decrek decrek commented Jan 6, 2025

Changes

  • Add service worker setup with basic network first strategy on HTML pages
  • Made the decision to go for my own custom integration. It can serve as an example integration and I like the fact that we build our own service worker from a service-worker.ts file instead of generating one. I feel this is the most understandable for others and gives you maximum freedom over its implementation.

Associated issue

Resolves #199

How to test

  1. Open preview link
  2. Open devtools --> Application
  3. Verify a service worker is installed
  4. Go offline, refresh the page and verify that the HTML page is still served

Checklist

  • I have performed a self-review of my own code
  • I have made sure that my PR is easy to review (not too big, includes comments)
  • I have made updated relevant documentation files (in project README, docs/, etc)
  • I have added a decision log entry if the change affects the architecture or changes a significant technology
  • I have notified a reviewer

@decrek decrek requested a review from jbmoelker January 6, 2025 08:25
# Conflicts:
#	src/components/PerfHead/PerfHead.astro
Copy link

cloudflare-workers-and-pages bot commented Jan 6, 2025

Deploying head-start with  Cloudflare Pages  Cloudflare Pages

Latest commit: 4f9c35a
Status: ✅  Deploy successful!
Preview URL: https://92cd60c5.head-start.pages.dev
Branch Preview URL: https://feat-199-add-service-worker.head-start.pages.dev

View logs

@jurgenbelien jurgenbelien changed the title Add service worker trough astro integration Add service worker through astro integration Jan 6, 2025
@jbmoelker jbmoelker changed the title Add service worker through astro integration feature: Service worker (custom Astro integration) Jan 6, 2025
decrek

This comment was marked as spam.

Copy link
Member

@jbmoelker jbmoelker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good and works well! I pushed some basic documentation and added comments with a few more suggestions.

}

export const GET: APIRoute = async () => {
const output = await esbuild.build({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The esbuild.build config between dev and prod are (and should be) mostly the same (only minify and sourcemap are different). Should we move the shared config up to the root?

const buildConfig = {
    entryPoints: [srcFilename],
    outdir: outFilename,
    target: ['es2020'],
    bundle: true,
    write: false,
    allowOverwrite: true,
}

and use that in both places to keep everything in sync?, like:

const output = await esbuild.build({
   ...buildConfig,
   minify: false,
   sourcemaps: false,
});

cacheName: 'pages',
plugins: [
new CacheableResponsePlugin({
statuses: [0, 200],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we consider a package like http-status-codes to write StatusCodes.OK instead of 200? Or simply use some consts at the top, like statusOpaque = 0; and statusOk = 200? Or does this only complicate things?

(ironically that package doesn't have the opaque response status; I also had to look that up. So maybe a comment or link on that would be helpful instead)

self.addEventListener('activate', (event) => {
event.waitUntil(self.clients.claim());
});

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We discussed caching assets as well. Do we want to add that to this PR? Something like:

registerRoute(
  ({ request }) => request.url.pathname.startsWith('/_astro/'),
  new CacheFirst({
    cacheName: 'assets',
    plugins: [
      new CacheableResponsePlugin({
        statuses: [0, 200],
      }),
      new ExpirationPlugin({
        maxEntries: 50,
        maxAgeSeconds: 30 * 24 * 60 * 60, // 30 days
      }),
    ],
  })
);

What would be good expiration settings?

Or should we match immutable responses instead? Like:

registerRoute(
  async ({ request, response }) => {
    if (!response) return false;
    const cacheControl = response.headers.get('cache-control');
    return cacheControl?.split(' ').includes('immutable') ?? false;
  },
  /* ... same */
);

import { NetworkFirst } from 'workbox-strategies';
import { CacheableResponsePlugin } from 'workbox-cacheable-response';
import { ExpirationPlugin } from 'workbox-expiration';

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add config that makes cache cleanup easier in the future? Like:

import { setCacheNameDetails } from 'workbox-core';
import pkg from '@root/package.json';

setCacheNameDetails({
  prefix: pkg.name,
  suffix: 'v1',
});

@jbmoelker jbmoelker mentioned this pull request Jan 12, 2025
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add Service Worker
3 participants