support `?inline` worker in constructors worker
Clear and concise description of the problem
we can use inline worker with import worker from "./worker?worker&inline"
and need to support inline worker in constructors worker.
Suggested solution
- use query syntax
const worker = new Worker(new URL('./worker.js?inline', import.meta.url))
but the end goal is to remove query suffixes everywhere for Vite.
- put inline in worker options
const worker = new Worker(new URL('./worker.js', import.meta.url), {
inline: true
})
that's non-standard
- use the comment
const worker = new Worker(new URL(/* #__INLINE__ */'./worker.js', import.meta.url))
and Rollup has a history of avoiding that too (e.g. webpackChunkName) and only supported pure comments thus far.
above solutions are not good.
this issue for it to discussed some ideas ❤️
Alternative
No response
Additional context
No response
Validations
- [X] Follow our Code of Conduct
- [X] Read the Contributing Guidelines.
- [X] Read the docs.
- [X] Check that there isn't already an issue that request the same feature to avoid creating a duplicate.
how about use the bundle size to generator inline or not. like fileToBuiltUrl
if (content.length < Number(config.build.assetsInlineLimit))) {
const encodedJs = "${code.toString('base64')}"
}
I'm not sure what's the usecase for inlining workers yet, but I like the option with config.build.assetsInlineLimit since it reuses an existing config option. The naming could be a bit misleading though since worker isn't really an asset, but I don't think it's a big issue 🤔
config in worker 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'
>
/**
* Worker files smaller than this number (in bytes) will be inlined as
* base64 strings. Default limit is `4096` (4kb). Set to `0` to disable.
* @default 4096
*/
inlineLimit?: number,
}
}
I have also seen suggestions for this configuration before, such as judging whether it should be inline by the file name
I'm not sure what's the usecase for inlining workers yet, but I like the option with
config.build.assetsInlineLimitsince it reuses an existing config option. The naming could be a bit misleading though since worker isn't really an asset, but I don't think it's a big issue 🤔
I don't know either (limit requests?) but then just switch to http2. The only use case I can think of if you want to inline ALL workers. (When you want a single file so evrything is potentaly inlined into the html file)
(Only if you need to support IE11 (or older) in windows < 10 you have problems see https://caniuse.com/http2,webworkers )
Hi, any bump on this? looking for solution how to inline worker for an npm package
@antokhio Why do you want them inline?
@antokhio Why do you want them inline?
https://discord.com/channels/804011606160703521/1040565505003618354
This is the discussion. Basically I’m trying to do an npm package, that have an component that needs a web worker witch implement 3-rd party library that I use for image processing.
So when I build package I have worker script bundled to /assets. Then I install this package with yarn or npm, add my component, check the chrome xhr and I see my worker script unavailable…
Already spent few days on that and I’m starting to think that the only way is to expose worker script and add is a dep to a worker manager class constructor that I’m using…
ps. If I copy worker bundle .js to public folder of new project it works… pss. package repo link is in discord thread, I did a try to make it work with comlink… but…
@antokhio
This is a bit strange but:
// doesn't work:
const getWorker = () => new Worker(new URL('./worker.js', import.meta.url), { type: 'module' })
// works:
const url = new URL('./worker.js', import.meta.url)
const getWorker = () => new Worker(url, { type: 'module' })
The first code example is handled by the internal workerImportMetaUrl which emits a separate asset for the worker that then fails to load, the second example is handled by assetImportMetaUrl plugin which inlines the asset as data URL, as you want.
hi @jonaskuske so i change the code and now it seems it's add another error hmm:
const url = new URL('./workers/arnft.worker.ts', import.meta.url);
const getWorker = () => new Worker(url, { type: 'module' });
const worker = getWorker() as Worker;
results:
const url = new URL("data:video/mp2t;base64,aW1...=", self.location);
const getWorker = () => new Worker(url, { type: "module" });
const worker = getWorker();
I think i've seen another issue with this data:video/mp2t
https://github.com/vitejs/vite/issues/9566#issuecomment-1293376288 https://github.com/vitejs/vite/issues/10271
trying to resolve from comments
@antokhio Yout npm-package problem as I understand (without need to inline):
- You need
new Worker(new URL('mypath.ts', import.meta.url), {type: "module"})to tell vite handle this worker - You need Vite to return in bundle the same syntax as 1. just a different path to
'assets/cunk-my-chunk.js'
I think there was a way to change how worker / import.meta.url are emitted... That would be a solution for your problem.
Default is:
const w = new Worker(
new URL("/assets/worker.5ac1100d.js", self.location),
{
type: "module"
}
);
@mathe42 that's what i have right now in the build:
const worker = new Worker(new URL("/arnft.worker.4e733d5c.js", self.location), {
type: "module"
});
Ahhh got it finnaly:
tsconfig.json > compilerOptions.target:es2020
vite.config.ts > build.target:es2020
the correct ts syntax:
const worker = new Worker(new URL('./workers/arnft.worker.ts', import.meta.url), { type: 'module', }) as Worker;
thanks @jonaskuske @mathe42
Did not fix that for me in build. What is the rest of your vite-config?
@mathe42 https://github.com/antokhio/react-three-jsartoolkitnft/blob/dbfd0efd6fe44937d2ee9349c26500ab3ebc1383/vite.config.ts
Did not fix that for me in build. What is the rest of your vite-config?
i think this isn't fixed ((( i had a worker script copied to public on tester project, that's why it worked yes it's same can't find worker file....
Will have a deeper look into it later.
did we come to a conclusion on this by any chance? also looking to embed worker as part of npm without needing to do ?inline with type: module option
running into the same issue defined here
Any update on this?
Yea, still haven't managed to fix my package...
Inlining didn't fix it for me since it didn't inline the whole tree (imports inside the worker) from this solution https://github.com/vitejs/vite/issues/7352#issuecomment-1312287659
I'm currently at the same state as here: https://github.com/vitejs/vite/issues/7352#issuecomment-1313366403 where the import with import.meta.url works but the produced code uses location.self
Edit: I've created a rollup plugin to rewrite the URL for now
Added to build.rollupOptions.output.plugins: [ rewriteWorkerImport() ]
const regex = /new Worker\(new URL\(\"(?<url>\.?\/.+?)\",\s?(?<base>self.location)\)/gm;
function rewriteWorkerImport() {
return {
name: 'rewriteWorkerImport',
renderChunk: {
order: 'post',
async handler(code: string, chunk, outputOptions) {
return code.replaceAll(regex, (match, url, _base) => {
if (url?.startsWith("/")) {
console.log(`Rewrite worker import in ${chunk.fileName}`);
// Make url file-relative
const newUrl = url.replace(/^\//, "");
return `new Worker(new URL("./${newUrl}", import.meta.url)`;
}
return match;
});
},
}
};
}