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

Importing a file from a web worker that imports said web worker causes Vite to build forever #7015

Closed
7 tasks done
hf02 opened this issue Feb 21, 2022 · 26 comments · Fixed by #16103
Closed
7 tasks done
Labels

Comments

@hf02
Copy link

hf02 commented Feb 21, 2022

Describe the bug

I have my project set up where I have an index file that exports everything in the folder. This is so I can solve a circular dependency.

When I created a web worker, I had it import from the index file. One of these files in the index directly imported the web worker using ?worker. This worked fine in development. When I went to build, however, Vite seemed to get stuck in an infinite loop and only stopped when it ran out of memory.

Reproduction

https://github.com/hf02/vite-infinite-build Much simpler reproduction, thanks to @zxch3n: https://stackblitz.com/edit/vitejs-vite-u59lcw?file=worker.js

System Info

System:
    OS: Windows 10 10.0.22000
    CPU: (16) x64 AMD Ryzen 7 3700X 8-Core Processor
    Memory: 9.38 GB / 15.95 GB
  Binaries:
    Node: 16.14.0 - ~\AppData\Local\nvs\default\node.EXE
    npm: 8.3.1 - ~\AppData\Local\nvs\default\npm.CMD
  Browsers:
    Edge: Spartan (44.22000.120.0), Chromium (98.0.1108.56)
    Internet Explorer: 11.0.22000.120

Used Package Manager

pnpm

Logs

PS C:\Users\user\Desktop\vite-project> # i replaced my windows username with a generic "user"
PS C:\Users\user\Desktop\vite-project> pnpx vite build --debug
  vite:config no config file found. +0ms
  vite:config using resolved config: {
  vite:config   root: 'C:/Users/user/Desktop/vite-project',
  vite:config   base: '/',
  vite:config   mode: 'production',
  vite:config   configFile: undefined,
  vite:config   logLevel: undefined,
  vite:config   clearScreen: undefined,
  vite:config   build: {
  vite:config     target: [ 'es2019', 'edge88', 'firefox78', 'chrome87', 'safari13.1' ],
  vite:config     polyfillModulePreload: true,
  vite:config     outDir: 'dist',
  vite:config     assetsDir: 'assets',
  vite:config     assetsInlineLimit: 4096,
  vite:config     cssCodeSplit: true,
  vite:config     cssTarget: [ 'es2019', 'edge88', 'firefox78', 'chrome87', 'safari13.1' ],
  vite:config     sourcemap: false,
  vite:config     rollupOptions: {},
  vite:config     minify: 'esbuild',
  vite:config     terserOptions: {},
  vite:config     write: true,
  vite:config     emptyOutDir: null,
  vite:config     manifest: false,
  vite:config     lib: false,
  vite:config     ssr: false,
  vite:config     ssrManifest: false,
  vite:config     reportCompressedSize: true,
  vite:config     chunkSizeWarningLimit: 500,
  vite:config     watch: null,
  vite:config     commonjsOptions: { include: [Array], extensions: [Array] },
  vite:config     dynamicImportVarsOptions: { warnOnError: true, exclude: [Array] }
  vite:config   },
  vite:config   configFileDependencies: [],
  vite:config   inlineConfig: {
  vite:config     root: undefined,
  vite:config     base: undefined,
  vite:config     mode: undefined,
  vite:config     configFile: undefined,
  vite:config     logLevel: undefined,
  vite:config     clearScreen: undefined,
  vite:config     build: {}
  vite:config   },
  vite:config   resolve: { dedupe: undefined, alias: [ [Object], [Object] ] },
  vite:config   publicDir: 'C:\\Users\\user\\Desktop\\vite-project\\public',
  vite:config   cacheDir: 'C:\\Users\\user\\Desktop\\vite-project\\node_modules\\.vite',
  vite:config   command: 'build',
  vite:config   isProduction: true,
  vite:config   plugins: [
  vite:config     'alias',
  vite:config     'vite:modulepreload-polyfill',
  vite:config     'vite:resolve',
  vite:config     'vite:html-inline-proxy',
  vite:config     'vite:css',
  vite:config     'vite:esbuild',
  vite:config     'vite:json',
  vite:config     'vite:wasm',
  vite:config     'vite:worker',
  vite:config     'vite:worker-import-meta-url',
  vite:config     'vite:asset',
  vite:config     'vite:define',
  vite:config     'vite:css-post',
  vite:config     'vite:watch-package-data',
  vite:config     'vite:build-html',
  vite:config     'commonjs',
  vite:config     'vite:data-uri',
  vite:config     'rollup-plugin-dynamic-import-variables',
  vite:config     'vite:asset-import-meta-url',
  vite:config     'vite:build-import-analysis',
  vite:config     'vite:esbuild-transpile',
  vite:config     'vite:terser',
  vite:config     'vite:reporter',
  vite:config     'vite:load-fallback'
  vite:config   ],
  vite:config   server: {
  vite:config     preTransformRequests: true,
  vite:config     fs: { strict: true, allow: [Array], deny: [Array] }
  vite:config   },
  vite:config   preview: {
  vite:config     port: undefined,
  vite:config     strictPort: undefined,
  vite:config     host: undefined,
  vite:config     https: undefined,
  vite:config     open: undefined,
  vite:config     proxy: undefined,
  vite:config     cors: undefined,
  vite:config     headers: undefined
  vite:config   },
  vite:config   env: { BASE_URL: '/', MODE: 'production', DEV: false, PROD: true },
  vite:config   assetsInclude: [Function: assetsInclude],
  vite:config   logger: {
  vite:config     hasWarned: false,
  vite:config     info: [Function: info],
  vite:config     warn: [Function: warn],
  vite:config     warnOnce: [Function: warnOnce],
  vite:config     error: [Function: error],
  vite:config     clearScreen: [Function: clearScreen],
  vite:config     hasErrorLogged: [Function: hasErrorLogged]
  vite:config   },
  vite:config   packageCache: Map(0) { set: [Function (anonymous)] },
  vite:config   createResolver: [Function: createResolver],
  vite:config   optimizeDeps: {
  vite:config     esbuildOptions: { keepNames: undefined, preserveSymlinks: undefined }
  vite:config   },
  vite:config   worker: {
  vite:config     format: 'iife',
  vite:config     plugins: [
  vite:config       [Object], [Object], [Object],
  vite:config       [Object], [Object], [Object],
  vite:config       [Object], [Object], [Object],
  vite:config       [Object], [Object], [Object],
  vite:config       [Object], [Object], [Object],
  vite:config       [Object], [Object], [Object],
  vite:config       [Object], [Object], [Object],
  vite:config       [Object], [Object], [Object]
  vite:config     ],
  vite:config     rollupOptions: {}
  vite:config   }
  vite:config } +5ms
