diff --git a/package.json b/package.json index 554c3ad8515c44..1f0b828364bb63 100644 --- a/package.json +++ b/package.json @@ -95,6 +95,7 @@ "rollup-plugin-dynamic-import-variables": "^1.0.1", "rollup-plugin-terser": "^5.3.0", "rollup-plugin-vue": "^6.0.0-beta.6", + "rollup-plugin-web-worker-loader": "^1.3.0", "selfsigned": "^1.10.7", "slash": "^3.0.0", "vue": "^3.0.0-beta.14", diff --git a/playground/App.vue b/playground/App.vue index 3da18bd92d833a..8923b863f3715d 100644 --- a/playground/App.vue +++ b/playground/App.vue @@ -23,6 +23,7 @@ + diff --git a/playground/worker/TestWorker.vue b/playground/worker/TestWorker.vue new file mode 100644 index 00000000000000..37a8697bfa5d34 --- /dev/null +++ b/playground/worker/TestWorker.vue @@ -0,0 +1,28 @@ + + + diff --git a/playground/worker/worker.js b/playground/worker/worker.js new file mode 100644 index 00000000000000..a36e3e812a04ba --- /dev/null +++ b/playground/worker/worker.js @@ -0,0 +1,7 @@ +import { msg } from './workerImport' + +self.onmessage = (e) => { + if (e.data === 'ping') { + self.postMessage(msg) + } +} diff --git a/playground/worker/workerImport.js b/playground/worker/workerImport.js new file mode 100644 index 00000000000000..b06eff50b47ec6 --- /dev/null +++ b/playground/worker/workerImport.js @@ -0,0 +1 @@ +export const msg = 'pong' diff --git a/src/node/build/index.ts b/src/node/build/index.ts index 62a03f44864ab5..6ec83452f18a52 100644 --- a/src/node/build/index.ts +++ b/src/node/build/index.ts @@ -283,6 +283,14 @@ export async function build(options: BuildConfig): Promise { assetsDir, assetsInlineLimit ), + // https://github.com/darionco/rollup-plugin-web-worker-loader + // configured to support `import Worker from './my-worker?worker'` + require('rollup-plugin-web-worker-loader')({ + targetPlatform: 'browser', + pattern: /(.+)\?worker/, + extensions: supportedExts, + preserveSource: true // somehow results in slightly smaller bundle + }), // minify with terser // this is the default which has better compression, but slow // the user can opt-in to use esbuild which is much faster but results @@ -290,7 +298,7 @@ export async function build(options: BuildConfig): Promise { minify && minify !== 'esbuild' ? require('rollup-plugin-terser').terser() : undefined - ] + ].filter(Boolean) }) const { output } = await bundle.generate({ diff --git a/src/node/server/index.ts b/src/node/server/index.ts index 5297f3275ca2dc..49f137903eedcd 100644 --- a/src/node/server/index.ts +++ b/src/node/server/index.ts @@ -24,6 +24,7 @@ import { cachedRead } from '../utils' import { envPlugin } from './serverPluginEnv' export { rewriteImports } from './serverPluginModuleRewrite' import { sourceMapPlugin, SourceMap } from './serverPluginSourceMap' +import { webWrokerPlugin } from './serverPluginWebWorker' export type ServerPlugin = (ctx: ServerPluginContext) => void @@ -99,6 +100,7 @@ export function createServer(config: ServerConfig): Server { esbuildPlugin, jsonPlugin, assetPathPlugin, + webWrokerPlugin, serveStaticPlugin ] resolvedPlugins.forEach((m) => m(context)) diff --git a/src/node/server/serverPluginWebWorker.ts b/src/node/server/serverPluginWebWorker.ts index e10d4fab8bb956..5e407b4143eabc 100644 --- a/src/node/server/serverPluginWebWorker.ts +++ b/src/node/server/serverPluginWebWorker.ts @@ -1,5 +1,14 @@ import { ServerPlugin } from '.' export const webWrokerPlugin: ServerPlugin = ({ app }) => { - app.use(async (ctx, next) => {}) + app.use((ctx, next) => { + if (ctx.query.worker != null) { + ctx.type = 'js' + ctx.body = `export default function WrappedWorker() { + return new Worker(${JSON.stringify(ctx.path)}, { type: 'module' }) + }` + return + } + return next() + }) } diff --git a/test/test.js b/test/test.js index 1d21fa7f9b5da2..65cb6f1f5779bb 100644 --- a/test/test.js +++ b/test/test.js @@ -578,6 +578,12 @@ describe('vite', () => { expect(await getText(`.dynamic-import-one`)).toMatch(`One`) expect(await getText(`.dynamic-import-two`)).toMatch(`Two`) }) + + test('importing web worker', async () => { + const button = await page.$('.worker-send') + await button.click() + await expectByPolling(() => getText('.worker-response'), 'pong') + }) } // test build first since we are going to edit the fixtures when testing dev diff --git a/yarn.lock b/yarn.lock index 6f20a68c2351c5..91964031bdd44d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5909,6 +5909,11 @@ rollup-plugin-vue@^6.0.0-beta.6: hash-sum "^2.0.0" rollup-pluginutils "^2.8.2" +rollup-plugin-web-worker-loader@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-web-worker-loader/-/rollup-plugin-web-worker-loader-1.3.0.tgz#4ee63ad8c3970a649a2c7a8b4b8cf3292eff3e70" + integrity sha512-BA/bp7ThY5wpWij7vWOJQyJgdQWaMFp6uFCv3i4qHdUd+0d+LFT8GzkgwsU8i26n6+iCQ3xTTHOyoi8h36EbUQ== + rollup-pluginutils@^2.8.2: version "2.8.2" resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e"