vite
vite copied to clipboard
Build fails when Web Worker dynamically imports module also dynamically imported by the main thread
Describe the bug
I have created a Web Worker with type: module that dynamically imports a module shared with the main thread. In dev mode this works as expected, but when building I get (full logs below)
rendering chunks (2)...The emitted file "assets/logger.c9021ab8.js" overwrites a previously emitted file of the same name.
[vite:build-import-analysis] Cannot read property 'importedCss' of undefined
Reproduction
git clone https://github.com/esturcke/web-worker-dynamic-import-error
cd web-worker-dynamic-import-error
yarn && yarn build
System Info
System:
OS: macOS 12.5.1
CPU: (10) x64 Apple M1 Pro
Memory: 33.20 MB / 16.00 GB
Shell: 5.8.1 - /bin/zsh
Binaries:
Node: 14.19.1 - ~/Library/Caches/fnm_multishells/39357_1662750145123/bin/node
Yarn: 1.22.19 - /opt/homebrew/bin/yarn
npm: 6.14.16 - ~/Library/Caches/fnm_multishells/39357_1662750145123/bin/npm
Watchman: 2022.07.04.00 - /opt/homebrew/bin/watchman
Browsers:
Brave Browser: 102.1.39.122
Chrome: 105.0.5195.102
Chrome Canary: 107.0.5290.0
Edge: 105.0.1343.33
Firefox Developer Edition: 105.0
Safari: 15.6.1
Safari Technology Preview: 16.0
npmPackages:
vite: ^3.1.0 => 3.1.0
Used Package Manager
yarn
Logs
Click to expand!
❯ yarn build --debug
yarn run v1.22.19
$ tsc && vite build --debug
vite:config bundled config file loaded in 85.98ms +0ms
vite:esbuild init tsconfck (root: /Users/esturcke/work/web-worker-dynamic-import-error) +0ms
vite:esbuild init tsconfck (root: /Users/esturcke/work/web-worker-dynamic-import-error) +1ms
vite:esbuild init tsconfck (root: /Users/esturcke/work/web-worker-dynamic-import-error) +1ms
vite:esbuild init tsconfck (root: /Users/esturcke/work/web-worker-dynamic-import-error) +0ms
vite:esbuild init tsconfck end +1ms
vite:esbuild init tsconfck end +0ms
vite:esbuild init tsconfck end +0ms
vite:esbuild init tsconfck end +0ms
vite:config using resolved config: {
vite:config worker: {
vite:config format: 'es',
vite:config plugins: [
vite:config 'vite:build-metadata',
vite:config 'vite:pre-alias',
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-helper',
vite:config 'vite:worker',
vite:config 'vite:asset',
vite:config 'vite:wasm-fallback',
vite:config 'vite:define',
vite:config 'vite:css-post',
vite:config 'vite:build-html',
vite:config 'vite:worker-import-meta-url',
vite:config 'vite:force-systemjs-wrap-complete',
vite:config 'vite:watch-package-data',
vite:config 'commonjs',
vite:config 'vite:data-uri',
vite:config 'vite:asset-import-meta-url',
vite:config 'vite:dynamic-import-vars',
vite:config 'vite:import-glob',
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 rollupOptions: {},
vite:config getSortedPlugins: [Function: getSortedPlugins],
vite:config getSortedPluginHooks: [Function: getSortedPluginHooks]
vite:config },
vite:config optimizeDeps: {
vite:config disabled: 'build',
vite:config force: undefined,
vite:config esbuildOptions: { preserveSymlinks: undefined }
vite:config },
vite:config build: {
vite:config target: [ 'es2020', 'edge88', 'firefox78', 'chrome87', 'safari13' ],
vite:config polyfillModulePreload: true,
vite:config outDir: 'dist',
vite:config assetsDir: 'assets',
vite:config assetsInlineLimit: 4096,
vite:config cssCodeSplit: true,
vite:config cssTarget: [ 'es2020', 'edge88', 'firefox78', 'chrome87', 'safari13' ],
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 configFile: '/Users/esturcke/work/web-worker-dynamic-import-error/vite.config.ts',
vite:config configFileDependencies: [
vite:config '/Users/esturcke/work/web-worker-dynamic-import-error/vite.config.ts'
vite:config ],
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 optimizeDeps: { force: undefined },
vite:config build: {}
vite:config },
vite:config root: '/Users/esturcke/work/web-worker-dynamic-import-error',
vite:config base: '/',
vite:config resolve: { alias: [ [Object], [Object] ] },
vite:config publicDir: '/Users/esturcke/work/web-worker-dynamic-import-error/public',
vite:config cacheDir: '/Users/esturcke/work/web-worker-dynamic-import-error/node_modules/.vite',
vite:config command: 'build',
vite:config mode: 'production',
vite:config ssr: {
vite:config format: 'esm',
vite:config target: 'node',
vite:config optimizeDeps: { disabled: true, esbuildOptions: [Object] }
vite:config },
vite:config isWorker: false,
vite:config mainConfig: null,
vite:config isProduction: true,
vite:config plugins: [
vite:config 'vite:build-metadata',
vite:config 'vite:pre-alias',
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-helper',
vite:config 'vite:worker',
vite:config 'vite:asset',
vite:config 'vite:wasm-fallback',
vite:config 'vite:define',
vite:config 'vite:css-post',
vite:config 'vite:build-html',
vite:config 'vite:worker-import-meta-url',
vite:config 'vite:force-systemjs-wrap-complete',
vite:config 'vite:watch-package-data',
vite:config 'commonjs',
vite:config 'vite:data-uri',
vite:config 'vite:asset-import-meta-url',
vite:config 'vite:dynamic-import-vars',
vite:config 'vite:import-glob',
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 middlewareMode: false,
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 appType: 'spa',
vite:config experimental: { importGlobRestoreExtension: false, hmrPartialAccept: false },
vite:config getSortedPlugins: [Function: getSortedPlugins],
vite:config getSortedPluginHooks: [Function: getSortedPluginHooks]
vite:config } +13ms
vite v3.1.0 building for production...
✓ 2 modules transformed.
✓ 8 modules transformed.
rendering chunks (2)...The emitted file "assets/logger.c9021ab8.js" overwrites a previously emitted file of the same name.
[vite:build-import-analysis] Cannot read property 'importedCss' of undefined
error during build:
TypeError: Cannot read property 'importedCss' of undefined
at addDeps (file:///Users/esturcke/work/web-worker-dynamic-import-error/node_modules/vite/dist/node/chunks/dep-665b0112.js:43002:60)
at Object.generateBundle (file:///Users/esturcke/work/web-worker-dynamic-import-error/node_modules/vite/dist/node/chunks/dep-665b0112.js:43024:33)
at file:///Users/esturcke/work/web-worker-dynamic-import-error/node_modules/rollup/dist/es/shared/rollup.js:22710:40
at processTicksAndRejections (internal/process/task_queues.js:95:5)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
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 reports the same bug to avoid creating a duplicate.
- [X] Make sure this is a Vite issue and not a framework-specific issue. For example, if it's a Vue SFC related bug, it should likely be reported to vuejs/core instead.
- [X] Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
- [X] The provided reproduction is a minimal reproducible example of the bug.
For a workaround, add a module that re-exports everything from logger.ts and use it instead in worker.
// logger2.ts
export * from './logger'
// worker.ts
onmessage = e => {
import("./logger2").then(({ log }: any) => log(`worker: ${e.data}`)) // use logger2
}
export {}
Thanks @sapphi-red, this looks like a nice workaround for direct imports. Unfortunately I ran into this while porting a project from Webpack to Vite and there are multiple dynamic imports brought in indirectly several levels deep. I'm not sure how feasible it will be to fork the entire call chain.
Update: I was able to get it to work with the workaround. Thanks!
Also struggling with this. In my case I'm not sure how to apply the workaround. My worker is a tiny wrapper around a class.
// Worker.ts
import { MyClass } from './MyClass'
import { expose } from 'comlink'
expose(MyClass)
MyClass is sometimes used within a worker, sometimes directly, depending on some settings.
Inside MyClass I make a dynamic import to a JS module, and since that is an implementation detail of MyClass, and not something I do directly in the worker, I'm not sure how to apply the workaround.
@esturcke It sounds similar to your case. Could you shed any light on your approach?
Interestingly, when using worker that requires the vite react plugin both the main app & the worker i don't get any of these errors and just see that all the dependencies have been bundled twice. Once for the use inside the worker and once in the main thread. This is the same result when using the workaround of reexporting the module suggested by @sapphi-red.
Even though this works, it increases the bundle size considerably in my case because both react and a large lib i.e. @react-pdf/renderer is getting bundled twice.