vite v2.8.4 building for production...
transforming (85241) src\lib\worker\theWorker.ts
<--- Last few GCs --->

[1580:000002AACF9E4580]   152266 ms: Mark-sweep 3980.6 (4139.2) -> 3968.6 (4141.2) MB, 1286.2 / 0.0 ms  (average mu = 0.131, current mu = 0.080) task scavenge might not succeed
[1580:000002AACF9E4580]   153712 ms: Mark-sweep 3982.3 (4141.4) -> 3970.8 (4143.4) MB, 1333.3 / 0.0 ms  (average mu = 0.105, current mu = 0.078) task scavenge might not succeed


<--- JS stacktrace --->

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
 1: 00007FF63F237B7F v8::internal::CodeObjectRegistry::~CodeObjectRegistry+114079
 2: 00007FF63F1C4546 DSA_meth_get_flags+65542
 3: 00007FF63F1C53FD node::OnFatalError+301
 4: 00007FF63FAFB29E v8::Isolate::ReportExternalAllocationLimitReached+94
 5: 00007FF63FAE587D v8::SharedArrayBuffer::Externalize+781
 6: 00007FF63F988C4C v8::internal::Heap::EphemeronKeyWriteBarrierFromCode+1468
 7: 00007FF63F9958F9 v8::internal::Heap::PublishPendingAllocations+1129
 8: 00007FF63F9928CA v8::internal::Heap::PageFlagsAreConsistent+2842
 9: 00007FF63F985529 v8::internal::Heap::CollectGarbage+2137
