Security News
Node.js EOL Versions CVE Dubbed the "Worst CVE of the Year" by Security Experts
Critics call the Node.js EOL CVE a misuse of the system, sparking debate over CVE standards and the growing noise in vulnerability databases.
astro-service-worker
Advanced tools
> ⚙️ Offline-capable [Astro](https://astro.build) apps via SWSR (Service Worker Side Rendering)
⚙️ Offline-capable Astro apps via SWSR (Service Worker Side Rendering)
astro-service-worker
will take your Astro SSR project, and create a service worker build out of it. This has several benefits:
All you have to do is add the integration, and consider that the code you write in your Astro frontmatter will now also need to run in the browser/service-worker. This means that you will not be able to make use of Nodejs built-in dependencies, or other commonjs libraries. If you still want to write server-only code, you can use the networkOnly
configuration option.
serviceWorker
Install:
npm i -S astro-service-worker
Add the integration to your configuration:
astro.config.mjs
:
import { defineConfig } from 'astro/config';
import netlify from '@astrojs/netlify';
import serviceWorker from 'astro-service-worker';
export default defineConfig({
adapter: netlify(),
integrations: [
/** Creates a client-side service worker */
serviceWorker()
]
});
Note:
astro-service-worker
requires your app to run in SSR mode, instead of SSG mode.
worker
This package also includes an adapter to build your apps for worker-like environments, such as cloudflare.
astro.config.mjs
:
import { defineConfig } from 'astro/config';
import worker from 'astro-service-worker/adapter';
export default defineConfig({
/** Creates an integration for worker-like environments */
adapter: worker()
});
serviceWorker
import serviceWorker from 'astro-service-worker';
export default defineConfig({
integrations: [
serviceWorker({
/** Provide custom service worker logic */
swSrc: 'user-sw.js',
/**
* Excludes specific pages from the service worker bundle, and forces them to always go to the network
* This is useful for server-only specific code, for example database connections
*/
networkOnly: ['/networkonly-astro'],
/** Configure workbox options */
workbox: {},
/** Both default to true, useful if you want to provide a custom installation experience */
skipWaiting: false,
clientsClaim: false,
/** Configure esbuild options */
esbuild: {},
/** Enables minifcation for esbuild, defaults to true */
minify: false,
/** Override the default service worker registration and update script */
swScript: '',
}),
]
});
worker
import worker, { cloudflare } from 'astro-service-worker/adapter';
export default defineConfig({
/** Using a preset: */
adapter: worker(cloudflare),
/** Configuration: */
adapter: worker({
/** Provide a module specifier to a custom shim file */
shim: [
/** local module */
`${process.cwd()}/custom-shim.js`,
/** bare module specifier */
'@worker-tools/location-polyfill'
],
})
});
serviceWorker
: Overwriting Workbox optionsInternally, astro-service-worker
makes use of Workbox's injectManifest
functionality. You can overwrite the default configuration via the workbox
options:
export default defineConfig({
integrations: [
serviceWorker({
workbox: {
globPatterns: ['**/*.{js,css,html,png,jpeg}'],
}
}),
]
});
serviceWorker
: Adding custom Service Worker logicIt could be the case that you need to extend the Service Worker to add custom logic. To do this, you can use the swSrc
option.
export default defineConfig({
integrations: [
serviceWorker({
swSrc: 'my-custom-sw.js',
}),
]
});
my-project/my-custom-sw.js
:
self.addEventListener('activate', (e) => {
console.log('Custom logic!');
});
Note that if you want to add custom logic for the
'fetch'
handler, you should use a middleware instead.
Note that you can also use modules in your custom service worker logic:
import { registerRoute } from 'workbox-routing';
import { StaleWhileRevalidate } from 'workbox-strategies';
registerRoute(
/^https:\/\/fonts\.googleapis\.com/,
new StaleWhileRevalidate({
cacheName: 'google-fonts-stylesheets',
})
);
serviceWorker
: Combine with other integrationsYou can also combine this integration with other integrations.
import { defineConfig } from 'astro/config';
import netlify from '@astrojs/netlify';
import customElements from 'custom-elements-ssr/astro.js';
import serviceWorker from 'astro-service-worker';
export default defineConfig({
adapter: netlify(),
integrations: [
customElements(),
serviceWorker()
]
});
serviceWorker
: Network-onlyIt could be the case that you would like to make use of some server-only endpoints or pages, perhaps for creating database connections, or other things that depend on Nodejs built-in modules that are not available in the browser. If that is the case, you can specify which page you'd like to exclude from the service worker bundle:
export default defineConfig({
integrations: [
serviceWorker({
networkOnly: ['/networkonly-page', '/db-endpoint', 'etc']
}),
]
});
worker
: ShimIt could be the case that other integrations will need to shim certain API's in the service worker, however. In this case, you can provide a custom import. The imports you provide here will be put at the very top of the service worker module before bundling.
import { defineConfig } from 'astro/config';
import worker from 'astro-service-worker/adapter';
export default defineConfig({
adapter: worker({
shim: [
// local module
`${process.cwd()}/custom-shim.js`,
// bare module specifier
'@worker-tools/location-polyfill'
]
}),
});
worker
: PresetsThe adapter also comes with some environment specific presets, for example if you're deploying on cloudflare, you'll want to use the cloudflare
preset:
import worker, { cloudflare } from 'astro-service-worker/adapter';
export default defineConfig({
adapter: worker(cloudflare)
});
If no wrangler.toml
is present, one will be created for you. If a wrangler.toml
is already present, you're in charge of adding the required settings, here's an example:
name = "cloudflare-astro" # Name of your project
main = "dist/worker/index.js" # Path to your function
[site]
bucket = './dist' # Path to where your static assets are located
worker
|serviceWorker
: MiddlewareIt's also possible to add custom middleware to your service worker. To do so, you can add a function to self.MIDDLEWARE
. A middleware function gets passed the event
as well as Astro's SSR manifest
, e.g.: middleware(event, manifest)
.
If a middleware returns a response, other middleware will no longer run, and event.respondWith
will be called with the response from the middleware that returned.
By default, Astro is the first middleware in the MIDDLEWARE
array. You can add any additional middleware to run after Astro. If you need to run code before Astro, you should prepend your middleware function to the self.MIDDLEWARE
array, instead of push
ing it to the end of the array. If no middleware has returned a response, the request will be sent to the network instead or when ran on the server, return a 404.
serviceWorker
:For client-side service workers, you can configure this via the swSrc
property:
serviceWorker({swSrc: 'custom-handler.js'})
Where /custom-handler.js
:
self.MIDDLEWARE.push((event, manifest) => {
const url = new URL(event.request.url);
if (url.pathname.endsWith('.jpg')) {
return caches.match(event.request);
}
});
worker
:If you're creating a preset for a server-run worker-like environment, you can do this in a shim file, for example:
worker({shim: [`${process.cwd()}/my-shim.js`]})
Where /my-shim.js
:
import { getAssetFromKV } from '@cloudflare/kv-asset-handler';
self.MIDDLEWARE.push((event, manifest) => {
const url = new URL(event.request.url);
if(manifest.assets.has(url.pathname)) {
return getAssetFromKV(event);
}
});
In the future, once Astro release streaming responses, we can make use of that to improve performance even further:
/blog/[id].astro
:
---
import Header from '../src/components/Header.astro';
import Sidemenu from '../src/components/Sidemenu.astro';
import Footer from '../src/components/Footer.astro';
const { id } = Astro.params;
---
<html>
<Header/>
<Sidemenu/>
{fetch(`/blog/${id}.html`).then(render)}
<Footer/>
</html>
In a similar fashion to this Workbox example:
import { strategy } from 'workbox-streams';
import { registerRoute } from 'workbox-core';
const streamResponse = strategy([
() => caches.match(HEADER_CACHE_KEY, {cacheName: CACHE_NAME}),
() => `<nav>sidebar<ul><li><a href="/about">about</a></li></ul></nav>`,
({event}) => apiStrategy.handle({
event: event,
request: new Request('/content/foo.md'),
}),
() => caches.match(FOOTER_CACHE_KEY, {cacheName: CACHE_NAME}),
]);
registerRoute('/foo', streamResponse);
This is awesome because it means that you can now get the document starting to request your (SW cached) CSS, JS, and other "header" resources in parallel with SW startup and the network fetch. None of the steps serialise until content comes back.
Given that the Astro's render
function is a tagged template literal which returns an Astro
component, which is an async Iterable, it seems like this future may not be far off:
class AstroComponent {
constructor(htmlParts, expressions) {
this.htmlParts = htmlParts;
this.expressions = expressions;
}
get [Symbol.toStringTag]() {
return "AstroComponent";
}
*[Symbol.iterator]() {
const { htmlParts, expressions } = this;
for (let i = 0; i < htmlParts.length; i++) {
const html = htmlParts[i];
const expression = expressions[i];
yield markHTMLString(html);
yield _render(expression);
}
}
}
FAQs
> ⚙️ Offline-capable [Astro](https://astro.build) apps via SWSR (Service Worker Side Rendering)
The npm package astro-service-worker receives a total of 12 weekly downloads. As such, astro-service-worker popularity was classified as not popular.
We found that astro-service-worker demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Critics call the Node.js EOL CVE a misuse of the system, sparking debate over CVE standards and the growing noise in vulnerability databases.
Security News
cURL and Go security teams are publicly rejecting CVSS as flawed for assessing vulnerabilities and are calling for more accurate, context-aware approaches.
Security News
Bun 1.2 enhances its JavaScript runtime with 90% Node.js compatibility, built-in S3 and Postgres support, HTML Imports, and faster, cloud-first performance.