导航:

(一)Electron跑起来
(二)从零搭建Vue全家桶+webpack项目框架
(三)Electron+Vue+Webpack,联合调试整个项目
(四)Electron配置润色
(五)预加载及自动更新
(六)构建、发布整个项目(包括client和web)

摘要:到目前为止,我们的项目已经具备了PC客户端该有的一些基础功能和调试环境,但是总感觉缺了灵魂,那就是结合实际项目、实际业务的细节处理,缺着吧。。。这篇文章就介绍一下预加载和自动更新,文字功底有限,如有介绍的不清楚的地方,欢迎留言指正,或者跳过文字,直接去看代码,项目完整代码:https://github.com/luohao8023/electron-vue-template,随博客更新。

一、预加载

1、什么是预加载?什么场景能用到? 

  1. preload String (可选) -在页面运行其他脚本之前预先加载指定的脚本 无论页面是否集成Node, 此脚本都可以访问所有Node API 脚本路径为文件的绝对路径。 node integration 关闭时, 预加载的脚本将从全局范围重新引入node的全局引用标志。

摘自electron官网的一段介绍,https://www.electronjs.org/docs/api/browser-window

preload是BrowserWindow类的参数webPreferences的一个可选配置项,我们解读一下官网的介绍:

在页面运行其他脚本之前预先加载的指定的脚本:首先是个js文件没错了,再看加载时机,在页面运行其他脚本之前预先加载,这个页面不是普通的某个h5页面,而是指某个渲染进程(需要预加载js的渲染进程,因为渲染进程可能有多个,每个就是一个窗口),我们new一个BrowserWindow,打开了一个窗口,就是启动了一个渲染进程,如果我们不给这个窗口指定页面,那它就是空白的,如果指定了页面,那么窗口就会加载这个页面:

  1. const win = new BrowserWindow({
  2. width: 800,
  3. height: 600
  4. });
  5. win.loadURL('https://www.baidu.com');

如上面代码,我们创建了一个窗口,然后加载百度首页,而preload脚本的加载时机就是窗口创建后,百度首页加载之前。如果有人问,如果不调用loadURL方法,不加载页面,preload脚本会加载吗?答案是会,但有什么用呢?你起个壳子不给人家看页面是什么鬼?不管这些,重要的是我们理解这个加载时机就好了;

无论页面是否集成Node,此脚本都可以访问所有Node API:首先要说明的一点是,Electron5.x以上版本,默认无法在渲染进程中访问Node API,如需使用,需要预先配置:

  1. const win = new BrowserWindow({
  2. width: 800,
  3. height: 600,
  4. webPreferences: {
  5. nodeIntegration: true
  6. }
  7. });

然后还要清楚一点,preload脚本是运行在渲染进程中的,可以仔细考虑一下。再有一点就是,preload脚本中可以访问window对象(渲染进程其实就是起了个浏览器壳子),preload脚本运行在渲染进程,提前于页面和其他所有js的加载,又能访问Node API;

脚本文件路径为绝对路径,当node integration关闭时,预加载的脚本将从全局范围重新引入node的全局引用标志:结合前面两点理解就好了。

那么,到底什么是预加载?用白话定义一下:

某一个渲染进程,在页面加载之前加载一个本地脚本,这个脚本能访问所有Node API、能访问window对象。用法如下:

  1. const win = new BrowserWindow({
  2. width: 800,
  3. height: 600,
  4. webPreferences: {
  5. preload: path.join(__dirname, 'preload.js')
  6. }
  7. });

理解应该差不多了,但什么场景能用到这玩意儿呢?按正常的逻辑来想,主进程启动后启动渲染进程,渲染进程加载页面就完事儿了,哪会用到这个preolad呢?

想一下,如果我们有以下场景:

a、如果我们启动了一个窗口(渲染进程),加载了一个线上的页面,本地没有页面文件,但要做一些错误处理,比如网络错误,页面加载失败,然后在页面空白但时候插入一些元素;

b、如果我们的一套代码部署在web端和客户端,需要用一个变量判断是在web端还是客户端;

...........

感觉举的例子好勉强啊,不要见怪,就是大概这么个意思,没准哪天就遇到了非preload解决不了的问题呢,毕竟这玩意儿还是有它的特殊之处的;

