Skip to content

Commit

Permalink
feat(worker): support worker format, plugins and rollupOptions (fix #…
Browse files Browse the repository at this point in the history
  • Loading branch information
poyoho committed Jan 2, 2022
1 parent a49d723 commit 133fcea
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 8 deletions.
21 changes: 21 additions & 0 deletions docs/config/index.md
Expand Up @@ -976,3 +976,24 @@ SSR options may be adjusted in minor releases.
- **Default:** `node`

Build target for the SSR server.

## Worker Options

### worker.format

- **Type:** `'es' | 'iife'`
- **Default:** `iife`

Output format for worker bundle.

### worker.plugins

- **Type:** [`(Plugin | Plugin[])[]`](#plugins)

Vite plugins that apply to worker bundle

### worker.rollupOptions

- **Type:** [`RollupOptions`](https://rollupjs.org/guide/en/#big-list-of-options)

Rollup options to build worker bundle.
5 changes: 4 additions & 1 deletion packages/playground/worker/__tests__/worker.spec.ts
Expand Up @@ -10,6 +10,10 @@ test('normal', async () => {
() => page.textContent('.mode'),
isBuild ? 'production' : 'development'
)
await untilUpdated(
() => page.textContent('.bundle-with-plugin'),
'worker bundle with plugin success!'
)
})

test('TS output', async () => {
Expand Down Expand Up @@ -52,7 +56,6 @@ if (isBuild) {
test('inlined code generation', async () => {
const assetsDir = path.resolve(testDir, 'dist/assets')
const files = fs.readdirSync(assetsDir)
// should have 3 worker chunk
expect(files.length).toBe(4)
const index = files.find((f) => f.includes('index'))
const content = fs.readFileSync(path.resolve(assetsDir, index), 'utf-8')
Expand Down
2 changes: 2 additions & 0 deletions packages/playground/worker/index.html
Expand Up @@ -3,6 +3,7 @@
<div>
Response from worker: <span class="pong"></span><span class="mode"></span>
</div>
<div>bundle-with-plugin: <span class="bundle-with-plugin"></span></div>

<button class="ping-inline">Ping Inline Worker</button>
<div>Response from inline worker: <span class="pong-inline"></span></div>
Expand Down Expand Up @@ -32,6 +33,7 @@
worker.addEventListener('message', (e) => {
text('.pong', e.data.msg)
text('.mode', e.data.mode)
text('.bundle-with-plugin', e.data.bundleWithPlugin)
})

document.querySelector('.ping').addEventListener('click', () => {
Expand Down
3 changes: 2 additions & 1 deletion packages/playground/worker/my-worker.ts
@@ -1,7 +1,8 @@
import { msg, mode } from './workerImport'
import { bundleWithPlugin } from './test-plugin'

self.onmessage = (e) => {
if (e.data === 'ping') {
self.postMessage({ msg, mode })
self.postMessage({ msg, mode, bundleWithPlugin })
}
}
3 changes: 3 additions & 0 deletions packages/playground/worker/package.json
Expand Up @@ -7,5 +7,8 @@
"build": "vite build",
"debug": "node --inspect-brk ../../vite/bin/vite",
"preview": "vite preview"
},
"devDependencies": {
"@vitejs/plugin-vue-jsx": "workspace:*"
}
}
1 change: 1 addition & 0 deletions packages/playground/worker/test-plugin.tsx
@@ -0,0 +1 @@
export const bundleWithPlugin: string = 'worker bundle with plugin success!'
11 changes: 11 additions & 0 deletions packages/playground/worker/vite.config.ts
@@ -0,0 +1,11 @@
import vueJsx from '@vitejs/plugin-vue-jsx'
import { defineConfig } from 'vite'

export default defineConfig({
build: {
target: process.env.NODE_ENV === 'production' ? 'chrome60' : 'esnext'
},
worker: {
plugins: [vueJsx()]
}
})
22 changes: 22 additions & 0 deletions packages/vite/src/node/config.ts
Expand Up @@ -39,6 +39,7 @@ import aliasPlugin from '@rollup/plugin-alias'
import { build } from 'esbuild'
import { performance } from 'perf_hooks'
import type { PackageCache } from './packages'
import type { RollupOptions } from 'rollup'

const debug = createDebugger('vite:config')

Expand Down Expand Up @@ -185,6 +186,27 @@ export interface UserConfig {
* @deprecated use `resolve.dedupe` instead
*/
dedupe?: string[]
/**
* Worker bundle options
*/
worker?: {
/**
* Output format for worker bundle
* @default 'iife'
*/
format?: 'es' | 'iife'
/**
* Vite plugins that apply to worker bundle
*/
plugins?: (PluginOption | PluginOption[])[]
/**
* Rollup options to build worker bundle
*/
rollupOptions?: Omit<
RollupOptions,
'plugins' | 'input' | 'onwarn' | 'preserveEntrySignatures'
>
}
}

export type SSRTarget = 'node' | 'webworker'
Expand Down
26 changes: 21 additions & 5 deletions packages/vite/src/node/plugins/worker.ts
@@ -1,17 +1,23 @@
import type { ResolvedConfig } from '../config'
import { sortUserPlugins } from '../config'
import type { Plugin } from '../plugin'
import { resolvePlugins } from '../plugins'
import { fileToUrl, getAssetHash } from './asset'
import { cleanUrl, injectQuery, parseRequest } from '../utils'
import type Rollup from 'rollup'
import { ENV_PUBLIC_PATH } from '../constants'
import path from 'path'
import { onRollupWarning } from '../build'
import { resolvePlugins } from '.'

const WorkerFileId = 'worker_file'

export function webWorkerPlugin(config: ResolvedConfig): Plugin {
const isBuild = config.command === 'build'
const workerBundleOptions = {
format: config.worker?.format || 'iife',
plugins: sortUserPlugins(config.worker?.plugins as Plugin[]),
rollupOptions: config.worker?.rollupOptions || {}
}

return {
name: 'vite:worker',
Expand Down Expand Up @@ -46,17 +52,26 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
if (isBuild) {
// bundle the file as entry to support imports
const rollup = require('rollup') as typeof Rollup
const { plugins, rollupOptions, format } = workerBundleOptions
const [prePlugins, normalPlugins, postPlugins] = plugins
const bundle = await rollup.rollup({
...rollupOptions,
input: cleanUrl(id),
plugins: await resolvePlugins({ ...config }, [], [], []),
plugins: await resolvePlugins(
{ ...config },
prePlugins,
normalPlugins,
postPlugins
),
onwarn(warning, warn) {
onRollupWarning(warning, warn, config)
}
},
preserveEntrySignatures: false
})
let code: string
try {
const { output } = await bundle.generate({
format: 'iife',
format,
sourcemap: config.build.sourcemap
})
code = output[0].code
Expand All @@ -65,13 +80,14 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
}
const content = Buffer.from(code)
if (query.inline != null) {
const workerOptions = format === 'es' ? '{type: "module"}' : '{}'
// inline as blob data url
return `const encodedJs = "${content.toString('base64')}";
const blob = typeof window !== "undefined" && window.Blob && new Blob([atob(encodedJs)], { type: "text/javascript;charset=utf-8" });
export default function WorkerWrapper() {
const objURL = blob && (window.URL || window.webkitURL).createObjectURL(blob);
try {
return objURL ? new Worker(objURL) : new Worker("data:application/javascript;base64," + encodedJs, {type: "module"});
return objURL ? new Worker(objURL, ${workerOptions}) : new Worker("data:application/javascript;base64," + encodedJs, {type: "module"});
} finally {
objURL && (window.URL || window.webkitURL).revokeObjectURL(objURL);
}
Expand Down
5 changes: 4 additions & 1 deletion pnpm-lock.yaml

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

0 comments on commit 133fcea

Please sign in to comment.