or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-controller.mdindex.mdplugins-cleanup.mdroute-strategy.mdsimple-setup.mdutilities.md

utilities.mddocs/

0

# Utility Functions

1

2

Helper functions for cache key management, request matching, and handler creation. These utilities provide access to precaching functionality without requiring a full controller instance.

3

4

## Capabilities

5

6

### Cache Key Management

7

8

Function for looking up cache keys for precached URLs.

9

10

```typescript { .api }

11

/**

12

* Takes a URL and returns the corresponding cache key used in the precache.

13

* Handles revision parameters automatically.

14

* @param url - The URL to look up the cache key for

15

* @returns The cache key or undefined if not found

16

*/

17

function getCacheKeyForURL(url: string): string | undefined;

18

```

19

20

**Usage Examples:**

21

22

```typescript

23

import { getCacheKeyForURL, precacheAndRoute } from "workbox-precaching";

24

25

// First precache some assets

26

precacheAndRoute([

27

{ url: "/index.html", revision: "abc123" },

28

"/logo.png", // No revision, uses URL as cache key

29

]);

30

31

// Later, look up cache keys

32

const indexCacheKey = getCacheKeyForURL("/index.html");

33

console.log(indexCacheKey); // "/index.html?__WB_REVISION__=abc123"

34

35

const logoCacheKey = getCacheKeyForURL("/logo.png");

36

console.log(logoCacheKey); // "/logo.png"

37

38

const notFoundKey = getCacheKeyForURL("/nonexistent.html");

39

console.log(notFoundKey); // undefined

40

```

41

42

### Request Matching

43

44

Function for looking up requests in the precache without needing a controller instance.

45

46

```typescript { .api }

47

/**

48

* Helper function that looks up a request in the precache.

49

* This is a wrapper around PrecacheController#matchPrecache using the default controller.

50

* @param request - The key (URL string or Request object) to look up

51

* @returns Promise resolving to cached response or undefined

52

*/

53

function matchPrecache(request: string | Request): Promise<Response | undefined>;

54

```

55

56

**Usage Examples:**

57

58

```typescript

59

import { matchPrecache, precacheAndRoute } from "workbox-precaching";

60

61

// Precache assets first

62

precacheAndRoute([

63

{ url: "/offline.html", revision: "v1.0" },

64

{ url: "/app-shell.html", revision: "v2.1" }

65

]);

66

67

// In service worker fetch event

68

self.addEventListener('fetch', async (event) => {

69

// Try to match against precache

70

const cachedResponse = await matchPrecache(event.request);

71

72

if (cachedResponse) {

73

console.log('Serving from precache:', event.request.url);

74

event.respondWith(cachedResponse);

75

return;

76

}

77

78

// Fallback to network

79

event.respondWith(fetch(event.request));

80

});

81

82

// Can also use with URL strings

83

const offlineResponse = await matchPrecache("/offline.html");

84

if (offlineResponse) {

85

// Use the cached offline page

86

return offlineResponse;

87

}

88

89

// Handle Request objects

90

const request = new Request("/app-shell.html");

91

const shellResponse = await matchPrecache(request);

92

```

93

94

### Handler Creation

95

96

Function for creating route handlers bound to specific precached URLs.

97

98

```typescript { .api }

99

/**

100

* Helper function that creates a route handler bound to a specific precached URL.

101

* Returns a handler function that serves the specified precached resource.

102

* @param url - The precached URL to bind the handler to

103

* @returns Route handler function that serves the precached resource

104

* @throws Will throw if the URL is not in the precache

105

*/

106

function createHandlerBoundToURL(url: string): RouteHandlerCallback;

107

```

108

109

**Usage Examples:**

110

111

```typescript

112

import {

113

createHandlerBoundToURL,

114

precacheAndRoute

115

} from "workbox-precaching";

116

import { registerRoute } from "workbox-routing";

117

118

// Precache assets first

119

precacheAndRoute([

120

{ url: "/", revision: "v1.0" },

121

{ url: "/offline.html", revision: "v1.1" },

122

{ url: "/app-shell.html", revision: "v2.0" }

123

]);

124

125

// Create handlers for specific URLs

126

const offlineHandler = createHandlerBoundToURL("/offline.html");

127

const shellHandler = createHandlerBoundToURL("/app-shell.html");

128

129

// Use handlers with routing

130

registerRoute(

131

// Serve offline page for failed navigation requests

132

({ request, event }) => {

133

return request.mode === 'navigate' && !navigator.onLine;

134

},

135

offlineHandler

136

);

137

138

registerRoute(

139

// Serve app shell for SPA routes

140

({ request, url }) => {

141

return request.mode === 'navigate' &&

142

url.pathname.startsWith('/app/');

143

},

144

shellHandler

145

);

146

147

// Direct usage in fetch event

148

self.addEventListener('fetch', (event) => {

149

if (event.request.mode === 'navigate' && event.request.url.includes('/dashboard')) {

150

// Always serve app shell for dashboard routes

151

const handler = createHandlerBoundToURL("/app-shell.html");

152

event.respondWith(handler({ request: event.request, event }));

153

}

154

});

155

```

156

157

## Advanced Usage Patterns

158

159

### Fallback Chain

160

161