上面两个场景如果用preload来解决的话,思路是利用prelaod中能访问window对象的特点,比如b,代码中可以用window.isClient来判断是否在客户端,默认为false,然后在preload中把window.isClient设置为true,而对于部署在web端的代码来说,这个值就是false。

2、怎么用?

上面说了怎么引用preload脚本,现在说一下怎么写,下面开始xxoo乱写乱画了:

  1. // 访问electron对象
  2. const {
  3. remote,
  4. ipcRenderer
  5. } = require('electron');
  6. // 访问node模块
  7. const fs = require('fs');
  8. const path = require('path');
  9. // 访问window对象
  10. window.isClient = true;
  11. window.sayHello = function() {
  12. console.log('hello');
  13. };
  14. // 操作dom
  15. const div = document.createElement('div');
  16. div.innerText = 'I am a div';
  17. document.body.appendChild(div);
  18. // ...

如果preoad里面逻辑比较复杂,有可能还要用webpack打包一下,单独拎出来打包就行了,webpack单文件打包,注意targer要"electron-renderer":

  1. /*
  2. Tip: preload 打包配置
  3. */
  4. const path=require('path');
  5. const { dependencies } = require('../package.json');
  6. module.exports = {
  7. mode:process.env.NODE_ENV,
  8. entry: {
  9. preload:['./src/preload/index.js']
  10. },
  11. output: {
  12. path: path.join(__dirname, '../app/'),
  13. libraryTarget: 'commonjs2',
  14. filename: './[name].js'
  15. },
  16. optimization: {
  17. runtimeChunk: false,
  18. minimize: true
  19. },
  20. node: {
  21. fs: 'empty',
  22. __dirname:false
  23. },
  24. module: {
  25. rules: [
  26. {
  27. test: /\.js$/,
  28. loader: 'babel-loader',
  29. exclude: /node_modules/
  30. }
  31. ]
  32. },
  33. externals: [
  34. ...Object.keys(dependencies || {})
  35. ],
  36. resolve: {
  37. extensions: ['.js'],
  38. alias: {
  39. '@': path.resolve(__dirname, "../src"),
  40. '@public': path.resolve(__dirname, "../public")
  41. }
  42. },
  43. plugins:[],
  44. target:"electron-renderer"
  45. }

我相信,总会遇到使用preload就能迎刃而解的问题。

二、自动更新

我们都知道,electron其实是封了个chrome内核,抛开壳子不说,里面运行的其实就是我们的h5页面,而就算我们跑了个空项目,没有任何内容,打包后的安装包也得30M左右,我们希望自己的程序有自动更新功能,但是更新机制是怎样的呢?

如果我们只改动了页面某一处的文本,却要用户更新整个安装包,那显然太不合理了,一是体验不好,二是我们的流量啊......

基于这种考虑,加上electron主进程和渲染进程的划分,那我们可以考虑如下更新机制:

主进程有改动时,那没的说,用户需要更新整个客户端(当然有精力有条件的可以做动态更新,官方好像是说支持,主要是我不会);渲染进程有改动时,我们只需要把h5包下载到本地然后加载就行了,当然这需要我们打包的时候能把h5包区分出来,在更新后能打开对应版本的h5包。

这里我们称主进程的更新为大版本更新,渲染进程的更新为小版本更新。

1、打包配置修改

为什么突然扯到打包配置修改了呢,因为牵扯到小版本的更新,那我们打包的时候就得把这个“小版本”给打出来,不然更新个