10: 00007FF63F935A95 v8::internal::IndexGenerator::~IndexGenerator+22165
11: 00007FF63F15607F std::basic_ostream<char,std::char_traits<char> >::operator<<+80079
12: 00007FF63F154896 std::basic_ostream<char,std::char_traits<char> >::operator<<+73958
13: 00007FF63F29708B uv_async_send+331
14: 00007FF63F29681C uv_loop_init+1292
15: 00007FF63F2969BA uv_run+202
16: 00007FF63F265825 node::SpinEventLoop+309
17: 00007FF63F17CE83 v8::internal::Isolate::stack_guard+53827
18: 00007FF63F1FA40C node::Start+220
19: 00007FF63F01894C RC4_options+348236
20: 00007FF64007FE68 v8::internal::compiler::RepresentationChanger::Uint32OverflowOperatorFor+14472
21: 00007FF9B1D354E0 BaseThreadInitThunk+16
22: 00007FF9B360485B RtlUserThreadStart+43
PS C:\Users\user\Desktop\vite-project>

Validations

@gotjoshua
Copy link

i have nearly the same problem and wondering if anyone has a workaround in mind...

@Niputi Niputi added inconsistency Inconsistency between dev & build feat: web workers labels Mar 16, 2022
@gotjoshua
Copy link

gotjoshua commented Mar 16, 2022

I found a partial workaround to at least prevent the infinite loop and get a build output:

in vite.config.ts :

build: {
    commonjsOptions: {
      dynamicRequireTargets: [
        'src/MyWebWorker.ts',
      ],
    },
},
...

this avoids the loop during the transforming step, but does not transpile the webworker. rather it creates a single line file with

require("/Absolute/Pathto/src/MyWebWorker.ts");

@zxch3n
Copy link

zxch3n commented May 10, 2022

I have a simplified reproduction of this infinite build https://stackblitz.com/edit/vitejs-vite-oqqjnr?file=worker.js,main.js,package.json&terminal=dev

@hf02
Copy link
Author

hf02 commented May 10, 2022

I have a simplified reproduction of this infinite build https://stackblitz.com/edit/vitejs-vite-oqqjnr?file=worker.js,main.js,package.json&terminal=dev

Thanks for the much simpler reproduction. However, this may be a different bug? Instead of Vite showing transforming (1) worker.js and counting, it gets stuck on it.

I forked your project. using import() in worker.js instead. This fully reproduces the bug: https://stackblitz.com/edit/vitejs-vite-u59lcw?file=worker.js

@zxch3n
Copy link

zxch3n commented May 10, 2022

I forked your project. using import() in worker.js instead. This fully reproduces the bug: https://stackblitz.com/edit/vitejs-vite-u59lcw?file=worker.js

I guess they are the same under the hook after this change

