Skip to content

Commit f29b54c

Browse files
MagicalTuxclaude
andcommitted
Add Version Service Worker installation documentation
- Add comprehensive guide for implementing version tracking service worker - Update list.json with new documentation metadata - Update list.txt with new file entry - Update README.md with new guide references and description 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 7a8e0fb commit f29b54c

File tree

4 files changed

+318
-0
lines changed

4 files changed

+318
-0
lines changed

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ This repository contains comprehensive documentation for integrating with Karpel
1212
- [KLB Framework Flutter](klbfw-flutter.md) - Documentation for the Flutter package integration
1313
- [Stripe Express Checkout](express_checkout.md) - Guide for implementing Stripe Express Checkout (Apple Pay, Google Pay)
1414
- [Media Variations API](media_variation.md) - Documentation for transforming media files through API endpoints
15+
- [Version Service Worker](install-version-service-worker.md) - Guide for setting up a service worker for version tracking in Vue.js apps
1516

1617
## Overview
1718

@@ -112,6 +113,17 @@ The [Media Variations API](media_variation.md) documentation covers:
112113
- Best practices for responsive images and media optimization
113114
- Performance considerations and CDN delivery
114115

116+
## Version Service Worker
117+
118+
The [Version Service Worker](install-version-service-worker.md) guide covers:
119+
120+
- Setting up a service worker that adds version headers to asset requests
121+
- Implementing version tracking using Git commit hashes
122+
- Configuring webpack plugins for automatic version injection
123+
- Integrating version information into Vue.js applications
124+
- Enabling better cache management and version-specific routing
125+
- Browser compatibility and troubleshooting
126+
115127
## Getting Started
116128

117129
1. Review the [API Basics](apibasics.md) document to understand how to authenticate and make API requests
@@ -122,6 +134,7 @@ The [Media Variations API](media_variation.md) documentation covers:
122134
6. Use the [KLB Framework Flutter](klbfw-flutter.md) for mobile application development
123135
7. Implement [Stripe Express Checkout](express_checkout.md) for streamlined payment processing
124136
8. Utilize [Media Variations API](media_variation.md) for optimized media delivery
137+
9. Set up [Version Service Worker](install-version-service-worker.md) for asset version tracking
125138

126139
## Using with Claude
127140

install-version-service-worker.md

