vitejs / vite

Next generation frontend tooling. It's fast!
http://vite.dev
MIT License
68.56k stars 6.19k forks source link

Vite SSR Imports not loading classes correctly - constructors not loaded #14048

Open lib-eramen opened 1 year ago

lib-eramen commented 1 year ago

Describe the bug

I'm trying to use a class in a Vite + SvelteKit project with TypeScript enabled. However, when I try to use a class and construct it in other places, while IntelliSense/LSPs don't throw any errors, when building/developing, the following error is outputted:

11:00:08 AM [vite] Error when evaluating SSR module /src/lib/core/games/chess/chess.ts:
|- TypeError: __vite_ssr_import_0__.GameMetadata is not a constructor
    at eval (/home/ramendev/projects/just-games/src/lib/core/games/chess/chess.ts:5:15)
    at async instantiateModule (file:///home/ramendev/projects/just-games/node_modules/vite/dist/node/chunks/dep-df561101.js:55974:9)

*other errors caused when importing the chess.ts file*

11:00:08 AM [vite] Error when evaluating SSR module /src/routes/+page.svelte: failed to import "/src/lib/components/games/GamesCarousel.svelte"
|- TypeError: __vite_ssr_import_0__.GameMetadata is not a constructor
    at eval (/home/ramendev/projects/just-games/src/lib/core/games/chess/chess.ts:5:15)
    at async instantiateModule (file:///home/ramendev/projects/just-games/node_modules/vite/dist/node/chunks/dep-df561101.js:55974:9)

Internal server error: __vite_ssr_import_0__.GameMetadata is not a constructor
      at eval (/home/ramendev/projects/just-games/src/lib/core/games/chess/chess.ts:5:15)
      at async instantiateModule (file:///home/ramendev/projects/just-games/node_modules/vite/dist/node/chunks/dep-df561101.js:55974:9)
TypeError: __vite_ssr_import_0__.GameMetadata is not a constructor
    at eval (/home/ramendev/projects/just-games/src/lib/core/games/chess/chess.ts:5:15)
    at async instantiateModule (file:///home/ramendev/projects/just-games/node_modules/vite/dist/node/chunks/dep-df561101.js:55974:9)

The class in question is defined as follows: src/lib/core/games.ts

export class GameMetadata {
    name: string;
    aka: string;
    description: string;
    jpName: string;

    constructor(name: string, aka: string, description: string, jpName: string) {
        this.name = name;
        this.aka = aka;
        this.description = description;
        this.jpName = jpName;
    }

src/lib/core/games/chess/chess.ts

import { GameMetadata } from "../../game";

export const chess = new GameMetadata(
    "chess",
    '...',
    "...",
    "西洋将棋"
);

Reproduction

https://github.com/developer-ramen/just-games

Steps to reproduce

Clone the repo, followed by npm install and npm run dev

System Info

System:
    OS: Linux 5.15 Ubuntu 22.04.2 LTS 22.04.2 LTS (Jammy Jellyfish)
    CPU: (8) x64 Intel(R) Core(TM) i7-8665U CPU @ 1.90GHz
    Memory: 5.39 GB / 7.67 GB
    Container: Yes
    Shell: 5.8.1 - /usr/bin/zsh
  Binaries:
    Node: 18.17.0 - /usr/local/bin/node
    npm: 9.6.7 - /usr/local/bin/npm
  npmPackages:
    vite: ^4.4.2 => 4.4.9

Used Package Manager

npm

Logs

Logs from runnning `vite-build-debug` ```shell vite:config bundled config file loaded in 675.06ms +0ms vite:vite-plugin-svelte adding bare svelte packages to optimizeDeps.include: svelte/animate, svelte/easing, svelte/internal, svelte/motion, svelte/store, svelte/transition, svelte, svelte/internal/disclose-version +0ms vite:vite-plugin-svelte extra config for dependencies generated by vitefu { optimizeDeps: { include: [], exclude: [] }, ssr: { noExternal: [], external: [] } } +5ms vite:vite-plugin-svelte post-processed extra config for dependencies { optimizeDeps: { include: [], exclude: [] }, ssr: { noExternal: [], external: [] } } +1ms vite:vite-plugin-svelte enabling "experimental.hmrPartialAccept" in vite config +1ms vite:vite-plugin-svelte additional vite config { resolve: { dedupe: [ 'svelte/animate', 'svelte/easing', 'svelte/internal', 'svelte/motion', 'svelte/ssr', 'svelte/store', 'svelte/transition', 'svelte', 'svelte/internal/disclose-version', 'svelte-hmr/runtime/hot-api-esm.js', 'svelte-hmr/runtime/proxy-adapter-dom.js', 'svelte-hmr' ], conditions: [ 'svelte' ] }, optimizeDeps: { include: [ 'svelte/animate', 'svelte/easing', 'svelte/internal', 'svelte/motion', 'svelte/store', 'svelte/transition', 'svelte', 'svelte/internal/disclose-version' ], exclude: [ 'svelte-hmr' ] }, ssr: { external: [], noExternal: [ 'svelte', /^svelte\// ] }, experimental: { hmrPartialAccept: true } } +0ms vite:vite-plugin-svelte resolved options { hot: false, compilerOptions: { css: 'external', dev: false, hydratable: true }, extensions: [ '.svelte' ], emitCss: true, prebundleSvelteLibraries: false, configFile: false, preprocess: [ { markup: [AsyncFunction: markup], script: [AsyncFunction: script], style: [AsyncFunction: style] }, { script: [Function: script], markup: [Function: markup] } ], onwarn: undefined, root: '/home/ramendev/projects/just-games', isBuild: true, isServe: false, isDebug: true, isProduction: true, stats: VitePluginSvelteStats {} } +53ms vite:config using resolved config: { vite:config plugins: [ vite:config 'vite:optimized-deps-build', vite:config 'vite:build-metadata', vite:config 'vite:watch-package-data', vite:config 'vite:pre-alias', vite:config 'alias', vite:config 'vite-plugin-svelte', 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-plugin-sveltekit-setup', vite:config 'vite-plugin-sveltekit-virtual-modules', vite:config 'vite-plugin-sveltekit-guard', vite:config 'vite-plugin-sveltekit-compile', 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:asset-import-meta-url', vite:config 'vite:force-systemjs-wrap-complete', vite:config 'commonjs', vite:config 'vite:data-uri', 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:manifest', vite:config 'vite:reporter', vite:config 'vite:load-fallback' vite:config ], vite:config test: { include: [ 'src/**/*.{test,spec}.{js,ts}' ] }, vite:config optimizeDeps: { vite:config disabled: false, vite:config include: [ vite:config 'svelte/animate', vite:config 'svelte/easing', vite:config 'svelte/internal', vite:config 'svelte/motion', vite:config 'svelte/store', vite:config 'svelte/transition', vite:config 'svelte', vite:config 'svelte/internal/disclose-version' vite:config ], vite:config exclude: [ 'svelte-hmr', '@sveltejs/kit', '$app', '$env' ], vite:config esbuildOptions: { preserveSymlinks: false } vite:config }, vite:config build: { vite:config target: 'node16.14', vite:config cssTarget: 'node16.14', vite:config outDir: '/home/ramendev/projects/just-games/.svelte-kit/output/server', vite:config assetsDir: 'assets', vite:config assetsInlineLimit: 4096, vite:config cssCodeSplit: true, vite:config sourcemap: false, vite:config rollupOptions: { vite:config input: [Object], vite:config output: [Object], vite:config preserveEntrySignatures: 'strict' vite:config }, vite:config minify: false, vite:config terserOptions: {}, vite:config write: true, vite:config emptyOutDir: null, vite:config copyPublicDir: false, vite:config manifest: 'vite-manifest.json', vite:config lib: false, vite:config ssr: true, vite:config ssrManifest: false, vite:config ssrEmitAssets: true, vite:config reportCompressedSize: true, vite:config chunkSizeWarningLimit: 500, vite:config watch: null, vite:config cssMinify: true, vite:config commonjsOptions: { include: [Array], extensions: [Array] }, vite:config dynamicImportVarsOptions: { warnOnError: true, exclude: [Array] }, vite:config modulePreload: { polyfill: true } vite:config }, vite:config resolve: { vite:config mainFields: [ 'svelte', 'module', 'jsnext:main', 'jsnext' ], vite:config browserField: true, vite:config conditions: [ 'svelte' ], vite:config extensions: [ vite:config '.mjs', '.js', vite:config '.mts', '.ts', vite:config '.jsx', '.tsx', vite:config '.json' vite:config ], vite:config dedupe: [ vite:config 'svelte/animate', vite:config 'svelte/easing', vite:config 'svelte/internal', vite:config 'svelte/motion', vite:config 'svelte/ssr', vite:config 'svelte/store', vite:config 'svelte/transition', vite:config 'svelte', vite:config 'svelte/internal/disclose-version', vite:config 'svelte-hmr/runtime/hot-api-esm.js', vite:config 'svelte-hmr/runtime/proxy-adapter-dom.js', vite:config 'svelte-hmr' vite:config ], vite:config preserveSymlinks: false, vite:config alias: [ [Object], [Object], [Object], [Object], [Object] ] vite:config }, vite:config ssr: { vite:config format: 'esm', vite:config target: 'node', vite:config external: [], vite:config noExternal: [ 'svelte', /^svelte\//, 'esm-env', '@sveltejs/kit' ], vite:config optimizeDeps: { disabled: true, esbuildOptions: [Object] } vite:config }, vite:config experimental: { importGlobRestoreExtension: false, hmrPartialAccept: true }, vite:config root: '/home/ramendev/projects/just-games', vite:config server: { vite:config preTransformRequests: true, vite:config cors: { preflightContinue: true }, vite:config fs: { strict: true, allow: [Array], deny: [Array] }, vite:config sourcemapIgnoreList: [Function: sourcemapIgnoreList], vite:config watch: { ignored: [Array] }, vite:config middlewareMode: false 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: { preflightContinue: true }, vite:config headers: undefined vite:config }, vite:config define: { vite:config __SVELTEKIT_ADAPTER_NAME__: '"@sveltejs/adapter-netlify"', vite:config __SVELTEKIT_APP_VERSION_FILE__: '"_app/version.json"', vite:config __SVELTEKIT_APP_VERSION_POLL_INTERVAL__: '0', vite:config __SVELTEKIT_DEV__: 'false', vite:config __SVELTEKIT_EMBEDDED__: 'false' vite:config }, vite:config base: '/', vite:config publicDir: '/home/ramendev/projects/just-games/static', vite:config worker: { vite:config format: 'iife', vite:config plugins: [ vite:config 'vite:optimized-deps-build', vite:config 'vite:build-metadata', vite:config 'vite:watch-package-data', 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:asset-import-meta-url', vite:config 'vite:force-systemjs-wrap-complete', vite:config 'commonjs', vite:config 'vite:data-uri', vite:config 'vite:worker-post', 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:load-fallback' vite:config ], vite:config rollupOptions: { output: [Object] }, vite:config getSortedPlugins: [Function: getSortedPlugins], vite:config getSortedPluginHooks: [Function: getSortedPluginHooks] vite:config }, vite:config configFile: '/home/ramendev/projects/just-games/vite.config.ts', vite:config configFileDependencies: [ '/home/ramendev/projects/just-games/vite.config.ts' ], 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 rawBase: '/', vite:config cacheDir: '/home/ramendev/projects/just-games/node_modules/.vite', vite:config command: 'build', vite:config mode: 'production', vite:config isWorker: false, vite:config mainConfig: null, vite:config isProduction: true, vite:config css: undefined, vite:config esbuild: { jsxDev: false }, vite:config envDir: '/home/ramendev/projects/just-games', vite:config env: { BASE_URL: '/', MODE: 'production', DEV: false, PROD: true }, vite:config assetsInclude: [Function: assetsInclude], vite:config logger: { vite:config hasWarned: true, 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(1) { vite:config 'fnpd_/home/ramendev/projects/just-games' => { vite:config dir: '/home/ramendev/projects/just-games', vite:config data: [Object], vite:config hasSideEffects: [Function: hasSideEffects], vite:config webResolvedImports: {}, vite:config nodeResolvedImports: {}, vite:config setResolvedCache: [Function: setResolvedCache], vite:config getResolvedCache: [Function: getResolvedCache] vite:config }, vite:config set: [Function (anonymous)] vite:config }, vite:config createResolver: [Function: createResolver], vite:config appType: 'spa', vite:config getSortedPlugins: [Function: getSortedPlugins], vite:config getSortedPluginHooks: [Function: getSortedPluginHooks] vite:config } +77ms vite v4.4.9 building SSR bundle for production... transforming (1) node_modules/@sveltejs/kit/src/runtime/server/index.js vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/routes/+layout.svelte +122ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/routes/+error.svelte +280ms vite:vite-plugin-svelte resolveId resolved virtual css module /home/ramendev/projects/just-games/src/routes/+error.svelte?svelte&type=style&lang.css +6ms vite:vite-plugin-svelte load returns css for /home/ramendev/projects/just-games/src/routes/+error.svelte +1ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/routes/+page.svelte +21ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/routes/games/+page.svelte +12ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/routes/login/+page.svelte +23ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/routes/signup/+page.svelte +10ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/routes/resources/+page.svelte +31ms transforming (11) src/routes/resources/+page.svelte vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/routes/about/+page.svelte +8ms vite:esbuild 537.78ms tsconfck init /home/ramendev/projects/just-games +0ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/lib/components/NavBar.svelte +130ms vite:vite-plugin-svelte resolveId resolved virtual css module /home/ramendev/projects/just-games/src/lib/components/NavBar.svelte?svelte&type=style&lang.css +8ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/lib/components/Footer.svelte +31ms vite:vite-plugin-svelte resolveId resolved virtual css module /home/ramendev/projects/just-games/src/lib/components/Footer.svelte?svelte&type=style&lang.css +3ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/.svelte-kit/generated/root.svelte +70ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/lib/components/home/GamePageButton.svelte +75ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/lib/components/games/GamesCarousel.svelte +52ms vite:vite-plugin-svelte resolveId resolved virtual css module /home/ramendev/projects/just-games/src/lib/components/games/GamesCarousel.svelte?svelte&type=style&lang.css +5ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/lib/components/home/HomeBanner.svelte +11ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/lib/components/games/GamesContent.svelte +24ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/lib/components/WipBanner.svelte +20ms vite:vite-plugin-svelte resolveId resolved virtual css module /home/ramendev/projects/just-games/src/lib/components/WipBanner.svelte?svelte&type=style&lang.css +5ms transforming (26) node_modules/@sveltejs/kit/src/runtime/server/endpoint.js vite:vite-plugin-svelte load returns css for /home/ramendev/projects/just-games/src/lib/components/NavBar.svelte +188ms vite:vite-plugin-svelte load returns css for /home/ramendev/projects/just-games/src/lib/components/Footer.svelte +5ms vite:vite-plugin-svelte load returns css for /home/ramendev/projects/just-games/src/lib/components/games/GamesCarousel.svelte +33ms transforming (45) node_modules/svelte/src/runtime/internal/dom.js vite:vite-plugin-svelte load returns css for /home/ramendev/projects/just-games/src/lib/components/WipBanner.svelte +109ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/lib/components/NameLabel.svelte +168ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/lib/components/NavButton.svelte +45ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/lib/components/games/CarouselGameItem.svelte +28ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/lib/components/games/GameCarouselHelpText.svelte +28ms vite:vite-plugin-svelte resolveId resolved virtual css module /home/ramendev/projects/just-games/src/lib/components/games/GameCarouselHelpText.svelte?svelte&type=style&lang.css +1ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/lib/components/games/search/GoogleImitationTitle.svelte +378ms transforming (65) src/lib/components/games/search/GoogleImitationTitle.svelte vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/lib/components/games/search/GoogleBannerImitation.svelte +30ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/lib/components/games/search/SearchSection.svelte +25ms vite:vite-plugin-svelte load returns css for /home/ramendev/projects/just-games/src/lib/components/games/GameCarouselHelpText.svelte +3ms transforming (83) node_modules/svelte/src/shared/utils/names.js vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/lib/components/games/search/SearchBar.svelte +434ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/lib/components/games/search/SearchResults.svelte +41ms transforming (100) src/lib/core/game.ts vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/lib/components/games/search/SearchResult.svelte +190ms "slice" is imported from external module "lodash" but never used in "src/lib/components/games/search/GoogleBannerImitation.svelte", "src/lib/core/game.ts", "src/lib/components/games/GamesCarousel.svelte" and "src/routes/+error.svelte". ✓ 109 modules transformed. vite:vite-plugin-svelte:stats ssr compile done. vite:vite-plugin-svelte:stats package files time avg vite:vite-plugin-svelte:stats svelte-games 26 0.36s 13.7ms +0ms vite:config bundled config file loaded in 17.58ms +3s vite:vite-plugin-svelte adding bare svelte packages to optimizeDeps.include: svelte/animate, svelte/easing, svelte/internal, svelte/motion, svelte/store, svelte/transition, svelte, svelte/internal/disclose-version +534ms vite:vite-plugin-svelte extra config for dependencies generated by vitefu { optimizeDeps: { include: [], exclude: [] }, ssr: { noExternal: [], external: [] } } +3ms vite:vite-plugin-svelte post-processed extra config for dependencies { optimizeDeps: { include: [], exclude: [] }, ssr: { noExternal: [], external: [] } } +1ms vite:vite-plugin-svelte enabling "experimental.hmrPartialAccept" in vite config +0ms vite:vite-plugin-svelte additional vite config { resolve: { dedupe: [ 'svelte/animate', 'svelte/easing', 'svelte/internal', 'svelte/motion', 'svelte/ssr', 'svelte/store', 'svelte/transition', 'svelte', 'svelte/internal/disclose-version', 'svelte-hmr/runtime/hot-api-esm.js', 'svelte-hmr/runtime/proxy-adapter-dom.js', 'svelte-hmr' ], conditions: [ 'svelte' ] }, optimizeDeps: { include: [ 'svelte/animate', 'svelte/easing', 'svelte/internal', 'svelte/motion', 'svelte/store', 'svelte/transition', 'svelte', 'svelte/internal/disclose-version' ], exclude: [ 'svelte-hmr' ] }, ssr: { external: [], noExternal: [ 'svelte', /^svelte\// ] }, experimental: { hmrPartialAccept: true } } +0ms vite:vite-plugin-svelte resolved options { hot: false, compilerOptions: { css: 'external', dev: false, hydratable: true }, extensions: [ '.svelte' ], emitCss: true, prebundleSvelteLibraries: false, configFile: false, preprocess: [ { markup: [AsyncFunction: markup], script: [AsyncFunction: script], style: [AsyncFunction: style] }, { script: [Function: script], markup: [Function: markup] } ], onwarn: undefined, root: '/home/ramendev/projects/just-games', isBuild: true, isServe: false, isDebug: true, isProduction: true, stats: VitePluginSvelteStats {} } +6ms vite:config using resolved config: { vite:config plugins: [ vite:config 'vite:optimized-deps-build', vite:config 'vite:build-metadata', vite:config 'vite:watch-package-data', vite:config 'vite:pre-alias', vite:config 'alias', vite:config 'vite-plugin-svelte', 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-plugin-sveltekit-setup', vite:config 'vite-plugin-sveltekit-virtual-modules', vite:config 'vite-plugin-sveltekit-guard', vite:config 'vite-plugin-sveltekit-compile', 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:asset-import-meta-url', vite:config 'vite:force-systemjs-wrap-complete', vite:config 'commonjs', vite:config 'vite:data-uri', 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:manifest', vite:config 'vite:reporter', vite:config 'vite:load-fallback' vite:config ], vite:config test: { include: [ 'src/**/*.{test,spec}.{js,ts}' ] }, vite:config optimizeDeps: { vite:config disabled: false, vite:config include: [ vite:config 'svelte/animate', vite:config 'svelte/easing', vite:config 'svelte/internal', vite:config 'svelte/motion', vite:config 'svelte/store', vite:config 'svelte/transition', vite:config 'svelte', vite:config 'svelte/internal/disclose-version' vite:config ], vite:config exclude: [ 'svelte-hmr', '@sveltejs/kit', '$app', '$env' ], vite:config esbuildOptions: { preserveSymlinks: false } vite:config }, vite:config configFile: '/home/ramendev/projects/just-games/vite.config.ts', vite:config mode: 'production', vite:config build: { vite:config target: [ 'es2020', 'edge88', 'firefox78', 'chrome87', 'safari14' ], vite:config cssTarget: [ 'es2020', 'edge88', 'firefox78', 'chrome87', 'safari14' ], vite:config outDir: '/home/ramendev/projects/just-games/.svelte-kit/output/client', vite:config assetsDir: 'assets', vite:config assetsInlineLimit: 4096, vite:config cssCodeSplit: true, vite:config sourcemap: false, vite:config rollupOptions: { vite:config input: [Object], vite:config output: [Object], vite:config preserveEntrySignatures: 'strict' vite:config }, vite:config minify: 'esbuild', vite:config terserOptions: {}, vite:config write: true, vite:config emptyOutDir: null, vite:config copyPublicDir: true, vite:config manifest: 'vite-manifest.json', vite:config lib: false, vite:config ssr: false, vite:config ssrManifest: false, vite:config ssrEmitAssets: true, vite:config reportCompressedSize: true, vite:config chunkSizeWarningLimit: 500, vite:config watch: null, vite:config cssMinify: true, vite:config commonjsOptions: { include: [Array], extensions: [Array] }, vite:config dynamicImportVarsOptions: { warnOnError: true, exclude: [Array] }, vite:config modulePreload: { polyfill: true } vite:config }, vite:config resolve: { vite:config mainFields: [ 'svelte', 'module', 'jsnext:main', 'jsnext' ], vite:config browserField: true, vite:config conditions: [ 'svelte' ], vite:config extensions: [ vite:config '.mjs', '.js', vite:config '.mts', '.ts', vite:config '.jsx', '.tsx', vite:config '.json' vite:config ], vite:config dedupe: [ vite:config 'svelte/animate', vite:config 'svelte/easing', vite:config 'svelte/internal', vite:config 'svelte/motion', vite:config 'svelte/ssr', vite:config 'svelte/store', vite:config 'svelte/transition', vite:config 'svelte', vite:config 'svelte/internal/disclose-version', vite:config 'svelte-hmr/runtime/hot-api-esm.js', vite:config 'svelte-hmr/runtime/proxy-adapter-dom.js', vite:config 'svelte-hmr' vite:config ], vite:config preserveSymlinks: false, vite:config alias: [ [Object], [Object], [Object], [Object], [Object] ] vite:config }, vite:config ssr: { vite:config format: 'esm', vite:config target: 'node', vite:config external: [], vite:config noExternal: [ 'svelte', /^svelte\//, 'esm-env', '@sveltejs/kit' ], vite:config optimizeDeps: { disabled: true, esbuildOptions: [Object] } vite:config }, vite:config experimental: { importGlobRestoreExtension: false, hmrPartialAccept: true }, vite:config root: '/home/ramendev/projects/just-games', vite:config server: { vite:config preTransformRequests: true, vite:config cors: { preflightContinue: true }, vite:config fs: { strict: true, allow: [Array], deny: [Array] }, vite:config sourcemapIgnoreList: [Function: sourcemapIgnoreList], vite:config watch: { ignored: [Array] }, vite:config middlewareMode: false 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: { preflightContinue: true }, vite:config headers: undefined vite:config }, vite:config define: { vite:config __SVELTEKIT_ADAPTER_NAME__: '"@sveltejs/adapter-netlify"', vite:config __SVELTEKIT_APP_VERSION_FILE__: '"_app/version.json"', vite:config __SVELTEKIT_APP_VERSION_POLL_INTERVAL__: '0', vite:config __SVELTEKIT_DEV__: 'false', vite:config __SVELTEKIT_EMBEDDED__: 'false' vite:config }, vite:config base: './', vite:config publicDir: '/home/ramendev/projects/just-games/static', vite:config worker: { vite:config format: 'iife', vite:config plugins: [ vite:config 'vite:optimized-deps-build', vite:config 'vite:build-metadata', vite:config 'vite:watch-package-data', 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:asset-import-meta-url', vite:config 'vite:force-systemjs-wrap-complete', vite:config 'commonjs', vite:config 'vite:data-uri', vite:config 'vite:worker-post', 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:load-fallback' vite:config ], vite:config rollupOptions: { output: [Object] }, vite:config getSortedPlugins: [Function: getSortedPlugins], vite:config getSortedPluginHooks: [Function: getSortedPluginHooks] vite:config }, vite:config configFileDependencies: [ '/home/ramendev/projects/just-games/vite.config.ts' ], vite:config inlineConfig: { vite:config configFile: '/home/ramendev/projects/just-games/vite.config.ts', vite:config mode: 'production', vite:config logLevel: undefined, vite:config clearScreen: undefined, vite:config build: { minify: undefined, assetsInlineLimit: 4096, sourcemap: false }, vite:config optimizeDeps: { force: undefined } vite:config }, vite:config rawBase: './', vite:config cacheDir: '/home/ramendev/projects/just-games/node_modules/.vite', vite:config command: 'build', vite:config isWorker: false, vite:config mainConfig: null, vite:config isProduction: true, vite:config css: undefined, vite:config esbuild: { jsxDev: false }, vite:config envDir: '/home/ramendev/projects/just-games', vite:config env: { BASE_URL: './', MODE: 'production', DEV: false, PROD: true }, vite:config assetsInclude: [Function: assetsInclude], vite:config logger: { vite:config hasWarned: true, 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(1) { vite:config 'fnpd_/home/ramendev/projects/just-games' => { vite:config dir: '/home/ramendev/projects/just-games', vite:config data: [Object], vite:config hasSideEffects: [Function: hasSideEffects], vite:config webResolvedImports: {}, vite:config nodeResolvedImports: {}, vite:config setResolvedCache: [Function: setResolvedCache], vite:config getResolvedCache: [Function: getResolvedCache] vite:config }, vite:config set: [Function (anonymous)] vite:config }, vite:config createResolver: [Function: createResolver], vite:config appType: 'spa', vite:config getSortedPlugins: [Function: getSortedPlugins], vite:config getSortedPluginHooks: [Function: getSortedPluginHooks] vite:config } +14ms vite v4.4.9 building for production... vite:resolve 5.27ms svelte/animate -> /home/ramendev/projects/just-games/node_modules/svelte/src/runtime/animate/index.js +0ms vite:resolve 0.29ms svelte/easing -> /home/ramendev/projects/just-games/node_modules/svelte/src/runtime/easing/index.js +0ms vite:resolve 0.19ms svelte/internal -> /home/ramendev/projects/just-games/node_modules/svelte/src/runtime/internal/index.js +1ms vite:resolve 0.18ms svelte/motion -> /home/ramendev/projects/just-games/node_modules/svelte/src/runtime/motion/index.js +0ms vite:resolve 0.17ms svelte/store -> /home/ramendev/projects/just-games/node_modules/svelte/src/runtime/store/index.js +1ms vite:resolve 0.21ms svelte/transition -> /home/ramendev/projects/just-games/node_modules/svelte/src/runtime/transition/index.js +0ms vite:resolve 0.21ms svelte -> /home/ramendev/projects/just-games/node_modules/svelte/src/runtime/index.js +0ms vite:resolve 0.24ms svelte/internal/disclose-version -> /home/ramendev/projects/just-games/node_modules/svelte/src/runtime/internal/disclose-version/index.js +1ms transforming (1) .svelte-kit/generated/client-optimized/app.js vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/.svelte-kit/generated/root.svelte +236ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/routes/+layout.svelte +23ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/routes/+error.svelte +59ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/routes/+page.svelte +18ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/routes/about/+page.svelte +8ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/routes/games/+page.svelte +12ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/routes/login/+page.svelte +13ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/routes/resources/+page.svelte +12ms vite:vite-plugin-svelte transform returns compiled js for /home/ramendev/projects/just-games/src/routes/signup/+page.svelte +9ms transforming (12) node_modules/esm-env/prod-browser.jsUnexpected early exit. This happens when Promises returned by plugins cannot resolve. Unfinished hook action(s) on exit: (commonjs--resolver) resolveId "/home/ramendev/projects/just-games/node_modules/@sveltejs/kit/src/runtime/client/start.js" undefined (vite:build-import-analysis) transform "/home/ramendev/projects/just-games/node_modules/@sveltejs/kit/src/runtime/client/start.js" (vite:build-import-analysis) transform "/home/ramendev/projects/just-games/.svelte-kit/generated/root.svelte" (commonjs--resolver) resolveId "svelte/internal" "/home/ramendev/projects/just-games/.svelte-kit/generated/root.svelte" (vite:optimized-deps-build) load "/home/ramendev/projects/just-games/node_modules/.vite/deps_build-e2ef5bc8/svelte_internal.js" (vite:build-import-analysis) transform "/home/ramendev/projects/just-games/src/routes/+layout.svelte" (commonjs--resolver) resolveId "svelte/internal" "/home/ramendev/projects/just-games/src/routes/+layout.svelte" (vite:build-import-analysis) transform "/home/ramendev/projects/just-games/src/routes/+error.svelte" (commonjs--resolver) resolveId "svelte/internal" "/home/ramendev/projects/just-games/src/routes/+error.svelte" (vite:build-import-analysis) transform "/home/ramendev/projects/just-games/src/routes/+page.svelte" (commonjs--resolver) resolveId "svelte/internal" "/home/ramendev/projects/just-games/src/routes/+page.svelte" (vite:build-import-analysis) transform "/home/ramendev/projects/just-games/src/routes/about/+page.svelte" (commonjs--resolver) resolveId "svelte/internal" "/home/ramendev/projects/just-games/src/routes/about/+page.svelte" (vite:build-import-analysis) transform "/home/ramendev/projects/just-games/src/routes/games/+page.svelte" (commonjs--resolver) resolveId "svelte/internal" "/home/ramendev/projects/just-games/src/routes/games/+page.svelte" (vite:build-import-analysis) transform "/home/ramendev/projects/just-games/src/routes/login/+page.svelte" (commonjs--resolver) resolveId "svelte/internal" "/home/ramendev/projects/just-games/src/routes/login/+page.svelte" (vite:build-import-analysis) transform "/home/ramendev/projects/just-games/src/routes/resources/+page.svelte" (commonjs--resolver) resolveId "svelte/internal" "/home/ramendev/projects/just-games/src/routes/resources/+page.svelte" (vite:build-import-analysis) transform "/home/ramendev/projects/just-games/src/routes/signup/+page.svelte" (commonjs--resolver) resolveId "svelte/internal" "/home/ramendev/projects/just-games/src/routes/signup/+page.svelte" (commonjs--resolver) resolveId "./client.js" "/home/ramendev/projects/just-games/node_modules/@sveltejs/kit/src/runtime/client/start.js" (vite:build-import-analysis) transform "/home/ramendev/projects/just-games/node_modules/@sveltejs/kit/src/runtime/client/client.js" (commonjs--resolver) resolveId "svelte" "/home/ramendev/projects/just-games/node_modules/@sveltejs/kit/src/runtime/client/client.js" (vite:optimized-deps-build) load "/home/ramendev/projects/just-games/node_modules/.vite/deps_build-e2ef5bc8/svelte.js" Unexpected early exit. This happens when Promises returned by plugins cannot resolve. Unfinished hook action(s) on exit: (vite-plugin-sveltekit-compile) writeBundle ✓ built in 3.72s error during build: Error: Unexpected early exit. This happens when Promises returned by plugins cannot resolve. Unfinished hook action(s) on exit: (vite-plugin-sveltekit-compile) writeBundle at process.handleBeforeExit (file:///home/ramendev/projects/just-games/node_modules/rollup/dist/es/shared/node-entry.js:25714:28) at Object.onceWrapper (node:events:629:26) at process.emit (node:events:514:28) ```

Validations

sapphi-red commented 1 year ago

Your code includes a circular dependency. So it's correct that it doesn't work. https://stackblitz.com/edit/node-fkfv2m?file=game.js,chess.js,index.js

I think it'd be nice to have a better error message though. (like Node: Error: Cannot access 'GameMetadata' before initialization)

lib-eramen commented 1 year ago

Thanks for spotting the issue! Resolving the circular dependency worked.

lib-eramen commented 1 year ago

New error (probably related to the code) and not Vite directly: Only happens during vite build and not vite dev:

transforming (12) node_modules/esm-env/prod-browser.js Unexpected early exit. This happens when Promises returned by plugins cannot resolve. Unfinished hook action(s) on exit:

*log lines from loading svelte/internal files*

Unexpected early exit. This happens when Promises returned by plugins cannot resolve. Unfinished hook action(s) on exit:
(vite-plugin-sveltekit-compile) writeBundle
✓ built in 2.84s
error during build:
Error: Unexpected early exit. This happens when Promises returned by plugins cannot resolve. Unfinished hook action(s) on exit:
(vite-plugin-sveltekit-compile) writeBundle
    at process.handleBeforeExit (file:///home/ramendev/projects/just-games/node_modules/rollup/dist/es/shared/node-entry.js:25777:28)
    at Object.onceWrapper (node:events:629:26)
    at process.emit (node:events:514:28)

prod.browser.js just toggled DEV to false and BROWSER to true:

export const BROWSER = true;
export const DEV = false;

The error could also be reproduced on a fresh StackBlitz clone.

sapphi-red commented 1 year ago

That's completely a different thing and should be in a different issue. Also we'll need a minimal reproduction for that.

sapphi-red commented 1 year ago

I'll reopen this issue for making the error message better.

chaejunlee commented 1 year ago

@sapphi-red it looks like the circular dependency should not error.

https://github.com/vitejs/vite/blob/8b174fdcc798092c5002d586e4f25cb2a6f8768a/playground/ssr/__tests__/ssr.spec.ts#L7

Do you have any clue why this particular case throws error?

I would like to work on this issue.

However, I am not sure if I should detect the particular case then throw new error, or just change the error message at the instantiateModule level.

lib-eramen commented 1 year ago

@chaejunlee I was trying to reproduce the error for a different issue: StackBlitz Just wanted to put it out there. I tried to make the example as minimal as possible.

chaejunlee commented 1 year ago

As far as I can see, ssrImport is used as __vite_ssr_import__(source) during ssr.

https://github.com/vitejs/vite/blob/6cb397fd2de29a57ba67962b7865ff310aed4d70/packages/vite/src/node/ssr/ssrModuleLoader.ts#L145

https://github.com/vitejs/vite/blob/6cb397fd2de29a57ba67962b7865ff310aed4d70/packages/vite/src/node/ssr/ssrTransform.ts#L108

In the case of this issue, source (in this case src/lib/core/game.ts) has a circular dependency. Then, ssrImport returns moduleGraph.urlToModuleMap.get(dep)?.ssrModule which is {} in this case.

https://github.com/vitejs/vite/blob/6cb397fd2de29a57ba67962b7865ff310aed4d70/packages/vite/src/node/ssr/ssrModuleLoader.ts#L152-L172

That is why the error says __vite_ssr_import_0__.GameMetadata is not a constructor. The object __vite_ssr_import_0__ is empty.

Screenshot 2023-08-10 at 3 22 44

What I am currently trying to do is throwing error at the ssrImport level, but this doesn't look good. Because, It throws the error every time the circular dependency (in this case, src/lib/core/game.ts) with empty moduleGraph.urlToModuleMap.get(dep)?.ssrModule is imported in the original javscript file.

Because this is a problem of the nature of ssrImport handles circular dependency, I can't think of any better solution.

I would like to hear other's thought on this.

sapphi-red commented 1 year ago

@sapphi-red it looks like the circular dependency should not error.

https://github.com/vitejs/vite/blob/8b174fdcc798092c5002d586e4f25cb2a6f8768a/playground/ssr/__tests__/ssr.spec.ts#L7

Do you have any clue why this particular case throws error?

The test case one doesn't throw any errors on Node: https://stackblitz.com/edit/node-qgbmvq?file=index.js,circular-dep-init.js,module-b.js

I don't know why it doesn't throw in this case and it throws in the OP's case. But I guess it's written in the ECMA script spec. Maybe this part is related: https://262.ecma-international.org/14.0/#sec-example-cyclic-module-record-graphs

Because this is a problem of the nature of ssrImport handles circular dependency, I can't think of any better solution.

I guess splitting into two phases would work. Collecting the exports / linking in the first phase and executing in the second phase. Though I haven't thought this deeply yet.

sheremet-va commented 1 year ago

I guess splitting into two phases would work. Collecting the exports / linking in the first phase and executing in the second phase. Though I haven't thought this deeply yet.

Would be nice to implement this when porting vite-node (I'm planning to resume the efforts soon). I noticed how it's implemented in VM module and quite liked the performance implications there. If you are looking to implement it, I would look into their implementation even though VM API is not perfect for memory management and HMR.

sapphi-red commented 1 year ago

We can also check how engine262 handles this. Performance is not included in their goals but its implementation would be 100% spec compliant. https://github.com/engine262/engine262/blob/1582a0c3b2b75eaa81d5c535852d632de7e7a28a/src/modules.mts#L123-L169

AlbertMarashi commented 6 months ago

I'm getting these issues with so many modules. In SSR, the module is treated as an object, but in client-side it works

AriPerkkio commented 1 month ago

Here's minimal reproduction case without any 3rd party dependencies: https://stackblitz.com/~/edit/vite-cyclic-imports-vs-node?file=load-with-vite.mjs&file=load-with-node.mjs

$ node ./load-with-vite.mjs

10:36:04 [vite] Error when evaluating SSR module /ion-js/dom/Blob.js:
|- TypeError: Cannot read properties of undefined (reading 'BLOB')
    at eval (/home/projects/vite-cyclic-imports-vs-node/ion-js/dom/Blob.js:5:45)
    at async instantiateModule (file:///home/projects/vite-cyclic-imports-vs-node/node_modules/vite/dist/node/chunks/dep-DyBnyoVI.js:52963:5)

Loading the same setup with Node without Vite works fine:

$ node ./load-with-node.mjs

[Module: null prototype] {
  IonTypes: { BLOB: 'Blob' },
  dom: [Module: null prototype] { Blob: 'Blob' }
}