Stimulus2升级到@hotwired/stimulus3报Controller无new调用错误如何解决
问题原因
Stimulus 3.x版本调整了产物编译规则,官方不再输出兼容ES5的转译代码,改为直接发布原生ES6类格式的产物。你遇到的Uncaught TypeError: Class constructor Controller cannot be invoked without 'new'错误,本质是你的项目构建工具将@hotwired/stimulus的ES6类代码误做ES5格式向下转译,转译后的代码调用Controller类时使用了ES5函数的调用逻辑,不符合ES6类必须用new关键字调用的要求。
你当前编写的控制器代码本身语法完全符合Stimulus 3的规范,不需要调整。
排查方向
你可以优先检查项目的转译配置,确认是否将@hotwired/stimulus纳入了转译处理范围:
- 若使用Webpack+Babel技术栈,检查
babel-loader的exclude规则是否未排除node_modules/@hotwired目录 - 若使用Rails技术栈,检查是否引入了非官方预转译的Stimulus包
- 若使用Vite技术栈,检查
optimizeDeps配置是否对Stimulus做了额外转译处理
修复方案
方案1:调整转译排除规则(优先推荐)
在构建转译配置中,将@hotwired/stimulus及相关Hotwire包加入排除列表,不对其做ES5转译即可。
Babel配置babel.config.json示例:
{ "presets": ["@babel/preset-env"], "exclude": [ "node_modules/@hotwired/**/*" ] }
Webpack配置中babel-loader规则示例:
module.exports = { module: { rules: [ { test: /\.js$/, exclude: /node_modules\/(?!@hotwired\/)/, use: ['babel-loader'] } ] } }
方案2:调整构建目标适配现代浏览器
如果你的项目不需要兼容IE11等老旧浏览器,可以直接将构建目标设置为支持ES6的现代浏览器,避免全局ES5转译。
Babel配置示例:
{ "presets": [ ["@babel/preset-env", { "targets": "> 0.25%, not dead, not ie 11" }] ] }
方案3:兼容老旧浏览器的特殊处理
如果必须兼容IE11等不支持ES6类的旧浏览器,可以安装@babel/plugin-transform-classes插件,单独给Stimulus包做类兼容转译:
{ "overrides": [{ "test": "./node_modules/@hotwired/**/*.js", "plugins": ["@babel/plugin-transform-classes"] }] }
内容的提问来源于stack exchange,提问作者Romeo
相关产品推荐
相关产品推荐