Lines changed: 298 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,298 @@
1+
# Version Service Worker Installation Guide
2+
3+
This guide explains how to set up a service worker that adds version headers to asset requests, enabling better cache management and version tracking in your Vue.js application.
4+
5+
## Overview
6+
7+
The version service worker system consists of:
8+
1. A static service worker that intercepts fetch requests
9+
2. A version injection plugin that gets the Git commit hash during build
10+
3. HTML modifications to register the service worker and pass version information
11+
4. Build configuration to enable the version injection
12+
13+
## Installation Steps
14+
15+
### Step 1: Create the Service Worker
16+
17+
Create a file `public/service-worker.js` with the following content:
18+
19+
```javascript
20+
// Static service worker that adds version headers to asset requests
21+
// This file remains the same across all deployments
22+
23+
let currentVersion = null;
24+
25+
// Listen for a message from the main thread to set the version
26+
self.addEventListener('message', event => {
27+
if (event.data && event.data.type === 'SET_VERSION') {
28+
currentVersion = event.data.version;
29+
} else if (event.data && event.data.type === 'RESET_VERSION') {
30+
currentVersion = null;
31+
}
32+
});
33+
34+
// Intercept fetch requests
35+
self.addEventListener('fetch', event => {
36+
// Skip modification if we don't have a version
37+
if (!currentVersion) {
38+
return;
39+
}
40+
41+
// Skip API requests (paths starting with /_)
42+
const url = new URL(event.request.url);
43+
if (url.pathname.startsWith('/_')) {
44+
return;
45+
}
46+
47+
// Skip document requests (HTML pages)
48+
if (event.request.destination === 'document') {
49+
return;
50+
}
51+
52+
// Only handle same-origin requests
53+
if (url.origin !== self.location.origin) {
54+
return;
55+
}
56+
57+
// Clone the request to modify it
58+
const modifiedRequest = new Request(event.request.url, {
59+
method: event.request.method,
60+
headers: new Headers(event.request.headers),
61+
mode: 'cors',
62+
credentials: event.request.credentials,
63+
redirect: event.request.redirect
64+
});
65+
66+
// Add our version header
67+
modifiedRequest.headers.set('X-Version-Hint', currentVersion);
68+
69+
// Use the modified request
70+
event.respondWith(
71+
fetch(modifiedRequest)
72+
.catch(error => {
73+
console.error('Service worker fetch error:', error);
74+
// Fall back to the original request if our modification fails
75+
return fetch(event.request);
76+
})
77+
);
78+
});
79+
80+
// Cache management
81+
self.addEventListener('install', event => {
82+
self.skipWaiting();
83+
});
84+
85+
self.addEventListener('activate', event => {
86+
event.waitUntil(self.clients.claim());
87+
});
88+
```
89+
90+
### Step 2: Create the Version Injector Plugin
91+
92+
Create a file `src/plugins/version-injector.js`:
93+
94+
```javascript
95+
// src/plugins/version-injector.js
96+
const childProcess = require('child_process');
97+
98+
/**
99+
* Webpack plugin to inject app version from Git commit hash
100+
*/
101+
class VersionInjectorPlugin {
102+
constructor(options = {}) {
103+
this.options = {
104+
// Default options
105+
placeholder: '%GIT_VERSION%',
106+
...options
107+
};
108+
}
109+
110+
apply(compiler) {
111+
compiler.hooks.compilation.tap('VersionInjectorPlugin', (compilation) => {
112+
// Get git commit hash
113+
const version = this.getGitCommitHash();
114+
115+
// Hook into HTML webpack plugin
116+
try {
117+
// For html-webpack-plugin v4 and above
118+
const HtmlWebpackPlugin = require('html-webpack-plugin');
119+
const hooks = HtmlWebpackPlugin.getHooks(compilation);
120+
121+
hooks.beforeEmit.tapAsync('VersionInjectorPlugin', (data, callback) => {
122+
data.html = data.html.replace(new RegExp(this.options.placeholder, 'g'), version);
123+
callback(null, data);
124+
});
125+
} catch (error) {
126+
console.warn('Could not find HtmlWebpackPlugin hooks - this is ok if you\'re not using HtmlWebpackPlugin');
127+
}
128+
});
129+
}
130+
131+
getGitCommitHash() {
132+
try {
133+
return childProcess.execSync('git rev-parse --short=7 HEAD')
134+
.toString()
135+
.trim();
136+
} catch (error) {
137+
console.warn('Unable to get git commit hash', error);
138+
return 'unknown';
139+
}
140+
}
141+
}
142+
143+
module.exports = VersionInjectorPlugin;
144+
```
145+
146+
### Step 3: Update Vue Configuration
147+
148+
Update your `vue.config.js` file:
149+
150+
```javascript
151+
const { defineConfig } = require('@vue/cli-service')
152+
const VersionInjectorPlugin = require('./src/plugins/version-injector')
153+
154+
module.exports = defineConfig({
155+
transpileDependencies: true,
156+
configureWebpack: {
157+
plugins: [
158+
new VersionInjectorPlugin()
159+
]
160+
}
161+
})
162+
```
163+
164+
### Step 4: Modify index.html
165+
166+
Update your `public/index.html` file to include the version meta tag and service worker registration. Add the following within the `<head>` section:
167+
168+
```html
169+
<meta name="app-version" content="%GIT_VERSION%">
170+
```
171+
172+
And add this script before the closing `</head>` tag:
173+
174+
```html
175+
<script>
176+
// Register service worker with version information
177+
if ('serviceWorker' in navigator) {
178+
// Get version from meta tag
179+
const versionMeta = document.querySelector('meta[name="app-version"]');
180+
const version = versionMeta ? versionMeta.getAttribute('content') : '%GIT_VERSION%';
181+
console.log('Page loaded with version:', version);
182+
183+
// Check for existing service worker controller first
184+
if (navigator.serviceWorker.controller) {
185+
console.log('Found existing service worker controller');
186+
// Send version to existing controller
187+
navigator.serviceWorker.controller.postMessage({
188+
type: 'SET_VERSION',
189+
version: version
190+
});
191+
}
192+
193+
// Register the service worker
194+
navigator.serviceWorker.register('/service-worker.js')
195+
.then(registration => {
196+
console.log('Service worker registered');
197+
198+
// If there's already an active service worker
199+
if (registration.active) {
200+
console.log('Active service worker found, sending version');
201+
registration.active.postMessage({
202+
type: 'SET_VERSION',
203+
version: version
204+
});
205+
}
206+
207+
// Handle waiting service worker
208+
if (registration.waiting) {
209+
console.log('Waiting service worker found, sending version');
210+
registration.waiting.postMessage({
211+
type: 'SET_VERSION',
212+
version: version
213+
});
214+
}
215+
216+
// Handle future installations
217+
registration.onupdatefound = () => {
218+
const installing = registration.installing;
219+
console.log('New service worker installing');
220+
221+
if (installing) {
222+
installing.onstatechange = () => {
223+
console.log('Service worker state changed:', installing.state);
224+
225+
if (installing.state === 'activated') {
226+
console.log('Service worker activated, sending version');
227+
installing.postMessage({
228+
type: 'SET_VERSION',
229+
version: version
230+
});
231+
}
232+
};
233+
}
234+
};
235+
})
236+
.catch(error => {
237+
console.error('Service worker registration failed:', error);
238+
});
239+
240+
// Listen for controlled change events
241+
navigator.serviceWorker.addEventListener('controllerchange', () => {
242+
console.log('Service worker controller changed');
243+
if (navigator.serviceWorker.controller) {
244+
console.log('Sending version to new controller');
245+
navigator.serviceWorker.controller.postMessage({
246+
type: 'SET_VERSION',
247+
version: version
248+
});
249+
}
250+
});
251+
}
252+
</script>
253+
```
254+
255+
## Building and Testing
256+
257+
1. Ensure you have a Git repository initialized in your project
258+
2. Run the build command:
259+
```bash
260+
yarn build
261+
```
262+
3. The build process will:
263+
- Extract the current Git commit hash (7 characters)
264+
- Replace all instances of `%GIT_VERSION%` in the HTML with the actual commit hash
265+
- Generate the production build in the `dist` directory
266+
267+
## How It Works
268+
269+
1. **During Build**: The `VersionInjectorPlugin` gets the Git commit hash and replaces `%GIT_VERSION%` placeholders in the HTML
270+
2. **On Page Load**: The browser reads the version from the meta tag and registers the service worker
271+
3. **Service Worker Communication**: The page sends the version to the service worker using `postMessage`
272+
4. **Request Interception**: The service worker intercepts outgoing requests and adds an `X-Version-Hint` header with the current version
273+
5. **Server-Side Usage**: Your server can use this header for cache management, logging, or version-specific routing
274+
275+
## Features
276+
277+
- **Static Service Worker**: The service worker file itself never changes, making it cache-friendly
278+
- **Version Headers**: All asset requests include the `X-Version-Hint` header
279+
- **API Request Exclusion**: Requests to paths starting with `/_` are not modified
280+
- **Document Request Exclusion**: HTML page requests are not modified
281+
- **Error Handling**: Falls back to original requests if modification fails
282+
- **Cross-Origin Safety**: Only modifies same-origin requests
283+
284+
## Troubleshooting
285+
286+
- If the version shows as "unknown", ensure your project is a Git repository with at least one commit
287+
- Check the browser console for service worker registration messages
288+
- Use the Network tab in DevTools to verify the `X-Version-Hint` header is being added to asset requests
289+
- The service worker will not modify requests until it receives a version via `postMessage`
290+
291+
## Browser Compatibility
292+
293+
This implementation requires browser support for:
294+
- Service Workers
295+
- `postMessage` API
296+
- Modern JavaScript features (const, arrow functions, template literals)
297+
298+
Most modern browsers (Chrome, Firefox, Safari, Edge) support these features.

list.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@
4747
"description": "Documentation for requesting and using transformed versions of media files (images and audio) through API endpoints with various filters and formats",
4848
"mimeType": "text/plain"
4949
},
50+
{
51+
"uri": "install-version-service-worker.md",
52+
"name": "Version Service Worker Installation Guide",
53+
"description": "Guide for setting up a service worker that adds version headers to asset requests for better cache management and version tracking in Vue.js applications",
54+
"mimeType": "text/plain"
55+
},
5056
{
5157
"uri": "README.md",
5258
"name": "Karpeles Lab Inc Integration Documentation",

list.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
apibasics.md
22
express_checkout.md
3+
install-version-service-worker.md
34
klbfw-describe.md
45
klbfw-flutter.md
56
klbfw-i18next.md

0 commit comments

Comments
 (0)