/
index.js
104 lines (91 loc) · 3.12 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import path from 'path';
import fs from 'fs';
import { injectManifest } from 'workbox-build';
import { build, transform } from "esbuild";
import { vitePluginSW } from './service-worker-integration/vite-plugin-sw.js';
import { getAdapter } from './service-worker-integration/adapter.js';
import {
SW_SCRIPT,
SW_FILE_NAME,
PROCESS_SHIM,
REPLACE_EXP
} from './service-worker-integration/constants.js';
/**
* Astro Integration
*/
export default function serviceWorker(options) {
let cfg, swInDir, manifest, renderers = [];
return {
name: 'astro-swsr-integration',
hooks: {
'astro:config:setup': async ({ config, command, injectScript }) => {
renderers = config._ctx.renderers;
cfg = config;
/** Add SW registration script */
if(command === 'build') {
injectScript('head-inline', (await transform(options?.swScript ?? SW_SCRIPT, {minify: true})).code);
}
},
'astro:build:setup': async ({ vite, pages }) => {
/**
* This plugin should be the last, even after vite-plugin-ssr,
* otherwise the main Integration (netlify, firebase, etc) function will be output as `entry2.mjs`,
* and then the created redirects might not work correctly (e.g. they'll point to `entry.mjs`, which is now the SW)
*/
vite.plugins.push(
vitePluginSW({
pages,
renderers,
networkOnly: options?.networkOnly,
swSrc: options?.swSrc,
adapter: getAdapter({
clientsClaim: options?.clientsClaim ?? true,
skipWaiting: options?.skipWaiting ?? true,
browser: options?.browser ?? true,
shim: options?.shim ?? [],
}),
})
);
swInDir = vite.build.outDir;
},
'astro:build:ssr': (ssr) => {
manifest = ssr.manifest;
},
"astro:build:done": async () => {
const globDirectory = cfg.outDir.pathname;
const swInPath = path.join(swInDir, SW_FILE_NAME);
const swInFile = fs.readFileSync(swInPath, 'utf-8');
const swOutPath = cfg.outDir.pathname;
const swOutFile = path.join(swOutPath, SW_FILE_NAME);
/** Filter out network only routes */
manifest.routes = manifest.routes.filter(({routeData}) => !options?.networkOnly?.includes(routeData.pathname));
/** Add SSR Manifest */
fs.writeFileSync(
swInPath,
swInFile.replace(
REPLACE_EXP,
() => JSON.stringify(manifest)
)
);
/** Bundle and build for the browser */
await build({
entryPoints: [swInPath],
outfile: swOutFile,
platform: 'browser',
bundle: true,
inject: [PROCESS_SHIM],
minify: options?.minify ?? true,
...(options?.esbuild ?? {})
});
fs.unlinkSync(swInPath);
/** Add precacheManifest via Workbox */
await injectManifest({
globDirectory,
swSrc: swOutFile,
swDest: swOutFile,
...(options?.workbox ?? {})
});
}
}
}
}