Skip to content

Commit

Permalink
refactor: context
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed Jul 6, 2022
1 parent 3e33253 commit fa30b52
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 99 deletions.
26 changes: 26 additions & 0 deletions src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { generateWebManifestFile } from './assets'
import { FILE_SW_REGISTER } from './constants'
import { generateSimpleSWRegister } from './html'
import type { PWAPluginContext } from './context'
import type { ExtendManifestEntriesHook, VitePluginPWAAPI } from './types'

export async function _generateSW({ options, viteConfig }: PWAPluginContext) {
if (options.disable)
Expand Down Expand Up @@ -46,3 +47,28 @@ export function _generateBundle({ options, viteConfig, useImportRegister }: PWAP
}
return bundle
}

export function createAPI(ctx: PWAPluginContext): VitePluginPWAAPI {
return {
get disabled() {
return ctx?.options?.disable
},
generateBundle(bundle) {
return _generateBundle(ctx, bundle!)
},
async generateSW() {
return await _generateSW(ctx)
},
extendManifestEntries(fn: ExtendManifestEntriesHook) {
const { options } = ctx
if (options.disable)
return

const configField = options.strategies === 'generateSW' ? 'workbox' : 'injectManifest'
const result = fn(options[configField].additionalManifestEntries || [])

if (result != null)
options[configField].additionalManifestEntries = result
},
}
}
13 changes: 6 additions & 7 deletions src/context.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import type { ResolvedConfig } from 'vite'
import type { ResolvedVitePWAOptions, VitePWAOptions } from './types'
import { resolveOptions } from './options'

export interface PWAPluginContext {
viteConfig: ResolvedConfig
userOptions: Partial<VitePWAOptions>
options: ResolvedVitePWAOptions
useImportRegister: boolean
}

export type PWAPluginContextResolver = () => PWAPluginContext

