Skip to content

Commit

Permalink
fix(workbox): New configuration for specifying plugins when configuri…
Browse files Browse the repository at this point in the history
…ng a strategy (#337)

* Initial implementation of #336

* Update types

* Fix test
The strategy constructor option object can be optional as shown here: https://developers.google.com/web/tools/workbox/modules/workbox-strategies

* Fix broken generated sw.js

* Remove unused field

* Typo fixes

* Correct RuntimeCaching type

* Added tests

* Fix code

* Revert "Added tests" partially

This reverts commit d467e17

* Do not directly generate runtime code from nuxt.config

#337 (comment)

* Template formatting and remove unnecessary replace in toCode function

* simplify toCode function

* refactor: use runtime code instead of codegen

Co-authored-by: pooya parsa <[email protected]>
  • Loading branch information
Yihao-G and pi0 committed Oct 1, 2020
1 parent 3e910ae commit dacf7ec
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 19 deletions.
13 changes: 9 additions & 4 deletions docs/content/en/workbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,15 @@ workbox: {
urlPattern: 'https://my-cdn.com/posts/.*',
strategyOptions: {
cacheName: 'our-cache',
cacheExpiration: {
maxEntries: 10,
maxAgeSeconds: 300
}
plugins: [{
// Use Workbox plugins, available options are 'BackgroundSync', 'BroadcastUpdate', 'CacheableResponse', 'Expiration' and 'RangeRequests'
use: 'Expiration',
// Pass parameter values of the plugin's constructor as an array. Function in parameter is not supported.
config: [{
maxEntries: 10,
maxAgeSeconds: 300
}]
}]
}
}
]
Expand Down
21 changes: 20 additions & 1 deletion lib/workbox/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,29 @@ function getOptions (pwa) {
}

// Normalize runtimeCaching
const pluginModules = {
BackgroundSync: 'backgroundSync.BackgroundSyncPlugin',
BroadcastUpdate: 'broadcastUpdate.BroadcastUpdatePlugin',
CacheableResponse: 'cacheableResponse.CacheableResponsePlugin',
Expiration: 'expiration.ExpirationPlugin',
RangeRequests: 'rangeRequests.RangeRequestsPlugin'
}

options.runtimeCaching = options.runtimeCaching.map(entry => ({
...entry,
handler: startCase(entry.handler) || 'NetworkFirst',
method: entry.method || 'GET'
method: entry.method || 'GET',
strategyPlugins: (entry.strategyPlugins || []).map((plugin) => {
const use = pluginModules[plugin.use]
if (!use) {
console.warn(`Invalid strategy plugin ${plugin.use}`)
return
}
return {
use,
config: Array.isArray(plugin.config) ? plugin.config : [plugin.config]
}
}).filter(Boolean)
}))

