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

feat(worker): bundle worker emit asset file #6599

Merged
4 changes: 4 additions & 0 deletions packages/playground/wasm/__tests__/wasm.spec.ts
Expand Up @@ -9,3 +9,7 @@ test('should work when output', async () => {
await page.click('.output-wasm .run')
await untilUpdated(() => page.textContent('.output-wasm .result'), '24')
})

test('should work when wasm in worker', async () => {
await untilUpdated(() => page.textContent('.worker-wasm .result'), '3')
})
Binary file added packages/playground/wasm/add.wasm
Binary file not shown.
15 changes: 15 additions & 0 deletions packages/playground/wasm/index.html
Expand Up @@ -12,9 +12,20 @@ <h3>When wasm is output, result should be 24</h3>
<span class="result"></span>
</div>

<div class="worker-wasm">
<h3>worker wasm</h3>
<span class="result"></span>
</div>

<script type="module">
import light from './light.wasm'
import heavy from './heavy.wasm'
import myWorker from './worker?worker'

const w = new myWorker()
w.addEventListener('message', (ev) => {
text('.worker-wasm .result', ev.data.result)
})

async function testWasm(init, resultElement) {
const { exported_func } = await init({
Expand All @@ -25,6 +36,10 @@ <h3>When wasm is output, result should be 24</h3>
exported_func()
}

function text(el, text) {
document.querySelector(el).textContent = text
}

document
.querySelector('.inline-wasm .run')
.addEventListener('click', async () =>
Expand Down
8 changes: 8 additions & 0 deletions packages/playground/wasm/vite.config.ts
@@ -0,0 +1,8 @@
import { defineConfig } from 'vite'
export default defineConfig({
build: {
// make can no emit light.wasm
// and emit add.wasm
assetsInlineLimit: 80
}
})
5 changes: 5 additions & 0 deletions packages/playground/wasm/worker.js
@@ -0,0 +1,5 @@
import init from './add.wasm'
init().then((exports) => {
// eslint-disable-next-line no-undef
self.postMessage({ result: exports.add(1, 2) })
})
22 changes: 9 additions & 13 deletions packages/playground/worker/__tests__/worker.spec.ts
Expand Up @@ -51,12 +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')
await untilUpdated(
() => page.textContent('.nested-worker-dynamic-import'),
'"msg":"pong"'
)
})

if (isBuild) {
const assetsDir = path.resolve(testDir, 'dist/assets')
// assert correct files
test('inlined code generation', async () => {
const files = fs.readdirSync(assetsDir)
expect(files.length).toBe(8)
expect(files.length).toBe(11)
const index = files.find((f) => f.includes('index'))
const content = fs.readFileSync(path.resolve(assetsDir, index), 'utf-8')
const worker = files.find((f) => f.includes('my-worker'))
Expand All @@ -75,18 +83,6 @@ if (isBuild) {
expect(content).toMatch(`(window.URL||window.webkitURL).createObjectURL`)
expect(content).toMatch(`window.Blob`)
})

test('worker need bundle', () => {
fs.readdirSync(assetsDir)
.filter(
(file) =>
file.includes('url-worker') || file.includes('url-shared-worker')
)
.forEach((file) => {
const content = fs.readFileSync(path.resolve(assetsDir, file), 'utf-8')
expect(content.startsWith('(function(){')).toBe(true)
})
})
}

test('classic worker is run', async () => {
Expand Down
15 changes: 15 additions & 0 deletions packages/playground/worker/index.html
Expand Up @@ -26,6 +26,9 @@
<p>new SharedWorker(new Url('path', import.meta.url), { type: 'module' })</p>
<div class="shared-worker-import-meta-url"></div>

<p>nested worker</p>
<div class="nested-worker"></div>
<div class="nested-worker-dynamic-import"></div>
<p>new Worker(new Url('path', import.meta.url))</p>
<div class="classic-worker"></div>

Expand All @@ -37,6 +40,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 { mode } from './workerImport'
import './classic-worker'

Expand Down Expand Up @@ -114,4 +118,15 @@
)
})
w2.port.start()

const nestedWorker = new NestedWorker()
nestedWorker.addEventListener('message', (ev) => {
console.log(ev)
if (typeof ev.data === 'string') {
text('.nested-worker', ev.data)
} else {
text('.nested-worker-dynamic-import', JSON.stringify(ev.data))
}
})
nestedWorker.postMessage('ping')
</script>
13 changes: 13 additions & 0 deletions packages/playground/worker/sub-worker.js
@@ -0,0 +1,13 @@
self.onmessage = (event) => {
if (event.data === 'ping') {
self.postMessage('pong')
}
}
const data = import('./workerImport')
data.then((data) => {
const { mode, msg } = data
self.postMessage({
mode,
msg
})
})
3 changes: 2 additions & 1 deletion packages/playground/worker/vite.config.ts
Expand Up @@ -3,9 +3,10 @@ import { defineConfig } from 'vite'

export default defineConfig({
build: {
target: process.env.NODE_ENV === 'production' ? 'chrome60' : 'esnext'
// target: process.env.NODE_ENV === 'production' ? 'chrome60' : 'esnext'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change related to the esbuild issue @poyoho? Should we wait for it before merging this PR?

Copy link
Member Author

@poyoho poyoho Mar 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I open a issues in vite #7179

and open in esbuild too. evanw/esbuild#2089

I think not. I think chrome60 is not a important unit test.
The config may I copy from the issues repo in last time. 🙈

Copy link
Member

@patak-dev patak-dev Mar 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's uncomment this line if the change isn't needed then? Or remove the line directly?
We can merge it afterwards

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok.

},
worker: {
format: 'es',
plugins: [vueJsx()]
}
})
13 changes: 13 additions & 0 deletions packages/playground/worker/worker-nested-worker.js
@@ -0,0 +1,13 @@
import SubWorker from './sub-worker?worker'

const subWorker = new SubWorker()

self.onmessage = (event) => {
if (event.data === 'ping') {
subWorker.postMessage('ping')
}
}

subWorker.onmessage = (event) => {
self.postMessage(event.data)
}
21 changes: 18 additions & 3 deletions packages/vite/src/node/plugins/worker.ts
Expand Up @@ -10,6 +10,7 @@ import { onRollupWarning } from '../build'
const WorkerFileId = 'worker_file'

export async function bundleWorkerEntry(
ctx: Rollup.TransformPluginContext,
config: ResolvedConfig,
id: string
): Promise<Buffer> {
Expand All @@ -27,11 +28,25 @@ export async function bundleWorkerEntry(
})
let code: string
try {
const { output } = await bundle.generate({
const {
output: [outputCode, ...outputChunks]
} = await bundle.generate({
format,
sourcemap: config.build.sourcemap
})
code = output[0].code
code = outputCode.code
outputChunks.forEach((outputChunk) => {
if (outputChunk.type === 'asset') {
ctx.emitFile(outputChunk)
}
poyoho marked this conversation as resolved.
Show resolved Hide resolved
if (outputChunk.type === 'chunk') {
ctx.emitFile({
fileName: `${config.build.assetsDir}/${outputChunk.fileName}`,
source: outputChunk.code,
type: 'asset'
})
}
})
} finally {
await bundle.close()
}
Expand Down Expand Up @@ -72,7 +87,7 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {

let url: string
if (isBuild) {
const code = await bundleWorkerEntry(config, id)
const code = await bundleWorkerEntry(this, config, id)
if (query.inline != null) {
const { format } = config.worker
const workerOptions = format === 'es' ? '{type: "module"}' : '{}'
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/plugins/workerImportMetaUrl.ts
Expand Up @@ -138,7 +138,7 @@ export function workerImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
const file = path.resolve(path.dirname(id), rawUrl.slice(1, -1))
let url: string
if (isBuild) {
const content = await bundleWorkerEntry(config, file)
const content = await bundleWorkerEntry(this, config, file)
const basename = path.parse(cleanUrl(file)).name
const contentHash = getAssetHash(content)
const fileName = path.posix.join(
Expand Down