Webpack按视图打包JS后浏览器报ReferenceError: checkPass未定义错误
Webpack打包后行内事件找不到定义函数的问题排查
问题描述
- 项目为每个视图单独打包对应JS文件,所有视图使用Pug模板开发,Webpack构建流程无编译报错,现有配置如下:
const path = require('path'); module.exports = { target: 'web', mode: 'development', entry: { showusers: [ './public/javascripts/showusers_actions.js', ], }, output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'bin'), }, }; - 浏览器运行时抛出未捕获异常:
ReferenceError: checkPass is not defined - 触发报错的关联函数定义在
showusers_actions.js中,代码片段如下:const checkPass = function(input) { if (input.value != document.getElementById('new_pass').value) { input.setCustomValidity('As senhas estão diferentes'); } else { input.setCustomValidity(''); } }; - 该函数通过Pug模板的行内事件属性调用,对应模板片段如下:
input.form-control(type="password", id="new_pass_ack", name="passwordack" oninput="checkPass(this)", required) - 浏览器调试工具中可确认,打包生成的
showusers.bundle.js内确实存在该函数的定义,形式为var checkPass = function checkPass(input) [...],但始终无法被行内事件识别。在接入Webpack前,该功能可正常运行。
错误根因
Webpack的打包机制会将每个入口文件的代码包裹在独立的模块作用域内,不会自动将文件内定义的变量、函数挂载到浏览器全局的window对象上。哪怕打包产物里可以看到var checkPass的声明代码,这个变量的作用域也是Webpack生成的模块闭包,而非浏览器的全局作用域。
行内事件(如oninput="checkPass(this)")执行时,仅会在全局作用域内查找目标函数,由于checkPass被封闭在模块作用域中未对外暴露,就会触发未定义的引用错误。
解决方法
- 手动暴露全局可访问的函数:在
checkPass定义完成后,追加代码将其挂载到全局对象上,即可被行内事件正常调用:window.checkPass = checkPass; - 更适配模块化规范的替代方案:移除模板中的行内事件绑定,改用JS在DOM加载完成后直接绑定事件,无需暴露全局变量,避免全局命名空间污染:
- 将Pug模板里的
oninput="checkPass(this)"属性删除 - 在
showusers_actions.js中补充事件绑定逻辑:document.addEventListener('DOMContentLoaded', () => { const passAckInput = document.getElementById('new_pass_ack'); passAckInput.addEventListener('input', (e) => { checkPass(e.target); }); });
- 将Pug模板里的
注意:不推荐通过修改Webpack配置批量暴露入口文件的全局变量,这种方式容易造成全局命名空间冲突,与当前项目按视图独立打包的结构适配性较差。
内容的提问来源于stack exchange,提问作者Gabriel Xavier
相关产品推荐
相关产品推荐