// Workbox URL
Expand Down
21 changes: 19 additions & 2 deletions lib/workbox/templates/sw.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,25 @@ workbox.precaching.precacheAndRoute(<%= JSON.stringify(options.preCaching, null,
// --------------------------------------------------

// Register route handlers for runtimeCaching
<% options.runtimeCaching.forEach(r => { %>workbox.routing.registerRoute(new RegExp('<%= r.urlPattern %>'), new workbox.strategies.<%= r.handler %> (<%= JSON.stringify(r.strategyOptions || {}) %>), '<%= r.method %>')
<% }) %>

const runtimeCaching = <%= JSON.stringify(options.runtimeCaching, null, 2) %>

const getProp = (obj, prop) => prop.split('.').reduce((p, c) => p[c], obj)

for (const cache of runtimeCaching) {
const urlPattern = new RegExp(cache.urlPattern)
const method = cache.method || 'GET'

const plugins = (cache.strategyPlugins || [])
.map(p => new (getProp(workbox, p.use))(...p.config))

const strategyOptions = { ...cache.strategyOptions, plugins }
const strategy = new workbox.strategies[cache.handler](strategyOptions)

console.log('registerRoute', { urlPattern, strategyOptions, strategy, method })

workbox.routing.registerRoute(urlPattern, strategy, method)
}

<% if (options.offlinePage) { %>
// Register router handler for offlinePage
Expand Down
7 changes: 4 additions & 3 deletions test/__snapshots__/pwa.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,10 @@ workbox.precaching.precacheAndRoute([
// --------------------------------------------------
// Register route handlers for runtimeCaching
workbox.routing.registerRoute(new RegExp('https://google.com/.*'), new workbox.strategies.CacheFirst ({}), 'GET')
workbox.routing.registerRoute(new RegExp('/_nuxt/'), new workbox.strategies.CacheFirst ({}), 'GET')
workbox.routing.registerRoute(new RegExp('/'), new workbox.strategies.NetworkFirst ({}), 'GET')
workbox.routing.registerRoute(new RegExp('https://google.com/.*'), new workbox.strategies.CacheFirst(), 'GET')
workbox.routing.registerRoute(new RegExp('https://pwa.nuxtjs.org/.*'), new workbox.strategies.CacheFirst({plugins:[new workbox.expiration.ExpirationPlugin({maxEntries:10,maxAgeSeconds:300})],cacheName:'nuxt-pwa'}), 'GET')
workbox.routing.registerRoute(new RegExp('/_nuxt/'), new workbox.strategies.CacheFirst(), 'GET')
workbox.routing.registerRoute(new RegExp('/'), new workbox.strategies.NetworkFirst(), 'GET')
// -- Start of routingExtensions --
// Routing Extension
Expand Down
17 changes: 17 additions & 0 deletions test/fixture/nuxt.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,23 @@ module.exports = {
urlPattern: 'https://google.com/.*',
handler: 'cacheFirst',
method: 'GET'
},
{
urlPattern: 'https://pwa.nuxtjs.org/.*',
handler: 'CacheFirst',
method: 'GET',
strategyOptions: {
cacheName: 'nuxt-pwa'
},
strategyPlugins: [
{
use: 'Expiration',
config: {
maxEntries: 10,
maxAgeSeconds: 300
}
}
]
}
]
}
Expand Down
58 changes: 49 additions & 9 deletions types/workbox.d.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,56 @@
import { CacheExpirationConfig } from 'workbox-expiration'
import { HTTPMethod } from 'workbox-routing'
import { Plugin as BackgroundSyncPlugin } from 'workbox-background-sync'
import { Plugin as BroadcastUpdatePlugin } from 'workbox-broadcast-update'
import { Plugin as CacheableResponsePlugin } from 'workbox-cacheable-response'
import { Plugin as ExpirationPlugin } from 'workbox-expiration'
import { Plugin as RangeRequestsPlugin } from 'workbox-range-requests'
import {
StaleWhileRevalidateOptions,
CacheFirstOptions,
NetworkFirstOptions,
NetworkOnlyOptions,
CacheOnlyOptions
} from 'workbox-strategies'

export type CachingStrategy = 'CacheFirst' | 'CacheOnly' | 'NetworkFirst' | 'NetworkOnly' | 'StaleWhileRevalidate'

export type RuntimeCaching = {
urlPattern: string,
handler?: CachingStrategy,
methods?: HTTPMethod,
strategyOptions?: {
cacheName: string,
cacheExpiration: CacheExpirationConfig
}
export interface RuntimeCaching {
urlPattern: string
handler?: CachingStrategy
method?: HTTPMethod
strategyOptions?: StrategyOptions
strategyPlugins?: StrategyPlugin[]
}

export type StrategyOptions =
Omit<StaleWhileRevalidateOptions | CacheFirstOptions | NetworkFirstOptions | NetworkOnlyOptions | CacheOnlyOptions, 'plugins'>


export type StrategyPlugin = BackgroundSync | BroadcastUpdate | CacheableResponse | Expiration | RangeRequests

export interface BackgroundSync {
use: 'BackgroundSync',
config: ConstructorParameters<typeof BackgroundSyncPlugin>
}

export interface BroadcastUpdate {
use: 'BroadcastUpdate',
config: ConstructorParameters<typeof BroadcastUpdatePlugin>
}

export interface CacheableResponse {
use: 'CacheableResponse',
config: ConstructorParameters<typeof CacheableResponsePlugin>
}

export interface Expiration {
use: 'Expiration',
config: ConstructorParameters<typeof ExpirationPlugin>
}

export interface RangeRequests {
use: 'RangeRequests',
config: ConstructorParameters<typeof RangeRequestsPlugin>
}

export interface WorkboxOptions {
Expand Down

0 comments on commit dacf7ec

Please sign in to comment.