为何Electron无法直接加载CDN引入的jQuery?
我之前也踩过这个一模一样的坑!核心原因是你Electron主进程里设置的nodeIntegration: true和CDN版jQuery的加载逻辑冲突了,具体来拆解下:
为什么CDN方式会失效?
当你开启nodeIntegration: true时,Electron会把Node.js的模块系统(比如module、exports这些变量)暴露到渲染进程的全局环境中。而CDN加载的jQuery源码里有一段环境检测逻辑:如果发现当前环境存在module和exports,它就会以CommonJS模块的形式导出,不会把$和jQuery挂载到浏览器的window对象上。
但问题在于,CDN加载的脚本没办法通过require去引入,这就导致jQuery既没有被正确导入到模块系统,也没有挂载到全局window上,Bootstrap依赖全局的$自然就找不到了,直接触发报错。
你的解决方案为什么有效?
你用require('jquery')的方式引入本地安装的jQuery时,Node.js的模块系统会正确加载它,之后你手动把jQuery和$挂载到window上,Bootstrap就能顺利找到全局的jQuery变量,自然就正常工作了。
补充两种可选解决方案
除了你采用的本地引入方式,还有两种常见的思路可以解决这个问题:
方案1:关闭nodeIntegration(推荐如果不需要Node.js API的场景)
修改Electron主进程的webPreferences配置,关闭Node.js集成:
const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: false, // 关闭Node.js集成 contextIsolation: true // 开启上下文隔离,Electron 12+版本默认开启 } })
这样渲染进程里就不会有Node.js的模块变量,CDN版jQuery会像在普通浏览器里一样,自动把$挂载到window上,Bootstrap就能正常加载了。
方案2:保留nodeIntegration,修改CDN jQuery的加载逻辑
在CDN加载jQuery的脚本后面,手动把模块导出的jQuery挂载到window对象上:
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script> <script> // 手动将jQuery挂载到全局window window.jQuery = window.$ = module.exports; </script> <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
附你的代码示例
原HTML代码
<!doctype html> <html lang="en"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <!-- Bootstrap CSS --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous"> <title>Hello, world!</title> </head> <body> <h1>Hello, world!</h1> <!-- Optional JavaScript --> <!-- jQuery first, then Popper.js, then Bootstrap JS --> <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script> </body> </html>
原Electron主进程代码
const { app, BrowserWindow } = require('electron') function createWindow () { // Create the browser window. const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true } }) // and load the index.html of the app. win.loadFile('index.html') } app.whenReady().then(createWindow)
你的解决代码(本地引入方式)
<script> window.jQuery = window.$ = require('jquery'); </script> <script src="./node_modules/bootstrap/dist/js/bootstrap.bundle.js"></script>
内容的提问来源于stack exchange,提问作者Lin Yun Wen

