Skip to content

Commit

Permalink
feat!: build custom service worker using vite (#506)
Browse files Browse the repository at this point in the history
* feat: build custom service worker using vite

* fix: lock file

* chore: change plugins type + add breaking changes version

* chore: change plugins with user config (excluding define) and use merge config

* chore: update `injectManifestViteOptions` jsdocs

* chore: fix wording `injectManifestViteOptions` jsdocs

* chore: change `CustomInjectManifestOptions` jsdocs

* chore: include rollup options only
  • Loading branch information
userquin committed May 19, 2023
1 parent e8ee8c5 commit 7cacdd3
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 93 deletions.
2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,6 @@
"debug": "^4.3.4",
"fast-glob": "^3.2.12",
"pretty-bytes": "^6.0.0",
"rollup": "^3.7.2",
"@rollup/plugin-replace": "^5.0.1",
"workbox-build": "^6.5.4",
"workbox-window": "^6.5.4"
},
Expand Down
52 changes: 13 additions & 39 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

78 changes: 29 additions & 49 deletions src/modules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import type { BuildResult } from 'workbox-build'
import type { ResolvedConfig } from 'vite'
import type { ResolvedVitePWAOptions } from './types'
import { logWorkboxResult } from './log'
import { defaultInjectManifestVitePlugins } from './constants'

const _dirname = typeof __dirname !== 'undefined'
? __dirname
Expand All @@ -25,19 +24,6 @@ async function loadWorkboxBuild(): Promise<typeof import('workbox-build')> {
}
}

async function loadRollupReplacePlugin() {
// Uses require to lazy load.

try {
const { createRequire } = await import('module').then(m => m.default || m)
const nodeRequire = createRequire(_dirname)
return nodeRequire('@rollup/plugin-replace')
}
catch (_) {
return require('@rollup/plugin-replace')
}
}

export async function generateRegisterSW(options: ResolvedVitePWAOptions, mode: 'build' | 'dev', source = 'register') {
const sw = options.buildBase + options.filename
const scope = options.scope
Expand Down Expand Up @@ -101,42 +87,36 @@ export async function generateInjectManifest(options: ResolvedVitePWAOptions, vi
// self.__WB_MANIFEST is default injection point
precacheAndRoute(self.__WB_MANIFEST)
*/
const vitePlugins = options.vitePlugins
const includedPluginNames: string[] = []
if (typeof vitePlugins === 'function')
includedPluginNames.push(...vitePlugins(viteOptions.plugins.map(p => p.name)))
else
includedPluginNames.push(...vitePlugins)

if (includedPluginNames.length === 0)
includedPluginNames.push(...defaultInjectManifestVitePlugins)

const replace = await loadRollupReplacePlugin()

const plugins = [
replace({
'preventAssignment': true,
'process.env.NODE_ENV': JSON.stringify(options.mode),
}),
...viteOptions.plugins.filter(p => includedPluginNames.includes(p.name)),
]
const { rollup } = await import('rollup')
const bundle = await rollup({
input: options.swSrc,
plugins,
})
try {
await bundle.write({
format: options.rollupFormat,
exports: 'none',
inlineDynamicImports: true,
file: options.injectManifest.swDest,

const { build } = await import('vite')

const define: Record<string, any> = { ...(viteOptions.define ?? {}) }
define['process.env.NODE_ENV'] = JSON.stringify(options.mode)

const { format, plugins, rollupOptions } = options.injectManifestRollupOptions

await build({
base: viteOptions.base,
build: {
sourcemap: viteOptions.build.sourcemap,
})
}
finally {
await bundle.close()
}
lib: {
entry: options.swSrc,
name: 'app',
formats: [format],
},
rollupOptions: {
...rollupOptions,
plugins,
output: {
entryFileNames: options.filename,
},
},
outDir: options.outDir,
emptyOutDir: false,
},
configFile: false,
define,
})

// don't force user to include injection point
if (!options.injectManifest.injectionPoint)
Expand Down
7 changes: 7 additions & 0 deletions src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ export async function resolveOptions(options: Partial<VitePWAOptions>, viteConfi
: Object.assign({}, defaultManifest, options.manifest || {})
const {
vitePlugins = defaultInjectManifestVitePlugins,
plugins = [],
rollupOptions = {},
rollupFormat = 'es',
...userInjectManifest
} = options.injectManifest || {}
Expand Down Expand Up @@ -159,6 +161,11 @@ export async function resolveOptions(options: Partial<VitePWAOptions>, viteConfi
vitePlugins,
selfDestroying,
buildBase: buildBase ?? basePath,
injectManifestRollupOptions: {
plugins,
rollupOptions,
format: rollupFormat,
},
}

// calculate hash only when required
Expand Down
29 changes: 26 additions & 3 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { ResolvedConfig } from 'vite'
import type { Plugin, ResolvedConfig } from 'vite'
import type { GenerateSWOptions, InjectManifestOptions, ManifestEntry } from 'workbox-build'
import type { OutputBundle } from 'rollup'
import type { OutputBundle, RollupOptions } from 'rollup'

export type InjectManifestVitePlugins = string[] | ((vitePluginIds: string[]) => string[])
export type CustomInjectManifestOptions = InjectManifestOptions & {
Expand All @@ -13,9 +13,25 @@ export type CustomInjectManifestOptions = InjectManifestOptions & {
/**
* `Vite` plugin ids to use on `Rollup` build.
*
* **WARN**: this option is for advanced usage, beware, you can break the service worker build.
* **WARN**: this option is for advanced usage, beware, you can break your application build.
*
* @deprecated use `plugins` instead
*/
vitePlugins?: InjectManifestVitePlugins
/**
* Since `v0.15.0` you can add plugins to build your service worker.
*
* When using `injectManifest` there are 2 builds, your application and the service worker.
* If you're using custom configuration for your service worker (for example custom plugins) you can use this option to configure the service worker build.
* Both configurations cannot be shared, and so you'll need to duplicate the configuration, with the exception of `define`.
*
* **WARN**: this option is for advanced usage, beware, you can break your application build.
*/
plugins?: Plugin[]
/**
* Since `v0.15.0` you can add custom Rollup options to build your service worker: we expose the same configuration to build a worker using Vite.
*/
rollupOptions?: Omit<RollupOptions, 'plugins' | 'output'>
}

export interface PWAIntegration {
Expand Down Expand Up @@ -169,13 +185,20 @@ export interface VitePWAOptions {
buildBase?: string
}

export interface ResolvedServiceWorkerOptions {
format: 'es' | 'iife'
plugins: Plugin[]
rollupOptions: RollupOptions
}

export interface ResolvedVitePWAOptions extends Required<VitePWAOptions> {
swSrc: string
swDest: string
workbox: GenerateSWOptions
injectManifest: InjectManifestOptions
rollupFormat: 'es' | 'iife'
vitePlugins: InjectManifestVitePlugins
injectManifestRollupOptions: ResolvedServiceWorkerOptions
}

export interface ShareTargetFiles {
Expand Down

0 comments on commit 7cacdd3

Please sign in to comment.