```typescript

162

import {

163

matchPrecache,

164

createHandlerBoundToURL,

165

precacheAndRoute

166

} from "workbox-precaching";

167

168

// Precache fallback resources

169

precacheAndRoute([

170

{ url: "/offline.html", revision: "v1.0" },

171

{ url: "/fallback.css", revision: "v1.0" },

172

{ url: "/404.html", revision: "v1.0" }

173

]);

174

175

// Create fallback handlers

176

const offlineHandler = createHandlerBoundToURL("/offline.html");

177

const notFoundHandler = createHandlerBoundToURL("/404.html");

178

179

self.addEventListener('fetch', async (event) => {

180

// First, try precache

181

const cachedResponse = await matchPrecache(event.request);

182

if (cachedResponse) {

183

event.respondWith(cachedResponse);

184

return;

185

}

186

187

// Then try network

188

event.respondWith(

189

fetch(event.request)

190

.catch(async (error) => {

191

// Network failed, use appropriate fallback

192

if (event.request.mode === 'navigate') {

193

return offlineHandler({ request: event.request, event });

194

}

195

196

if (event.request.destination === 'document') {

197

return notFoundHandler({ request: event.request, event });

198

}

199

200

// For other resources, try to find a similar precached resource

201

return matchPrecache('/fallback.css') || new Response('Offline', {

202

status: 503,

203

statusText: 'Service Unavailable'

204

});

205

})

206

);

207

});

208

```

209

210

### Cache Key Validation

211

212

```typescript

213

import { getCacheKeyForURL, precacheAndRoute } from "workbox-precaching";

214

215

// Precache with revisions

216

precacheAndRoute([

217

{ url: "/critical.css", revision: "v1.5.2" },

218

{ url: "/app.js", revision: "v2.1.0" }

219

]);

220

221

// Utility to check if resources are properly cached

222

function validatePrecacheIntegrity(expectedAssets: Record<string, string>) {

223

const issues: string[] = [];

224

225

for (const [url, expectedRevision] of Object.entries(expectedAssets)) {

226

const cacheKey = getCacheKeyForURL(url);

227

228

if (!cacheKey) {

229

issues.push(`Missing from precache: ${url}`);

230

continue;

231

}

232

233

// Extract revision from cache key

234

const revisionMatch = cacheKey.match(/\?__WB_REVISION__=(.+)$/);

235

const actualRevision = revisionMatch ? revisionMatch[1] : 'none';

236

237

if (actualRevision !== expectedRevision) {

238

issues.push(`Version mismatch for ${url}: expected ${expectedRevision}, got ${actualRevision}`);

239

}

240

}

241

242

return issues;

243

}

244

245

// Check integrity

246

const issues = validatePrecacheIntegrity({

247

'/critical.css': 'v1.5.2',

248

'/app.js': 'v2.1.0'

249

});

250

251

if (issues.length > 0) {

252

console.warn('Precache integrity issues:', issues);

253

}

254

```

255

256

### Dynamic Handler Selection

257

258

```typescript

259

import {

260

createHandlerBoundToURL,

261

getCacheKeyForURL,

262

precacheAndRoute

263

} from "workbox-precaching";

264

import { registerRoute } from "workbox-routing";

265

266

// Precache multiple app shells

267

precacheAndRoute([

268

{ url: "/mobile-shell.html", revision: "v1.0" },

269

{ url: "/desktop-shell.html", revision: "v1.0" },

270

{ url: "/tablet-shell.html", revision: "v1.0" }

271

]);

272

273

// Dynamic handler based on user agent

274

const createResponsiveHandler = () => {

275

const mobileHandler = createHandlerBoundToURL("/mobile-shell.html");

276

const desktopHandler = createHandlerBoundToURL("/desktop-shell.html");

277

const tabletHandler = createHandlerBoundToURL("/tablet-shell.html");

278

279

return async ({ request, event }) => {

280

const userAgent = request.headers.get('user-agent') || '';

281

282

if (/Mobile/.test(userAgent)) {

283

return mobileHandler({ request, event });

284

} else if (/Tablet|iPad/.test(userAgent)) {

285

return tabletHandler({ request, event });

286

} else {

287

return desktopHandler({ request, event });

288

}

289

};

290

};

291

292

// Register responsive route

293

registerRoute(

294

({ request }) => request.mode === 'navigate',

295

createResponsiveHandler()

296

);

297

```

298

299

### Conditional Precache Serving

300

301

```typescript

302

import { matchPrecache, getCacheKeyForURL } from "workbox-precaching";

303

304

// Check if resource is precached before serving

305

async function servePrecachedIfAvailable(request: Request): Promise<Response> {

306

const url = new URL(request.url);

307

308

// Check if we have this resource precached

309

const cacheKey = getCacheKeyForURL(url.pathname);

310

if (!cacheKey) {

311

throw new Error(`Resource not precached: ${url.pathname}`);

312

}

313

314

// Try to serve from precache

315

const cachedResponse = await matchPrecache(request);

316

if (cachedResponse) {

317

// Add custom headers to indicate precached response

318

const response = new Response(cachedResponse.body, {

319

status: cachedResponse.status,

320

statusText: cachedResponse.statusText,

321

headers: {

322

...cachedResponse.headers,

323

'X-Served-From': 'precache',

324

'X-Cache-Key': cacheKey

325

}

326

});

327

return response;

328

}

329

330

throw new Error(`Failed to retrieve precached resource: ${url.pathname}`);

331

}

332

```