Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(worker): import.meta.* #7706

Merged
merged 18 commits into from Apr 26, 2022
19 changes: 16 additions & 3 deletions packages/playground/worker/__tests__/es/es-worker.spec.ts
Expand Up @@ -51,16 +51,20 @@ test.concurrent.each([[true], [false]])('shared worker', async (doTick) => {
await waitSharedWorkerTick(page)
})

test('worker emitted', async () => {
await untilUpdated(() => page.textContent('.nested-worker'), 'pong')
test('worker emitted and import.meta.url in nested worker', async () => {
expect(await page.textContent('.nested-worker')).toMatch('/worker-nested')
expect(await page.textContent('.nested-worker-module')).toMatch('/sub-worker')
expect(await page.textContent('.nested-worker-constructor')).toMatch(
'"type":"constructor"'
)
})

if (isBuild) {
const assetsDir = path.resolve(testDir, 'dist/es/assets')
// assert correct files
test('inlined code generation', async () => {
const files = fs.readdirSync(assetsDir)
expect(files.length).toBe(22)
expect(files.length).toBe(27)
const index = files.find((f) => f.includes('main-module'))
const content = fs.readFileSync(path.resolve(assetsDir, index), 'utf-8')
const worker = files.find((f) => f.includes('my-worker'))
Expand Down Expand Up @@ -100,3 +104,12 @@ test('emit chunk', async () => {
'"A string/es/"'
)
})

test('import.meta.glob in worker', async () => {
expect(await page.textContent('.importMetaGlob-worker')).toMatch('["')
})

// FIXME after buildEsbuildPlugin renderChunk export default a() break token
// test('import.meta.globEager in worker', async () => {
// expect(await page.textContent('.importMetaGlobEager-worker')).toMatch('["')
// })
poyoho marked this conversation as resolved.
Show resolved Hide resolved
13 changes: 9 additions & 4 deletions packages/playground/worker/__tests__/iife/worker.spec.ts
Expand Up @@ -52,9 +52,10 @@ test.concurrent.each([[true], [false]])('shared worker', async (doTick) => {
})

test('worker emitted and import.meta.url in nested worker', async () => {
await untilUpdated(
() => page.textContent('.nested-worker'),
'pong http://localhost:3000/iife/sub-worker.js?worker_file'
expect(await page.textContent('.nested-worker')).toMatch('/worker-nested')
expect(await page.textContent('.nested-worker-module')).toMatch('/sub-worker')
expect(await page.textContent('.nested-worker-constructor')).toMatch(
'"type":"constructor"'
)
})

Expand All @@ -63,7 +64,7 @@ if (isBuild) {
// assert correct files
test('inlined code generation', async () => {
const files = fs.readdirSync(assetsDir)
expect(files.length).toBe(13)
expect(files.length).toBe(14)
const index = files.find((f) => f.includes('main-module'))
const content = fs.readFileSync(path.resolve(assetsDir, index), 'utf-8')
const worker = files.find((f) => f.includes('my-worker'))
Expand Down Expand Up @@ -94,3 +95,7 @@ test('classic worker', async () => {
expect(await page.textContent('.classic-worker')).toMatch('A classic')
expect(await page.textContent('.classic-shared-worker')).toMatch('A classic')
})

test('import.meta.globEager in worker', async () => {
expect(await page.textContent('.importMetaGlobEager-worker')).toMatch('["')
})
Expand Up @@ -9,7 +9,7 @@ if (isBuild) {
test('sourcemap generation for web workers', async () => {
const files = fs.readdirSync(assetsDir)
// should have 2 worker chunk
expect(files.length).toBe(25)
expect(files.length).toBe(27)
const index = files.find((f) => f.includes('main-module'))
const content = fs.readFileSync(path.resolve(assetsDir, index), 'utf-8')
const indexSourcemap = getSourceMapUrl(content)
Expand Down
Expand Up @@ -9,7 +9,7 @@ if (isBuild) {
test('sourcemap generation for web workers', async () => {
const files = fs.readdirSync(assetsDir)
// should have 2 worker chunk
expect(files.length).toBe(13)
expect(files.length).toBe(14)
const index = files.find((f) => f.includes('main-module'))
const content = fs.readFileSync(path.resolve(assetsDir, index), 'utf-8')
const indexSourcemap = getSourceMapUrl(content)
Expand Down
Expand Up @@ -9,7 +9,7 @@ if (isBuild) {
test('sourcemap generation for web workers', async () => {
const files = fs.readdirSync(assetsDir)
// should have 2 worker chunk
expect(files.length).toBe(25)
expect(files.length).toBe(27)
const index = files.find((f) => f.includes('main-module'))
const content = fs.readFileSync(path.resolve(assetsDir, index), 'utf-8')
const indexSourcemap = getSourceMapUrl(content)
Expand Down
5 changes: 5 additions & 0 deletions packages/playground/worker/importMetaGlob.worker.js
@@ -0,0 +1,5 @@
const modules = import.meta.glob('./modules/*js')

self.onmessage = function (e) {
self.postMessage(Object.keys(modules))
}
5 changes: 5 additions & 0 deletions packages/playground/worker/importMetaGlobEager.worker.js
@@ -0,0 +1,5 @@
const modules = import.meta.globEager('./modules/*js')

self.onmessage = function (e) {
self.postMessage(Object.keys(modules))
}
29 changes: 28 additions & 1 deletion packages/playground/worker/index.html
Expand Up @@ -40,11 +40,25 @@ <h2 class="format-iife">format iife:</h2>
<code class="shared-worker-import-meta-url"></code>

<p>
import NestedWorker from './worker-nested-worker?worker' - nested worker
import NestedWorker from './worker-nested-worker?worker' - import.meta.url
<span class="classname">.nested-worker</span>
</p>
<code class="nested-worker"></code>

<p>
import NestedWorker from './worker-nested-worker?worker' - nested module
worker
<span class="classname">.nested-worker-module</span>
</p>
<code class="nested-worker-module"></code>

<p>
import NestedWorker from './worker-nested-worker?worker' - nested worker
constructor
<span class="classname">.nested-worker-constructor</span>
</p>
<code class="nested-worker-constructor"></code>

<p>
new Worker(new URL('./classic-worker.js', import.meta.url))
<span class="classname">.classic-worker</span>
Expand All @@ -58,9 +72,22 @@ <h2 class="format-iife">format iife:</h2>
</p>
<code class="classic-shared-worker"></code>

<p>
use import.meta.globEager in iife worker
<span class="classname">.importMetaGlobEager-worker</span>
</p>
<code class="importMetaGlobEager-worker"></code>

<hr />

<h2 class="format-es"></h2>

<p>
use import.meta.glob in es worker
<span class="classname">.importMetaGlob-worker</span>
</p>
<code class="importMetaGlob-worker"></code>

<p>
worker emit chunk <br />
module and worker:worker in worker file <br />
Expand Down
19 changes: 17 additions & 2 deletions packages/playground/worker/worker-nested-worker.js
Expand Up @@ -8,6 +8,21 @@ self.onmessage = (event) => {
}
}

subWorker.onmessage = (event) => {
self.postMessage(event.data)
self.postMessage(import.meta.url)

subWorker.onmessage = (ev) => {
self.postMessage({
type: 'module',
data: ev.data
})
}

const classicWorker = new Worker(new URL('./url-worker.js', import.meta.url), {
type: 'module'
})
classicWorker.addEventListener('message', (ev) => {
self.postMessage({
type: 'constructor',
data: ev.data
})
})
9 changes: 9 additions & 0 deletions packages/playground/worker/worker/main-format-es.js
@@ -1,5 +1,6 @@
// run when format es
import NestedWorker from '../emit-chunk-nested-worker?worker'
import ImportMetaGlobWorker from '../importMetaGlob.worker?worker'

function text(el, text) {
document.querySelector(el).textContent = text
Expand Down Expand Up @@ -39,3 +40,11 @@ const moduleWorker = new Worker(
moduleWorker.addEventListener('message', (ev) => {
text('.module-and-worker-worker', JSON.stringify(ev.data))
})

const importMetaGlobWorker = new ImportMetaGlobWorker()

importMetaGlobWorker.postMessage('1')

importMetaGlobWorker.addEventListener('message', (e) => {
text('.importMetaGlob-worker', JSON.stringify(e.data))
})
13 changes: 13 additions & 0 deletions packages/playground/worker/worker/main-module.js
Expand Up @@ -3,6 +3,7 @@ import InlineWorker from '../my-worker?worker&inline'
import mySharedWorker from '../my-shared-worker?sharedworker&name=shared'
import TSOutputWorker from '../possible-ts-output-worker?worker'
import NestedWorker from '../worker-nested-worker?worker'
import ImportMetaGlobEagerWorker from '../importMetaGlobEager.worker?worker'
import { mode } from '../modules/workerImport'

function text(el, text) {
Expand Down Expand Up @@ -56,6 +57,10 @@ const nestedWorker = new NestedWorker()
nestedWorker.addEventListener('message', (ev) => {
if (typeof ev.data === 'string') {
text('.nested-worker', JSON.stringify(ev.data))
} else if (ev.data.type === 'module') {
text('.nested-worker-module', JSON.stringify(ev.data))
} else if (ev.data.type === 'constructor') {
text('.nested-worker-constructor', JSON.stringify(ev.data))
}
})
nestedWorker.postMessage('ping')
Expand Down Expand Up @@ -83,3 +88,11 @@ w2.port.addEventListener('message', (ev) => {
text('.shared-worker-import-meta-url', JSON.stringify(ev.data))
})
w2.port.start()

const importMetaGlobEagerWorker = new ImportMetaGlobEagerWorker()

importMetaGlobEagerWorker.postMessage('1')

importMetaGlobEagerWorker.addEventListener('message', (e) => {
text('.importMetaGlobEager-worker', JSON.stringify(e.data))
})
23 changes: 16 additions & 7 deletions packages/vite/src/node/plugins/importAnalysisBuild.ts
Expand Up @@ -85,8 +85,8 @@ function preload(baseModule: () => Promise<{}>, deps?: string[]) {
*/
export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
const ssr = !!config.build.ssr
const insertPreload = !(ssr || !!config.build.lib)
const isWorker = config.isWorker
const insertPreload = !(ssr || !!config.build.lib || isWorker)

const scriptRel = config.build.polyfillModulePreload
? `'modulepreload'`
Expand Down Expand Up @@ -121,11 +121,6 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
return
}

if (isWorker) {
// preload method use `document` and can't run in the worker
return
}

await init

let imports: readonly ImportSpecifier[] = []
Expand Down Expand Up @@ -157,6 +152,18 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
source.slice(start, end) === 'import.meta' &&
source.slice(end, end + 5) === '.glob'
) {
// es worker allow globEager / glob
// iife worker just allow globEager
if (
isWorker &&
config.worker.format === 'iife' &&
source.slice(end, end + 10) !== '.globEager'
) {
this.error(
'can not use dynamic import(import.meta.glob) in iife worker. Just support import.meta.globEager in iife worker.',
end
)
}
const { importsString, exp, endIndex, isEager } =
await transformImportGlob(
source,
Expand All @@ -180,7 +187,9 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
if (dynamicIndex > -1 && insertPreload) {
needPreloadHelper = true
const original = source.slice(expStart, expEnd)
const replacement = `${preloadMethod}(() => ${original},${isModernFlag}?"${preloadMarker}":void 0)`
const replacement = isWorker
? `() => ${original}`
: `${preloadMethod}(() => ${original},${isModernFlag}?"${preloadMarker}":void 0)`
poyoho marked this conversation as resolved.
Show resolved Hide resolved
str().overwrite(expStart, expEnd, replacement, { contentOnly: true })
}

Expand Down
3 changes: 2 additions & 1 deletion packages/vite/src/node/plugins/index.ts
Expand Up @@ -12,7 +12,7 @@ import { clientInjectionsPlugin } from './clientInjections'
import { buildHtmlPlugin, htmlInlineProxyPlugin } from './html'
import { wasmPlugin } from './wasm'
import { modulePreloadPolyfillPlugin } from './modulePreloadPolyfill'
import { webWorkerPlugin } from './worker'
import { webWorkerPlugin, webWorkerImportMetaUrlPlugin } from './worker'
import { preAliasPlugin } from './preAlias'
import { definePlugin } from './define'
import { ssrRequireHookPlugin } from './ssrRequireHook'
Expand Down Expand Up @@ -72,6 +72,7 @@ export async function resolvePlugins(
isBuild && buildHtmlPlugin(config),
workerImportMetaUrlPlugin(config),
...buildPlugins.pre,
isBuild && webWorkerImportMetaUrlPlugin(config),
...postPlugins,
...buildPlugins.post,
// internal server-only plugins are always applied after everything else
Expand Down
20 changes: 16 additions & 4 deletions packages/vite/src/node/plugins/worker.ts
Expand Up @@ -194,7 +194,6 @@ export async function workerFileToUrl(

export function webWorkerPlugin(config: ResolvedConfig): Plugin {
const isBuild = config.command === 'build'
const isWorker = config.isWorker

return {
name: 'vite:worker',
Expand Down Expand Up @@ -276,10 +275,23 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
}`,
map: { mappings: '' } // Empty sourcemap to supress Rolup warning
}
},
}
}
}

// just run in build mode
export function webWorkerImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
const isWorker = config.isWorker

renderChunk(code) {
if (isWorker && code.includes('import.meta.url')) {
return {
name: 'vite:workerImportMetaUrl',
transform(code) {
if (isWorker && config.worker.format !== 'es') {
// if build with iife it will polyfill with rollup will be used document in the worker
// else if build with es it will replace with `define plugin` will got a unexpected data.
// so replace import.meta.url break the default handle.
// And it must be done at this (after `(?new Worker)new URL('xxx', import.meta.url)` match),
// Otherwise, the following regex will be incorrectly matched.
return code.replace('import.meta.url', 'self.location.href')
poyoho marked this conversation as resolved.
Show resolved Hide resolved
}
}
Expand Down