今天遇到一个很诡异的问题。
一个 Excel 导入的功能,采用动态加载 JS 的方法加载 XLSX 脚本,在浏览器中运行正常,但是把这个页面嵌入 Electron 打开,却遇到程序报错 XLSX.read is not a function
。
更奇怪的是,这个项目之前已经开发过类似的功能并上线发布,并没有什么问题。于是继续调查,发现只有在 Electron 本地调试环境会有这个报错,Electron 正式环境和浏览器上并没有问题,之前开发类似功能,只是恰好没有在 Electron 本地调试环境调试过。
在 XLSX 的 Github 官网发现一个 issue XLSX.read is not a function Electron JS · Issue #2209 · SheetJS/sheetjs,但是并没有解决问题。
把 XLSX 的源码下载下来,发现其中有这样一段代码,意思是 XLSX 会根据环境来决定调用 make_xlsx_lib 时传入的参数。
在 xlsx.min.js 上打断点,看看 make_xlsx_lib 的参数如何不同
Electron 本地调试环境断点如下:
Electron 正式环境断点如下
调试环境的 Electron,打开 Console,查看 module,发现并不是 undefined
正式环境的 Electron,打开 Console,查看 module,发现是 undefined
至此,问题查明,是 XLSX 本身导致的问题,而且在正式环境没有影响。
那么 XLSX 为什么这么做呢?是 XLSX 做错了吗?其实这不是 XLSX 的错,而是 UMD 规范,jQuery 等许多库都有类似的问题 stackoverflow.com/questions/3…
上文中提到的 Electron 本地调试环境和正式环境的区别,就在于是否开启了 nodeIntegration。开启 nodeIntegration 的时候,module 不为空,XLSX 会以为是处于 nodejs 环境,所以采用 CommonJS 规范。
在 Electron 的 官网FAQ 也有提到这个问题。
因为 Electron 在运行环境中引入了 Node.js,所以在 DOM 中有一些额外的变量,比如
module
、exports
和require
。 这导致 了许多库不能正常运行,因为它们也需要将同名的变量加入运行环境中。 可以通过禁用 nodeIntegration 来解决