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

使用webpack.externals排除依赖时出现Object.defineProperty调用错误

问题解决:Webpack externals 配置导致 tsyringe 运行时错误

问题背景

我在构建用户脚本模板时,依赖tsyringe和reflect-metadata两个包,希望通过Tampermonkey的@require字段从jsdelivr CDN加载它们,而非打包进最终文件。用Webpack的externals属性传入package.json的dependencies内容后,打包成功但运行时报错:

Uncaught (in promise) TypeError: Object.defineProperty called on non-object

错误指向tsyringe代码中的Object.defineProperty(exports, "__esModule", { value: !0 })语句,尝试使用webpack-node-externals也未解决问题。

问题原因

Webpack默认的externals配置针对CommonJS模块,但Tampermonkey加载的CDN包多为UMD或全局变量形式。直接将dependencies传入externals,会导致Webpack生成的代码错误地以CommonJS模块的方式引用全局包,触发Object.defineProperty的非对象调用错误。

解决方案

1. 精准配置Webpack externals

替换原有externals配置,明确指定两个包的全局变量映射:

// webpack.config.ts
externals: {
  'tsyringe': {
    root: 'tsyringe', // 对应CDN包暴露的全局变量
    commonjs: 'tsyringe',
    commonjs2: 'tsyringe',
    amd: 'tsyringe'
  },
  'reflect-metadata': {
    root: 'Reflect', // reflect-metadata暴露的全局变量是Reflect
    commonjs: 'reflect-metadata',
    commonjs2: 'reflect-metadata',
    amd: 'reflect-metadata'
  }
}

2. 保证用户脚本依赖加载顺序

Tampermonkey脚本头部必须先加载reflect-metadata,再加载tsyringe(tsyringe依赖前者初始化):

// ==UserScript==
// @name         你的用户脚本名称
// @require      https://cdn.jsdelivr.net/npm/reflect-metadata@latest/Reflect.js
// @require      https://cdn.jsdelivr.net/npm/tsyringe@latest/dist/tsyringe.umd.js
// ==/UserScript==

3. 验证TypeScript配置

确保tsconfig.json开启装饰器相关选项,否则tsyringe的依赖注入会失效:

// tsconfig.json
{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

原理说明

通过明确externals的root字段,Webpack会生成正确的代码引用全局变量,而非尝试用CommonJS的exports方式处理,避免了非对象上调用Object.defineProperty的错误。同时严格的依赖加载顺序保证了tsyringe初始化时,reflect-metadata的API已经可用。

内容的提问来源于stack exchange,提问作者Kenya-West

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 13:45:06