Workers are detected and bundled when using `new URL('path', import.meta.url)`, replacing the need for the `?worker` suffix and aligning Vite with standard patterns. See [#6356](https://github.com/vitejs/vite/issues/6356). Instead of

@iamcco

This comment was marked as spam.

@Pyrolistical
Copy link

Pyrolistical commented Aug 18, 2022

I also ran into this while trying to create a single file typed web worker. https://stackblitz.com/edit/vitejs-vite-9zt7v2?file=src/worker.ts

It works in dev but goes into a infinite loop during build.

What I was trying to do is build something like https://nodejs.org/api/worker_threads.html, where the script for both the client and the worker can be in the same file.

This is desirable in TypeScript in order align the type of data passed into the worker from the client.

Before this gets resolved, I now have to split up my worker into multiple files.

@john-landgrave
Copy link

I am running into the same issue. This is particularly in a Vue project and my initial solve was to use inversion of control by having the module which was originally calling new Worker (let's call it useWorker.ts) have a configurable member that creates the worker. Basically, useWorker.ts exports a function called setWorkerDefinition which looks something like:

let ModuleWorkerDefinition;

export function setWorkerDefinition(workerDefinition: () => Worker) {
    ModuleWorkerDefinition = workerDefinition;
} 

So that when something needs to create a worker it calls a method, call it useWorker, that can use ModuleWorkerDefinition. Something like:

export function useWorker() {
   return ModuleWorkerDefinition();
}

And lastly the new Worker call is abstracted out into a separate module, call it defineWorker.ts:

// some import that causes your circular dependency issue because it in turn somewhere imports `useWorker.ts`
import { setWorkerDefinition } from '@/useWorker';

setWorkerDefinition(() => {
    return new Worker(/* worker stuff here  */);
})

This means that useWorker.ts doesn't have to import the definite of a worker (which, in my case, imports some other things that were causing the circular dependency since some of those things ultimately imported useWorker.ts). So then the last step was to get something to import defineWorker.ts so that it would register itself.

In Vue this was pretty easy. In the main.ts for the app I just added a import '@/defineWorker.ts'; which took care of everything (since nothing imports main.ts in my app and it will definitely always be called). The trouble is now I have a need to nest workers and I think that the only solution I can come to is to have two different "worker entry files" so that they shouldn't end up importing each other, but that still feels super brittle to me. Is there actually any hope of a real solution to this? Because at the end of the day it works fine in dev mode add just fails when it is being bundled, which tells me that there isn't actually a circular dependency to be concerned about.

@john-landgrave
Copy link

In talking through this with one of my teammates I think it makes sense why this is happening. Can someone confirm that this is how the bundler is working and that this logic makes sense? It seems to us that this is about the way that the bundler should be working:

  1. Start compiling the entry file
  2. Trace dependencies and build and start building an AST of the dependency network for the entry file
  3. When a worker import is encountered, start a sub-process at step 1 for that file
  4. Continue through the process from the "main entry file" until you are done.
  5. Either in a separate thread or after the "main entry file" is done, finish tracing dependencies and bundling for the worker file.

I understand that there is a lot more to the process here, but as a whiteboard explanation of the process, I think that this is pretty close to what it seems to be doing? If that is the case, then assuming that there is some process/memory isolation in step 3 it would make sense that the circular loop would case the cycle to repeat over and over until you run out of memory. However, it seems like a reasonable solution to essentially create a dictionary where the keys are the import paths and the values are the files that will ultimately be created so that you can effectively reuse the output of the sub-process spawned in step 3 at any import, even if that import is inside of the worker itself, right? Because in the end this is going to show up in the bundled, transpiled, minified code as new Worker('/some-worker.8675309.js'), right?

Is this something that it would even be possible to write a Vite/Rollup plugin for, or is this just too core to the way that those tools work?

@AceBear
Copy link

AceBear commented Nov 6, 2022

I had the same issue, and have found a workaround after attempting for several days. Hope this can help someone.

The key idea is forcing the vite bypassing new Worker/SharedWorker(...)

let scriptForWorker = "/path/to/myWorker.js"
const worker = new Worker(scriptForWorker, { type: 'module' })

The scriptForWorker is a true variable, so the vite have no idea about how to process it, and will just keep it as a simple string. And then, let rollup build the myWorker.js for us.

  1. modify vite.config, let rollup build 'myWorker.js'
  2. modify vite.config, let vite generate manifest.json
import { defineConfig } from 'vite';
export default defineConfig({
    build: {
        rollupOptions: {
            input: {
                main: "index.html",
                worker: "path/to/worker"
            }
        },
        manifest: true
    }
});
  1. modify the source code about new Worker(...)
let scriptForWorker = "path/to/worker.ts";
if(!import.meta.env.DEV){
    // in production, we get the js from manifest.json
    // in `npm run dev` mode, using orignal path directly
    const response = await fetch("/manifest.json");
    if(response.ok){
        const manifest = await response.json();
        scriptForWorker = manifest[scriptForWorker].file;
    }
    else{
        return Promise.reject(response.statusText);
    }
}

// create the Worker
const worker = new Worker(scriptForWorker, { type:'module' });
// or the SharedWorker
const sharedWorker = new SharedWorker(scriptForWorker, { type:'module' });
  1. building
npm run build
# or
npm run dev

@deluksic
Copy link

deluksic commented Feb 9, 2023

We had the exact same case (worker -> importing file -> importing same worker). However, instead of hanging, we got:

Unexpected early exit. This happens when Promises returned by plugins cannot resolve. Unfinished hook action(s) on exit:
...

@dkspec
Copy link

dkspec commented Apr 9, 2023

we also get this hang. any update?
Unexpected early exit. This happens when Promises returned by plugins cannot resolve. Unfinished hook action(s) on exit:

@lgarron
Copy link
Contributor

lgarron commented Oct 6, 2023

From the error logs, it seems that this happens from trying to bundle workers as CommonJS?

Would the error go away if worker constructor files were instead just treated as entry points for ESM bundling?
That's basically how Vite works in dev, and how I used to assume Vite built code as well.

I understand that some apps will want backwards compat through opt-in or opt-out, but all modern browsers and runtimes support module workers.

@jamsinclair
Copy link
Contributor

jamsinclair commented Nov 8, 2023

I believe for a while the problem was masked by the nested workers regression (#13367). You can see this in other developer outputs above. The error would look like:

Unexpected early exit. This happens when Promises returned by plugins cannot resolve. Unfinished hook action(s) on exit:

That issue was fixed in #14685 and released in v5.0.0-beta.11. The original reported issue is now present for nested workers and re-occuring from v5.0.0-beta.11.

After the next major release I think there will be an uptick in people reporting this hanging build issue as circular imports is a common pattern when working with nested workers (pun unintended) and often added automatically by dev tooling.

@kleisauke
Copy link

kleisauke commented Nov 8, 2023

This issue is still present in v5.0.0-beta.11. As mentioned in #14499 (comment), it can be circumvented by doing:

Details
import { defineConfig } from 'vite';

// https://github.com/vitejs/vite/blob/ec7ee22cf15bed05a6c55693ecbac27cfd615118/packages/vite/src/node/plugins/workerImportMetaUrl.ts#L127-L128
const workerImportMetaUrlRE =
    /\bnew\s+(?:Worker|SharedWorker)\s*\(\s*(new\s+URL\s*\(\s*('[^']+'|"[^"]+"|`[^`]+`)\s*,\s*import\.meta\.url\s*\))/g

// https://vitejs.dev/config/
export default defineConfig({
    build: {
        target: 'esnext',
    },
    server: {
        host: 'localhost',
        headers: {
            'Cross-Origin-Embedder-Policy': 'require-corp',
            'Cross-Origin-Opener-Policy': 'same-origin',
            'Cross-Origin-Resource-Policy': 'cross-origin'
        }
    },
    optimizeDeps: {
        esbuildOptions: {
            target: 'esnext'
        }
    },
    worker: {
        format: 'es',
        // https://github.com/vitejs/vite/issues/7015
        // https://github.com/vitejs/vite/issues/14499#issuecomment-1740267849
        plugins: () => [
            {
                name: 'Disable nested workers',
                enforce: 'pre',
                transform(code: string, id: string) {
                    if (code.includes('new Worker') && code.includes('new URL') && code.includes('import.meta.url')) {
                        return code.replace(workerImportMetaUrlRE, `((() => { throw new Error('Nested workers are disabled') })()`);
                    }
                }
            }
        ]
    }
});

Note that for Emscripten-generated code this would mean that the locateFile handler on the incoming module would have to be overridden to provide support for nested workers.

@jamsinclair
Copy link
Contributor

I'd like to second @lgarron's idea for not separately bundling module workers. Seems like it would simplify many things. No need to worry about nested workers, parallelized builds, circular-ish dependencies and separate worker plugins. Plus reduced code duplication as modules can be shared between main entry points and module workers.

Are there any obvious or hidden pitfalls that would make this unappealing? @patak-dev @sapphi-red

Some smaller ones that I can think of are:

  • Vite users might be heavily relying on plugins to augment code differently between workers and their main code
  • Vite would still need to keep current worker tooling for legacy support of non-module workers

@jamsinclair
Copy link
Contributor

jamsinclair commented Dec 4, 2023

I've attempted to create an experimental plugin that would make Vite chunk module workers instead of bundling. It seems to work for my use case and solves the circular dependency issue (Gist of plugin source).

There's a few caveats that showed up:

  • Only works for workers instantiated like new Worker(new URL('path', import.meta.url), type: { 'module' })
  • module preload will need to be disabled in your vite config. Otherwise preload code is injected into the worker which breaks it.
  • You need to be careful that the module that instantiates the worker does not bundle any code that includes Web APIs that are not supported by workers. As your worker will import that bundle and it could break.

There's likely other things that could break because the plugin simply tricks Vite into thinking the worker is a dynamic import of an ES module.

@simonbuehler
Copy link

for me it worked for opencv.js wasm workers with the config from #7015 (comment) , thanks a lot!

@CodeF53
Copy link

CodeF53 commented Dec 8, 2023

Fixing this may solve nuxt/nuxt#22966

@wcdeich4
Copy link

I'm having a similar problem. Simple web workers are fine, but any code that imports classes & instantiates a new object inside a web worker always fails.

@lgarron
Copy link
Contributor

lgarron commented Mar 6, 2024

While I appreciate a partial fix in #16103 , I'd like to note that that it does far from solving the issue in general.

Trying to run npx vite build using a build of eef9da1 on my repro from #14499 still fails the same way, unfortunately.

#16103 states that:

But I think it's fine because doing that is not popular and will make the code complex.

I appreciate that it might not be possible to fix the current situation super easily, but it's not a matter of popular conventions. Some of us don't have a choice about the recursive dynamic imports in our code, unless we want our code to fail in other bundlers. 😢

Would it be possible to reopen one of these issues to keep track of the general problem?

Thanks,
»Lucas

@sapphi-red
Copy link
Member

@lgarron

I'd like to note that that it does far from solving the issue in general.

I do think it solves most cases. I actually tested with all the repros I found and all of them worked (without throwing errors on build) as I stated in the PR. Your repro does not match the "complex case" condition.

By using the main branch (eef9da1) Vite and setting worker.format: 'es', the build of your repro (#14499) succeeds and the preview is working.

vite v5.1.5 building for production...
✓ 41 modules transformed.
dist/index.html                                                           0.45 kB │ gzip:   0.30 kB
dist/assets/chunk-KDMCYBSC-DJfxFAvj.js                                    1.56 kB  
dist/assets/twsearch-SLVE4NQH-CeABCLXd.js                                 2.04 kB  
dist/assets/search-worker-entry-Biyfh-f5.js                               4.81 kB  
dist/assets/search-dynamic-solve-sq1-INOYNRSJ-t49RGMrR.js                 7.77 kB  
dist/assets/search-dynamic-solve-kilominx-WREDL6AE-Ba_NcXDp.js            8.05 kB  
dist/assets/search-dynamic-solve-master_tetraminx-3D4MBF3V-DMwauRA8.js    8.12 kB  
dist/assets/search-dynamic-solve-fto-EY5ZVAGO-CWb6KctK.js                17.80 kB  
dist/assets/search-dynamic-sgs-unofficial-KTHSSINP-BR48LPsc.js           27.61 kB  
dist/assets/search-dynamic-solve-4x4x4-JQRNWKAG-BAd9vsD8.js              27.73 kB  
dist/assets/search-dynamic-sgs-side-events-KBQTGXZR-DA9PpCP1.js          31.42 kB  
dist/assets/index-XmOFflW_.js                                            70.31 kB  
dist/assets/inside-5CIAPTLP-DjKnNCQK.js                                  76.18 kB  
dist/assets/index-LDxwnHR4.css                                            1.24 kB │ gzip:   0.65 kB
dist/assets/inside-5CIAPTLP-BymCh4jE.js                                   0.10 kB │ gzip:   0.10 kB
dist/assets/search-worker-entry-BPdL309Z.js                               0.96 kB │ gzip:   0.55 kB
dist/assets/chunk-KDMCYBSC-DrFRfSNi.js                                    1.55 kB │ gzip:   0.71 kB
dist/assets/twsearch-SLVE4NQH-8_jTapat.js                                 2.21 kB │ gzip:   0.98 kB
dist/assets/search-dynamic-solve-sq1-INOYNRSJ-9KflgMA7.js                 7.72 kB │ gzip:   3.18 kB
dist/assets/search-dynamic-solve-kilominx-WREDL6AE-BWEa1P9Z.js            7.99 kB │ gzip:   3.28 kB
dist/assets/search-dynamic-solve-4x4x4-JQRNWKAG-BB_OirYQ.js              27.68 kB │ gzip:   9.62 kB
dist/assets/puzzles-dynamic-unofficial-WXH65MSQ-BfUzpykK.js              30.61 kB │ gzip:   3.85 kB
dist/assets/search-dynamic-sgs-side-events-KBQTGXZR-WehrTIpp.js          31.70 kB │ gzip:   6.59 kB
dist/assets/index-CvE7NQzx.js                                            70.25 kB │ gzip:  22.53 kB
dist/assets/index-BepD_N6A.js                                            90.43 kB │ gzip:  26.89 kB
dist/assets/puzzles-dynamic-side-events-EEMN2PI4-B1nZhrxY.js            118.69 kB │ gzip:  13.14 kB
dist/assets/twsearch-BDAXZGZU-Q2YC2EQ6-CCxkWTHd.js                      418.70 kB │ gzip: 166.31 kB
✓ built in 2.30s

image

If it doesn't work on your computer, there's probably something wrong with your self-built Vite. If not, maybe there's a bug that doesn't happen on my computer?

@lgarron
Copy link
Contributor

lgarron commented Mar 9, 2024

By using the main branch (eef9da1) Vite and setting worker.format: 'es', the build of your repro (#14499) succeeds and the preview is working.

That's reassuring to hear!

I tried it again, and I still can't get it to work — do you have more details on how to test?

This is what I'm doing:

# In a vite checkout:
pnpm i
pnpm run build
cd packages/vite
npm link

# In a project:
npm link vite

Regardless of what I try to put in vite.config.js, I now get:

> npx vite build src
vite v5.1.5 building for production...
✓ 33 modules transformed.
x Build failed in 622ms
error during build:
RollupError: [commonjs--resolver] Invalid value "iife" for option "output.format" - UMD and IIFE output formats are not supported for code-splitting builds.
file: /Users/lgarron/Downloads/fjlsdfjdsf/node_modules/cubing/dist/lib/cubing/chunks/chunk-44CBFEXI.js
    at error (file:///Users/lgarron/Code/git/github.com/vitejs/vite/node_modules/.pnpm/rollup@4.2.0/node_modules/rollup/dist/es/shared/parseAst.js:337:30)
    at validateOptionsForMultiChunkOutput (file:///Users/lgarron/Code/git/github.com/vitejs/vite/node_modules/.pnpm/rollup@4.2.0/node_modules/rollup/dist/es/shared/node-entry.js:16926:16)
    at Bundle.generate (file:///Users/lgarron/Code/git/github.com/vitejs/vite/node_modules/.pnpm/rollup@4.2.0/node_modules/rollup/dist/es/shared/node-entry.js:16819:17)
    at file:///Users/lgarron/Code/git/github.com/vitejs/vite/node_modules/.pnpm/rollup@4.2.0/node_modules/rollup/dist/es/shared/node-entry.js:19376:27
    at catchUnfinishedHookActions (file:///Users/lgarron/Code/git/github.com/vitejs/vite/node_modules/.pnpm/rollup@4.2.0/node_modules/rollup/dist/es/shared/node-entry.js:18809:16)
    at bundleWorkerEntry (file:///Users/lgarron/Code/git/github.com/vitejs/vite/packages/vite/dist/node/chunks/dep-bykU6hf7.js:49118:61)
    at workerFileToUrl (file:///Users/lgarron/Code/git/github.com/vitejs/vite/packages/vite/dist/node/chunks/dep-bykU6hf7.js:49172:29)
    at Object.transform (file:///Users/lgarron/Code/git/github.com/vitejs/vite/packages/vite/dist/node/chunks/dep-bykU6hf7.js:49641:40)
    at transform (file:///Users/lgarron/Code/git/github.com/vitejs/vite/node_modules/.pnpm/rollup@4.2.0/node_modules/rollup/dist/es/shared/node-entry.js:17368:16)
    at ModuleLoader.addModuleSource (file:///Users/lgarron/Code/git/github.com/vitejs/vite/node_modules/.pnpm/rollup@4.2.0/node_modules/rollup/dist/es/shared/node-entry.js:17580:36)

@lgarron
Copy link
Contributor

lgarron commented Mar 9, 2024

Aha! I forgot that the vite.config.js file needs to be in the src folder, not the project root! It works with:

export default {
  worker: {
    format: "es"
  }
}

🤩🤩🤩

This is fantastic to see, but unfortunately it does mean people using our library will still get a confusing error out of the box.
Given that ESM is the default output for the main bundles, would it be possible to default the workers to ESM as well? I would find that much more intuitive, and it could allow significant code deduplication for some use cases.

@sapphi-red
Copy link
Member

would it be possible to default the workers to ESM as well?

We won't be able to do that for now. ESM workers are not supported by browsers we specify as the default value of build.target.

@wcdeich4
Copy link

would it be possible to default the workers to ESM as well?

We won't be able to do that for now. ESM workers are not supported by browsers we specify as the default value of build.target.

what about typescript?

@github-actions github-actions bot locked and limited conversation to collaborators Mar 27, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet