Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | 1x 6x 6x 5x 1x 1x 1x 1x 7x 7x 6x 6x 6x 6x 6x 1x 5x 5x 1x 4x 4x 4x 4x | /**
* vite-plugin-sw-build-id
*
* Substitutes the `__BUILD_ID__` placeholder in `public/sw.js` with a
* short, per-build unique identifier when emitting `dist/sw.js`. The
* substituted file body therefore differs on every push, which is the
* trigger the browser uses to detect a service-worker update — without
* this rotation, every PR-merge content deploy would ship the same
* `sw.js` and the SW would never update, leaving the in-cache HTML
* pinned to whatever build the user first installed.
*
* ## Why not use `package.json` `version`?
*
* `version` only changes on releases (occasional, manual, used to
* publish updated API docs / test results / release notes). Content
* (news articles, sitemaps, RSS, regenerated indexes, dashboards)
* ships on every PR merge. A version-pinned cache name would stay
* constant across dozens of content pushes between releases, and the
* `activate`-purge eviction step in `public/sw.js` would never run.
*
* ## BUILD_ID resolution order
*
* 1. `process.env.GITHUB_SHA` (short form) — present on every
* GitHub Actions run; for `deploy-s3.yml` this is the merge-commit
* SHA of the PR that triggered the deploy. **Primary signal.**
* 2. `git rev-parse --short=12 HEAD` — local builds, `release.yml`
* runs without `GITHUB_SHA`, and any environment where step 1
* is unavailable.
* 3. `Date.now().toString(36)` — final fallback for sandboxed CI
* contexts without a git repo. Guarantees uniqueness; less
* debuggable but never collides.
*
* ## Where else to use `BUILD_ID`
*
* Only `dist/sw.js`. The chrome / footer / JSON-LD `softwareVersion`
* markers in HTML pages keep using `process.env.npm_package_version`
* because those values are user-facing release identifiers, not
* cache-busting tokens.
*
* @author Hack23 AB
* @license Apache-2.0
*/
import { execSync } from 'node:child_process';
import fs from 'node:fs';
import path from 'node:path';
/**
* Resolve the BUILD_ID for this build run.
*
* @returns {string}
*/
function resolveBuildId() {
const shaEnv = process.env.GITHUB_SHA;
if (shaEnv && /^[0-9a-f]+$/i.test(shaEnv)) {
return shaEnv.slice(0, 12);
}
try {
const out = execSync('git rev-parse --short=12 HEAD', {
stdio: ['ignore', 'pipe', 'ignore'],
encoding: 'utf8',
}).trim();
Eif (/^[0-9a-f]+$/i.test(out) && out.length >= 7) {
return out;
}
} catch {
/* git not available, fall through */
}
return `t${Date.now().toString(36)}`;
}
/**
* Vite plugin factory.
*
* @param {{ projectRoot: string, outDir?: string }} options
* @returns {import('vite').Plugin}
*/
export default function swBuildIdPlugin(options) {
const { projectRoot, outDir = 'dist' } = options;
return {
name: 'sw-build-id',
apply: 'build',
enforce: 'post',
closeBundle: {
order: 'post',
sequential: true,
handler() {
const buildId = resolveBuildId();
const distDir = path.isAbsolute(outDir)
? outDir
: path.join(projectRoot, outDir);
const srcPath = path.join(projectRoot, 'public', 'sw.js');
const destPath = path.join(distDir, 'sw.js');
if (!fs.existsSync(srcPath)) {
throw new Error(
`[sw-build-id] Source service worker not found at ${srcPath}`,
);
}
const src = fs.readFileSync(srcPath, 'utf8');
if (!src.includes('__BUILD_ID__')) {
throw new Error(
`[sw-build-id] public/sw.js is missing the __BUILD_ID__ ` +
`placeholder. Expected literal "__BUILD_ID__" so the build ` +
`can substitute the per-build cache identifier.`,
);
}
const out = src.split('__BUILD_ID__').join(buildId);
fs.mkdirSync(path.dirname(destPath), { recursive: true });
fs.writeFileSync(destPath, out, 'utf8');
console.log(
`[sw-build-id] emitted dist/sw.js with BUILD_ID=${buildId}`,
);
},
},
};
}
|