workbox
workbox copied to clipboard
How to pass variables to RouteMatchCallback?
Library Affected: workbox-build
Browser & Platform: all browsers
Issue or Feature Request Description:
I'm using the vite-plugin-pwa
package with the generateSW
mode, which actually uses the generateSW method of workbox-build under the hood with given options (see example)
I'd like to use the Caching resources during runtime Workbox recipe to add a runtimeCaching to CDN assets. In future I'd like to extend the complexity of callback logic, so replacing it by RegExp or string is not an option.
The path to CDN assets is stored in environment variable
My setup is:
// vite.config.js
import { defineConfig, loadEnv } from 'vite'
import { VitePWA } from 'vite-plugin-pwa'
import type { RouteMatchCallback } from 'workbox-core'
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, '.')
const assetsRx = new RegExp(`^${env.VITE_ASSETS_CDN}/`)
const routeMatchCallback: RouteMatchCallback = ({ request }) =>
assetsRx.test(request.url) &&
request.destination === 'image'
return ({
plugins: [
workbox: {
runtimeCaching: [{
urlPattern: routeMatchCallback,
handler: 'CacheFirst',
//..
}],
},
],
})
})
The problem is that generated service worker contains reference to assetsRx
variable, which is undefined.
Uncaught ReferenceError: assetsRx is not defined
at Route.match (sw.js:103:78)
at Router.findMatchingRoute (Router.js:265:39)
at Router.handleRequest (Router.js:142:40)
at Router.js:56:42
In the workbox-build source code I found that the urlPattern is being transformed to string and injected in template so doesn't have access to upper scope (assetsRx variable is not defined in the template)
https://github.com/GoogleChrome/workbox/blob/5e69c3f6a74ea0e6b1a0d3261a6cde11d8075859/packages/workbox-build/src/lib/runtime-caching-converter.ts#L207-L209
=> "({ request }) => assetsRx.test(request.url) && request.destination === 'image'"
So my question is: How to pass variables to routeMatchCallback? I'd say it's a quite common scenario to match routes against values coming from outer scope.
A hacky way around this is to overwrite routeMatchCallback.toString method like this:
// Trick workbox
routeMatchCallback.toString = (asString => () => asString)(routeMatchCallback
.toString()
.replace(/assetsRx/, `/${assetsRx.source}/`)
)
but this doesn't feel right.
Using Function.prototype.bind is not an option either as function's body becomes a [native code]
string
I'm facing the same issue, I think it does not make sense to convert a function to a string, it should be evaluated as it is to be able to use variables on it as a programmer would expect.
so, how to access env value in generated sw scope ?
Hi there,
Workbox is moving to a new engineering team within Google. As part of this move, we're declaring a partial bug bankruptcy to allow the new team to start fresh. We realize this isn't optimal, but realistically, this is the only way we see it working. For transparency, here're the criteria we applied:
- For PRs, we closed everything that doesn't target the current
v7
branch. - For Issues, we closed everything that was created before 2024.
Thanks, and we hope for your understanding! The Workbox team