export async function resolvePWAPluginContext(viteConfig: ResolvedConfig, userOptions: Partial<VitePWAOptions>) {
return <PWAPluginContext>{
viteConfig,
options: await resolveOptions(userOptions, viteConfig),
export function createContext(userOptions: Partial<VitePWAOptions>): PWAPluginContext {
return {
userOptions,
options: undefined!,
viteConfig: undefined!,
useImportRegister: false,
}
}
11 changes: 6 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import type { Plugin } from 'vite'
import { createContext } from './context'
import type { VitePWAOptions } from './types'
import { CreatePlugin } from './plugins'
import { BuildPlugin } from './plugins/build'
import { DevPlugin } from './plugins/dev'
import { MainPlugin } from './plugins/main'

export function VitePWA(userOptions: Partial<VitePWAOptions> = {}): Plugin[] {
const [contextResolver, VirtualPlugin] = CreatePlugin(userOptions)
const ctx = createContext(userOptions)
return [
VirtualPlugin,
BuildPlugin(contextResolver),
DevPlugin(contextResolver),
MainPlugin(ctx),
BuildPlugin(ctx),
DevPlugin(ctx),
]
}

Expand Down
35 changes: 5 additions & 30 deletions src/plugins/build.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import type { Plugin } from 'vite'
import { injectServiceWorker } from '../html'
import type { ExtendManifestEntriesHook, VitePluginPWAAPI } from '../types'
import type { PWAPluginContextResolver } from '../context'
import { _generateBundle, _generateSW } from '../api'
import type { PWAPluginContext } from '../context'

export function BuildPlugin(contextResolver: PWAPluginContextResolver) {
export function BuildPlugin(ctx: PWAPluginContext) {
return <Plugin>{
name: 'vite-plugin-pwa',
name: 'vite-plugin-pwa:build',
enforce: 'post',
apply: 'build',
transformIndexHtml: {
enforce: 'post',
transform(html) {
const { options, useImportRegister } = contextResolver()
const { options, useImportRegister } = ctx
if (options.disable)
return html

Expand All @@ -24,39 +23,15 @@ export function BuildPlugin(contextResolver: PWAPluginContextResolver) {
},
},
generateBundle(_, bundle) {
return _generateBundle(contextResolver(), bundle)
return _generateBundle(ctx, bundle)
},
async closeBundle() {
const ctx = contextResolver()
if (!ctx.viteConfig.build.ssr && !ctx.options.disable)
await _generateSW(ctx)
},
async buildEnd(error) {
if (error)
throw error
},
api: <VitePluginPWAAPI>{
get disabled() {
const ctx = contextResolver()
return ctx?.options?.disable
},
generateBundle(bundle) {
return _generateBundle(contextResolver(), bundle!)
},
async generateSW() {
return await _generateSW(contextResolver())
},
extendManifestEntries(fn: ExtendManifestEntriesHook) {
const { options } = contextResolver()
if (options.disable)
return

const configField = options.strategies === 'generateSW' ? 'workbox' : 'injectManifest'
const result = fn(options[configField].additionalManifestEntries || [])

if (result != null)
options[configField].additionalManifestEntries = result
},
},
}
}
12 changes: 6 additions & 6 deletions src/plugins/dev.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
import { basename, resolve } from 'path'
import { existsSync, promises as fs, mkdirSync } from 'fs'
import type { Plugin, ResolvedConfig } from 'vite'
import type { PWAPluginContextResolver } from '../context'
import { generateSimpleSWRegister, injectServiceWorker } from '../html'
import { generateWebManifestFile } from '../assets'
import { DEV_SW_NAME, FILE_SW_REGISTER } from '../constants'
import type { ResolvedVitePWAOptions } from '../types'
import { generateServiceWorker } from '../modules'
import { normalizePath } from '../utils'
import type { PWAPluginContext } from '../context'

export const swDevOptions = {
swUrl: DEV_SW_NAME,
swDevGenerated: false,
workboxPaths: new Map<string, string>(),
}

export function DevPlugin(contextResolver: PWAPluginContextResolver) {
export function DevPlugin(ctx: PWAPluginContext): Plugin {
return <Plugin>{
name: 'vite-plugin-pwa:dev-sw',
apply: 'serve',
transformIndexHtml: {
enforce: 'post',
async transform(html) {
const { options, useImportRegister, viteConfig } = contextResolver()
const { options, useImportRegister, viteConfig } = ctx
if (options.disable || !options.manifest || !options.devOptions.enabled)
return html

Expand All @@ -36,7 +36,7 @@ export function DevPlugin(contextResolver: PWAPluginContextResolver) {
},
},
configureServer(server) {
const { options } = contextResolver()
const { options } = ctx
if (!options.disable && options.manifest && options.devOptions.enabled) {
const name = options.devOptions.webManifestUrl ?? `${options.base}${options.manifestFilename}`
server.middlewares.use((req, res, next) => {
Expand All @@ -53,7 +53,7 @@ export function DevPlugin(contextResolver: PWAPluginContextResolver) {
}
},
resolveId(id) {
const { options } = contextResolver()
const { options } = ctx
if (!options.disable && options.devOptions.enabled && options.strategies === 'injectManifest') {
const name = id.startsWith('/') ? id.slice(1) : id
// the sw must be registered with .js extension on browser, here we detect that request:
Expand All @@ -69,7 +69,7 @@ export function DevPlugin(contextResolver: PWAPluginContextResolver) {
return undefined
},
async load(id) {
const { options, viteConfig } = contextResolver()
const { options, viteConfig } = ctx
if (!options.disable && options.devOptions.enabled) {
if (options.strategies === 'injectManifest') {
// we need to inject self.__WB_MANIFEST with an empty array: there is no pwa on dev
Expand Down
50 changes: 0 additions & 50 deletions src/plugins/index.ts

This file was deleted.

46 changes: 46 additions & 0 deletions src/plugins/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import type { Plugin } from 'vite'
import { VIRTUAL_MODULES, VIRTUAL_MODULES_MAP, VIRTUAL_MODULES_RESOLVE_PREFIX } from '../constants'
import { generateRegisterSW } from '../modules'
import { resolveOptions } from '../options'
import { createAPI } from '../api'
import type { PWAPluginContext } from '../context'
import { swDevOptions } from './dev'

export function MainPlugin(ctx: PWAPluginContext): Plugin {
return {
name: 'vite-plugin-pwa',
async configResolved(config) {
ctx.useImportRegister = false
ctx.viteConfig = config
ctx.options = await resolveOptions(ctx.userOptions, config)
},
resolveId(id) {
return VIRTUAL_MODULES.includes(id) ? VIRTUAL_MODULES_RESOLVE_PREFIX + id : undefined
},
load(id) {
if (id.startsWith(VIRTUAL_MODULES_RESOLVE_PREFIX))
id = id.slice(VIRTUAL_MODULES_RESOLVE_PREFIX.length)
else
return

if (VIRTUAL_MODULES.includes(id)) {
ctx.useImportRegister = true
if (ctx.viteConfig.command === 'serve' && ctx.options.devOptions.enabled) {
return generateRegisterSW(
{ ...ctx.options, filename: swDevOptions.swUrl },
'build',
VIRTUAL_MODULES_MAP[id],
)
}
else {
return generateRegisterSW(
ctx.options,
!ctx.options.disable && ctx.viteConfig.command === 'build' ? 'build' : 'dev',
VIRTUAL_MODULES_MAP[id],
)
}
}
},
api: createAPI(ctx),
}
}
2 changes: 1 addition & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ export interface VitePluginPWAAPI {
/*
* Explicitly generate the manifests.
*/
generateBundle(bundle?: OutputBundle): OutputBundle
generateBundle(bundle?: OutputBundle): OutputBundle | undefined
/*
* Explicitly generate the PWA services worker.
*/
Expand Down

0 comments on commit fa30b52

Please sign in to comment.