From fa30b52bb3fd898286255c8bf6a4d6ff1d010577 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Wed, 6 Jul 2022 17:42:07 +0800 Subject: [PATCH] refactor: context --- src/api.ts | 26 +++++++++++++++++++++++ src/context.ts | 13 ++++++------ src/index.ts | 11 +++++----- src/plugins/build.ts | 35 +++++-------------------------- src/plugins/dev.ts | 12 +++++------ src/plugins/index.ts | 50 -------------------------------------------- src/plugins/main.ts | 46 ++++++++++++++++++++++++++++++++++++++++ src/types.ts | 2 +- 8 files changed, 96 insertions(+), 99 deletions(-) delete mode 100644 src/plugins/index.ts create mode 100644 src/plugins/main.ts diff --git a/src/api.ts b/src/api.ts index 467900aa..5baa8bcf 100644 --- a/src/api.ts +++ b/src/api.ts @@ -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) @@ -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 + }, + } +} diff --git a/src/context.ts b/src/context.ts index 304fd0b5..dd60925f 100644 --- a/src/context.ts +++ b/src/context.ts @@ -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 options: ResolvedVitePWAOptions useImportRegister: boolean } -export type PWAPluginContextResolver = () => PWAPluginContext - -export async function resolvePWAPluginContext(viteConfig: ResolvedConfig, userOptions: Partial) { - return { - viteConfig, - options: await resolveOptions(userOptions, viteConfig), +export function createContext(userOptions: Partial): PWAPluginContext { + return { + userOptions, + options: undefined!, + viteConfig: undefined!, useImportRegister: false, } } diff --git a/src/index.ts b/src/index.ts index 33a77f35..1b590dd3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -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 = {}): Plugin[] { - const [contextResolver, VirtualPlugin] = CreatePlugin(userOptions) + const ctx = createContext(userOptions) return [ - VirtualPlugin, - BuildPlugin(contextResolver), - DevPlugin(contextResolver), + MainPlugin(ctx), + BuildPlugin(ctx), + DevPlugin(ctx), ] } diff --git a/src/plugins/build.ts b/src/plugins/build.ts index 81c66b61..7e43be0e 100644 --- a/src/plugins/build.ts +++ b/src/plugins/build.ts @@ -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 { - 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 @@ -24,10 +23,9 @@ 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) }, @@ -35,28 +33,5 @@ export function BuildPlugin(contextResolver: PWAPluginContextResolver) { if (error) throw error }, - api: { - 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 - }, - }, } } diff --git a/src/plugins/dev.ts b/src/plugins/dev.ts index 0bd0c9af..e24d9ff3 100644 --- a/src/plugins/dev.ts +++ b/src/plugins/dev.ts @@ -1,13 +1,13 @@ 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, @@ -15,14 +15,14 @@ export const swDevOptions = { workboxPaths: new Map(), } -export function DevPlugin(contextResolver: PWAPluginContextResolver) { +export function DevPlugin(ctx: PWAPluginContext): Plugin { return { 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 @@ -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) => { @@ -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: @@ -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 diff --git a/src/plugins/index.ts b/src/plugins/index.ts deleted file mode 100644 index 45e3256b..00000000 --- a/src/plugins/index.ts +++ /dev/null @@ -1,50 +0,0 @@ -import type { Plugin } from 'vite' -import { VIRTUAL_MODULES, VIRTUAL_MODULES_MAP, VIRTUAL_MODULES_RESOLVE_PREFIX } from '../constants' -import { generateRegisterSW } from '../modules' -import type { PWAPluginContext, PWAPluginContextResolver } from '../context' -import { resolvePWAPluginContext } from '../context' -import type { VitePWAOptions } from '../types' -import { swDevOptions } from './dev' - -export function CreatePlugin(userOptions: Partial): [PWAPluginContextResolver, Plugin] { - let context: PWAPluginContext - const contextResolver: PWAPluginContextResolver = () => { - return context - } - return [ - contextResolver, - { - name: 'vite-plugin-pwa:virtual', - async configResolved(config) { - context = await resolvePWAPluginContext(config, userOptions) - }, - 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)) { - context.useImportRegister = true - if (context.viteConfig.command === 'serve' && context.options.devOptions.enabled) { - return generateRegisterSW( - { ...context.options, filename: swDevOptions.swUrl }, - 'build', - VIRTUAL_MODULES_MAP[id], - ) - } - else { - return generateRegisterSW( - context.options, - !context.options.disable && context.viteConfig.command === 'build' ? 'build' : 'dev', - VIRTUAL_MODULES_MAP[id], - ) - } - } - }, - }, - ] -} diff --git a/src/plugins/main.ts b/src/plugins/main.ts new file mode 100644 index 00000000..0acb5ced --- /dev/null +++ b/src/plugins/main.ts @@ -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), + } +} diff --git a/src/types.ts b/src/types.ts index 00c26da1..8a97394c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -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. */