You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vite编译文件执行时出现命名空间映射错误如何解决

问题描述

我使用Vite/SWC构建Node.js(NestJS)应用,配置文件如下:

import { defineConfig } from 'vite';
import { VitePluginNode } from 'vite-plugin-node';
import path from 'path';

export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        format: 'cjs',
        entryFileNames: '[name].js' 
      }
    }
  },
  plugins: [
    ...VitePluginNode({
      adapter: 'nest',
      appPath: './src/index.ts',

      initAppOnBoot: false,
      tsCompiler: 'swc',

      swcOptions: {
        jsc: {
          parser: {
            syntax: 'typescript',
            dynamicImport: true,
            decorators: true
          },
          baseUrl: path.resolve('.'),
          paths: {
            '@libs/*': ['src/libs/*']
          },
          target: 'es2021',
          transform: {
            decoratorMetadata: true
          }
        }
      }
    })
  ],
  optimizeDeps: {
    exclude: ['@nestjs/microservices', '@nestjs/websockets']
  }
});

编译过程可成功完成,但执行编译后的文件时抛出如下错误:

Object.defineProperty(n, k, d.get ? d : {
                                      ^

TypeError: Cannot read properties of undefined (reading 'get')
    at _interopNamespaceDefault (pathToFile/index.js:34:39)
    at Module.<anonymous> (pathToFile/index.js:48:41)
    ...

排查后发现问题根源:Rollup生成的_interopNamespaceDefault函数中,当处理process对象的setMaxListeners属性时,Object.getOwnPropertyDescriptor(e, k)返回undefined(因为setMaxListeners是EventEmitter原型链上的属性,而非process自身属性),导致读取d.get时触发类型错误。

解决方法

方案1:标记process为外部模块

修改Vite的Rollup配置,将process标记为外部内置模块,避免Rollup对其进行命名空间转换处理:

export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        format: 'cjs',
        entryFileNames: '[name].js' 
      },
      // 告知Rollup process是Node.js内置模块,不参与打包转换
      external: ['process']
    }
  },
  // ...其他原有配置
});

方案2:调整SWC模块处理配置

在SWC配置中明确指定模块类型为CommonJS,并启用外部辅助函数,减少不必要的转换逻辑:

swcOptions: {
  jsc: {
    // ...原有jsc配置
  },
  externalHelpers: true,
  module: {
    type: 'commonjs'
  }
}

方案3:自定义插件修复interop函数

添加自定义Vite插件,重写Rollup生成的_interopNamespaceDefault函数,补充原型链属性的处理逻辑:

import { defineConfig } from 'vite';
import { VitePluginNode } from 'vite-plugin-node';
import path from 'path';

export default defineConfig({
  // ...原有配置
  plugins: [
    ...VitePluginNode({/* 原有插件配置 */}),
    {
      name: 'fix-interop-namespace',
      transform(code, id) {
        // 仅处理编译后的入口文件
        if (id.endsWith('index.js') && code.includes('_interopNamespaceDefault')) {
          return code.replace(
            /function _interopNamespaceDefault\(e\) {[\s\S]*?return Object.freeze\(n\);}/,
            `function _interopNamespaceDefault(e) {
  const n = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } });
  if (e) {
    for (const k in e) {
      if (k !== 'default') {
        let d = Object.getOwnPropertyDescriptor(e, k);
        // 处理原型链上的属性
        if (!d) {
          d = { enumerable: true, get: () => e[k] };
        }
        Object.defineProperty(n, k, d.get ? d : {
          enumerable: true,
          get: () => e[k]
        });
      }
    }
  }
  n.default = e;
  return Object.freeze(n);
}`
          );
        }
        return code;
      }
    }
  ]
});

方案4:降级依赖版本

该问题属于特定版本Rollup/Vite的interop处理bug,可尝试将Rollup降级到3.x系列,或Vite降级到4.x稳定版本,规避该问题。


内容的提问来源于stack exchange,提问作者Vololodymyr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 20:25:17