本博客不欢迎:各种镜像采集行为,请尊重知识产权法律法规。大家都是程序员,不要闹得不开心。

话说,在传统的electron程序中,大量的逻辑是写在renderer.js文件中的。但是,后来随着electron的版本发展,逐渐出来了一种呼声:就是要将node能力从renderer.js中分离出来。让renderer.js回归传统js的功能。这个时候,出现的新概念就是preload.js

苏南大叔:electron代码,browserWindow的preload.js作用范围是哪里? - electron-browserwindow-preload-js
electron代码,browserWindow的preload.js作用范围是哪里?(图5-1)

本文的测试环境:electron@13.0.1win10。本文探讨preload.jsbrowserWindow中的应用,当然,preload.jswebview中也有使用到。但是暂时不在本文的讨论范围内。本文主要命题是:preload.js的作用范围,以及如何区分当前作用的页面。

开题简述

preload.js并非一个新事物,在苏南大叔的测试中,至少electron@3.0系列就支持preload.js了。只不过,在以前的经验教程中,renderer.js是更加被推荐的,掩盖了preload.js的锋芒。直到electron@5系列中,默认在渲染进程中,禁用了node能力,preload.js才被提上日程。

苏南大叔:electron代码,browserWindow的preload.js作用范围是哪里? - preload-js
electron代码,browserWindow的preload.js作用范围是哪里?(图5-2)

对于electronbrowserWindow来说,一个browserWindow可以加载一个preload.js。而在browserWindow里面,实际上是可以进行页面跳转的。那么,问题来了,页面跳转后,这个preload.js还生效么?preload.js里面定义的全局js代码,还能执行么?

下面就是苏南大叔的实验代码,主要功能是:使用electron打开一个本地页面index.html,然后当前页面跳转到next.html,新开浏览器窗口打开next.html,新开browserWindow打开next.html。这三种方式来测试,preload.js中的代码,还能否生效。还是否可以执行?

代码概述

main.js,这里简单加载preload.js

//...
const mainWindow = new BrowserWindow({
  //...
  webPreferences: {
    preload: path.join(__dirname, 'preload.js'),
    //...
  }
})
//...

preload.js,这里简单定义:当页面加载完preload.js的时候(优先于页面内所有的js代码),做个console输出。

window.hello = function(){
    alert("say hello to 苏南大叔")
}
console.log("preload init")

苏南大叔:electron代码,browserWindow的preload.js作用范围是哪里? - preload-js-demo-code
electron代码,browserWindow的preload.js作用范围是哪里?(图5-3)

index.htmlnext.htmlnext2.html三者相互链接,简单调用preload.js中的函数,看看能否加载到。next2.html是通过target='_blank'弹出的。

<script>
  hello();
</script>

另外,值得一提的是:如果使用electron fiddle来生成这些html的话,会有CSP规则限制inline的代码执行。具体可以参考下面这篇文章:

electron@12开始的注意事项

electron@12开始的新参数,contextIsolation: false,参与了本次实验。在这个实验中,间接的实验了最新的electron@12的新参数contextIsolation。在preload.js中的console.log是一直可以执行的。但是,注入到window对象的hello()函数,却是只能在contextIsolation: false下才能被识别。

苏南大叔:electron代码,browserWindow的preload.js作用范围是哪里? - preload-js-demo-code-error
electron代码,browserWindow的preload.js作用范围是哪里?(图5-4)

const mainWindow = new BrowserWindow({
   //...
   webPreferences: {
     //...
     contextIsolation:false
   }
})

实验结果

实验结果是这样的:只要当前browserWindow还在,无论在其内部的页面地址如何变化,preload.js都是有效的。就相当于:每次页面加载的时候,都自动注入一个公共的js文件。即使是通过target='_blank'打开一个新的electron窗口,preload.js依然有效。

苏南大叔:electron代码,browserWindow的preload.js作用范围是哪里? - preload-js-demo
electron代码,browserWindow的preload.js作用范围是哪里?(图5-5)

preload.js一次加载,多次执行。新开的窗口,默认也支持preload.js

这里多说一句,如果你想控制新开electron窗口的大小的话,可以参考下面这篇文章。

相关链接

总结

结论就是:只要browserWindow在,那么preload.js就在,并且页面加载一次,就自动加载preload.js一次。并且其优先级很高,先于页面内原有的js代码。并且,值得一提的是:正常来说,只有preload.js才具有node能力,默认情况下,renderer.js或者是在index.html,都是没有node能力的。除非,你主动赋予他们访问node功能的权利。

下面的链接,是苏南大叔写过的有关electron的相关文章链接,欢迎保存入您的收藏夹中。如下:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。