【原创】从零开始搭建Electron+Vue+Webpack项目框架(五)预加载和Electron自动更新的更多相关文章

  1. 【原创】从零开始搭建Electron+Vue+Webpack项目框架,一套代码,同时构建客户端、web端(二)

    摘要:上篇文章说到了如何新建工程,并启动一个最简单的Electron应用.“跑起来”了Electron,那就接着把Vue“跑起来”吧.有一点需要说明的是,webpack是贯穿这个系列始终的,我也是本着 ...

  2. 【原创】从零开始搭建Electron+Vue+Webpack项目框架(六)Electron打包,同时构建客户端和web端

    导航: (一)Electron跑起来(二)从零搭建Vue全家桶+webpack项目框架(三)Electron+Vue+Webpack,联合调试整个项目(四)Electron配置润色(五)预加载及自动更 ...

  3. 从零开始搭建Electron+Vue+Webpack项目框架,一套代码,同时构建客户端、web端(一)

    摘要:随着前端技术的飞速发展,越来越多的技术领域开始被前端工程师踏足.从NodeJs问世至今,各种前端工具脚手架.服务端框架层出不穷,“全栈工程师”对于前端开发者来说,再也不只是说说而已.在NodeJ ...

  4. Android 加载gif图片强大框架(支持预加载、缓存,还支持显示静态图片,一行代码全搞定)

    之前项目中没有涉及到显示gif图片的功能,也没有着重研究过,最近项目中要用到显示gif图片,于是就在网上一顿搜,用过之后发现如下几个缺点. 1.加载大的gif图片会出现oom. 2.没有预加载和缓存功 ...

  5. 基于spring的web项目启动时预加载数据到ServletContext

    1.要在web启动时预加载数据到ServletContext,实现方法有很多,一种比较简单的方案就是: 1)新建一个bean,定义其初始化方法: <bean id="beanId&qu ...

  6. Android项目框架之图片加载框架的选择

    本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 从Android爆发以后,自定义的控件如EditTextWithDelete.ActionBar.P ...

  7. vue图片预加载

    目的: 图片预加载能够使得用户在浏览后续页面的时候,不会出现图片加载一半导致浏览不流畅的情况. 一.方法一 项目打开的时候要对图片进行预加载,在App.vue里面的beforeCreate添加预加载程 ...

  8. vue-用Vue-cli从零开始搭建一个Vue项目

    Vue是近两年来比较火的一个前端框架(渐进式框架吧). Vue两大核心思想:组件化和数据驱动.组件化就是将一个整体合理拆分为一个一个小块(组件),组件可重复使用:数据驱动是前端的未来发展方向,释放了对 ...

  9. 从零开始:一个正式的vue+webpack项目的目录结构是怎么形成的

    如何从零开始一个vue+webpack前端工程工作流的搭建,首先我们先从项目的目录结构入手.一个持续可发展,不断加入新功能,方便后期维护的目录结构究竟是长什么样子的?接下来闰土大叔带你们一起手摸手学起 ...

随机推荐

  1. 17.3.20---python的变量作用域

    1---变量的作用域 在Python程序中创建.改变.查找变量名时,都是在一个保存变量名的空间中进行,我们称之为命名空间,也被称之为作用域.Python的作用域是静态的,在源代码中变量名被赋值的位置决 ...

  2. Kubernetes系列二: 使用kubeadm安装k8s环境

    环境 三台主机,一台master,两台node 作为master 作为node节点 作为node节点 每台主机Centos版本使用 CentOS Linux release 7.6.1810 (Cor ...

  3. Java之接口(java8的新特性)

    public class SubClassTest { public static void main(String[] args) { SubClass s = new SubClass(); // ...

  4. Linux集群软件安装实战

    一.需求和思路 1. 需求描述 公司有N个节点的集群,需要统一安装一个软件(jdk)需要开发一个脚本程序,实现对集群中的N个节点批量自动下载.安装jdk 2. 思路 1)编写一个启动脚本,用来发送一个 ...

  5. 【线段树】Interval GCD

    题目描述 给定一个长度为N的数列A,以及M条指令 (N≤5*10^5, M<=10^5),每条指令可能是以下两种之一: "C l r d",表示把 A[l],A[l+1],- ...

  6. hibernate 持久化对象 save

    hibernate 持久化对象 save new出来的user对象是游离状态的对象,执行session.save()方法保存后,user对象就变为持久化了,持久化的对象跟数据库表双向绑定的意思, 对象 ...

  7. zabbix监控Linux服务器丢包率

    http://www.ttlsa.com/zabbix/zabbix-simple-checks/  这个文章看了,还没有实践 1.先创建监控项,键值如下 icmppingloss[<121.1 ...

  8. F. Maximum Weight Subset(贪心or树形dp解法)

    题:https://codeforces.com/contest/1249/problem/F 题意:给一颗树,边权为1,节点有点权,问取到一个点集,俩俩之间路径超过k,是点权和最大 思路:贪心地取点 ...

  9. yum源本地部署完后网络部署报错

    错误信息 已加载插件:fastestmirror Determining fastest mirrors * base: mirrors.aliyun.com * extras: mirrors.al ...

  10. descriptive statistics|inferential statistics|Observational Studies| Designed Experiments

    descriptive statistics:组织和总结信息,为自身(可以是population也可以是sample)审视和探索, inferential statistics.从sample中推论p ...