2023年12月6日发(作者:)

Electron源码学习:Electron程序体积裁剪(减小体积)

Electron源码学习: Electron程序体积裁剪(减小体积)

前言

此篇专题名称可能叫

Electron

的编译(虽然并没有具体的编译步骤,但实际上本文里面的各种技术都需要源码编译Electron)更为合适。因为

此篇文章基本不涉及到源码的解析和修改,但是因为也是基于

Electron

的学习和理解之上的,勉勉强强也叫这个名字吧。我测试编译的环境

Electron

V4.2.9,为2019年年底的版本,本文中部分的方法在最新的版本

Electron

版本上不能直接适用; 那这种情况怎么办呢?自己去

改改就好了。

目的

针对

Electron

体积削减的话题讨论也是由来已久,因为

Electron

的根本就是

Chromium

, 也因此

Chromium

的裁剪办法基本上也都适用

Electron

,

Electron

是一个独立的exe, 针对

Electron

也有一些特殊的办法减小一些体积。本文的目的就是介绍一些我现在用到的一些用于裁

剪程序的方法,看下效果:

途径1:GN编译开关

注意:该方法不适用于老版本的

Electron

,老版本通过

static_library

的方法在链接的时候太慢,我个人认为没必要在这上面花功夫。

整理的开关如下:(以下开关主要作用是关闭一些不太可能用到的功能,对体积影响不是很大, 也相当于是源码裁剪,但是力度不大,做不

到把具体某个庞大的部件减去)

is_debug = false

target_cpu = "x86" #编译目标程序为32位

enable_nacl = false

is_component_build = false

is_component_ffmpeg=false

symbol_level = 2 #设置为0的时候,将不会产生PDB,少量减少体积和极大加快编译速度

blink_symbol_level=2 # 同上

enable_basic_printing = false

enable_resource_whitelist_generation=false

debug_devtools = false

#enable_plugins = false

enable_pdf = false

enable_webrtc = false

enable_plugin_installation =false

enable_spellcheck = false

use_browser_spellchecker = false

enable_print_preview = false

enable_web_speech = false

#enable_electron_extensions = false

enable_task_manager = false

enable_themes = false

win_pdf_metafile_for_printing = false

enable_service_discovery = false

enable_wifi_bootstrapping = false

enable_webvr = false

enable_notifications = false

disable_ftp_support = true

#enable_electron_extensions = false

enable_fake_location_provider = false

enable_message_center = false

enable_nacl_nonsfi = false

enable_native_notifications = false

enable_one_click_signin = false

#enable_openvr = false

enable_session_service = false

enable_tts = false

enable_vr = false

enable_windows_mr = false

enable_windows_mr = false

#pdf_is_standalone = true

pdf_use_skia_paths = false

pdf_use_skia = false

pdf_is_complete_lib = false

pdf_enable_xfa_tiff = false

pdf_enable_xfa_png = false

pdf_enable_xfa_gif = false

pdf_enable_xfa_bmp = false

pdf_enable_xfa = false

pdf_enable_v8 = false

pdf_enable_click_logging = false

pdf_bundle_freetype = false

rtc_build_examples = false

rtc_build_tools = false

#toolkit_views = false

treat_warnings_as_errors = false

start_daemons_for_testing = false

is_unsafe_developer_build = true

angle_enable_custom_vulkan_cmd_buffers=false

angle_enable_d3d11=true

angle_enable_d3d9=true

angle_enable_vulkan=false

angle_enable_gl=false

angle_enable_gl_null=false

angle_enable_essl=false

enable_swiftshader=false

enable_reporting = flase

enable_net_mojo=false

那么这些开关放在哪里呢? 通过执行命令

gn args outRelease

会打开你对应的编译目录的配置,然后将这些东西放进去。保存,然后关闭。

然后这些配置会被存储到

outRelease

目录下的

中。如图示:

途径2: 修改优化编译选项(可以直接减10+M)

在4.2.9版本中,绝大部分的项目的编译优化选项是/O1(最小体积优先);部分项目的编译优化选项是/O2(速度优先),如图:

我们这里来个极限优化。

第一步, 需要先将编译选项中的

/Oy-

/GS

分别都去掉,(因为和第二步中的开关冲突了)

第二步,把

/O2

/O1

分别都替换成

/Ox /Os /GS- /GF /GR- /Oy

途径3:使用VC-LTL来移除基础运行库(省掉2M左右的体积)

这里可能会让人有点儿疑惑, 这个

VC-LTL

是个什么东西?

VC-LTL

很NB啊,

VC-LTL

是一套由国内的初雨团队打造的一套用于链接

Windows自带运行库的套件;

简单来说,我们在编写程序的时候,经常会用到

memcpy

,

strcpy

类似的函数;通常来讲,在DEBUG的模式或者

/MT

下,

memcpy

,

strcpy

这一类的函数会直接链接到类似于

,

(链接到具体版本的DLL,由编译器的版本决定)

这一类的DLL库中,所以当程序调用

memcpy

的时候,就会实际调用对应模块中的函数。

当程序选择使用

/MT

编译的时候,这一类函数的就会直接以嵌入到程序中,这就会直接增加程序的体积。然而其实Windows操作系统在发

行的时候,这一类的函数的包含库它自己已经携带了。意思就是,操作系统自己有一套自己的运行库。

如果能仔细看到这里,那么想必你已经明白了。

VC-LTL

干的事情就是,让目标程序也能用上这个Windows自带的库。Windows自带的库

的名称为

,每个版本的Windows的这个库都叫这个名字。

VC-LTL

的作用就是将以

/MT

编译的程序所使用的基础库以

/MD

的形式链接到

中。

安装

VC-LTL

, 并确定当前的

Electron

所使用的编译器版本,并将

VC-LTL

引用到

Electron

1. 在

中确定SDK和库的版本,例如我这里4.2.9使用的版本是SDK,10.0.17763.0和14.16.27023。为什么要确定?引

VC-LTL

需要手动将头文件目录,LIB库目录加入到当前的编译环境中。

2. 添加

VC-LTL

的引用;假定你已经正确安装了

VC-LTL

,并且已经确定了版本号。那么接下来需要将

VC-LTL

的目录分别添加

electron_

中。假定

VC-LTL

的目录在

F:Open_SourceVC-LTL

1. 处理

1. 找到

rule cc

下的

/showIncludes

,将如下目录添加到

/showIncludes

后面,

"-imsvcF:Open_SourceVC-LTLconfigVista" "-imsvcF:Open_SourceVC-LTLVC14.16.27023include" "-imsvcF:Open_SourceVC-LTLVC

14.16.27023atlmfcinclude" "-imsvcF:Open_SourceVC-LTLucrt10.0.17763.0"

2. 找到

rule cxx

下的

/showIncludes

,执行上一步的操作。

2. 处理

electron_

,假定你的SDK安装在

C:/Program Files (x86)/Windows Kits/10/lib/10.0.17763.0/um/x86

搜索

electron_

,将

/LIBPATH:"C$:/Program$ Files$ (x86)/Windows$ Kits/10/lib/10.0.17763.0/um/x86"

替换为:

/LIBPATH:"F$:/Open_Source/VC-LTL/VC/VC-LTL-4.0.1.10-Binary-VS2017/lib/x86/Vista" /LIBPATH:"F$:/Open_Source/VC-LTL/VC/VC-LTL-4.0.1.10-

Binary-VS2017/lib/x86/Vista/Advanced" /LIBPATH:"F$:/Open_Source/VC-LTL/VC/VC-LTL-4.0.1.10-Binary-VS2017/VC/14.16.27023/lib/x86" /LIBPATH:

"F$:/Open_Source/VC-LTL/VC/VC-LTL-4.0.1.10-Binary-VS2017/VC/14.16.27023/lib/x86/Vista" /LIBPATH:"F$:/Open_Source/VC-LTL/VC/VC-LTL-4.0.

1.10-Binary-VS2017/ucrt/10.0.17763.0/lib/x86" /LIBPATH:"C$:/Program$ Files$ (x86)/Windows$ Kits/10/lib/10.0.17763.0/um/x86"

如果你的程序是64位的,那么就引用到64位对应的目录即可。

注意:因为不同的操作系统的附带的

各不相同,那么很容易存在新编译器支持的特性在老版本的操作系统上不受支持。例如:新版

本的

vcruntime

肯定支持类似于

%zu

这样的格式控制串,但是老版本的操作系统,例如Win7,甚至老一点儿的Win10所附带的

支持该格式控制串。但如果采用常规的方式以

/MT

的方式编译的话,那么自然没有问题;因为

%zu

的支持是直接嵌入到程序里面的,因此哪

怕是老版本的操作系统也不受链接文件影响。但是

VC-LTL

的模式天生决定了这个问题不好处理,因此读者在使用VC-LTL的时候应注意相

关的问题。

途径4:移除exe的重定位表 (又可以减少2M左右)

熟悉PE结构的读者肯定知道重定位表是个什么东西,其实这个玩意儿就是为了让DLL能够每次都加载到不同的基址上的技术。PE结构

中,DLL为了解决DLL默认基址被占用的问题,弄出了一个重定位表;一旦DLL不能被加载到预期的位置上,那么通过重定位表就能重新将

变量,函数等调用重新指向对应的位置。

当然现在有一个链接选项就是动态基址的

/DYNAMICBASE

,所有有时候哪怕DLL的默认基址没有被占用,也会重新定位到新的基址。

上述的东西只是对DLL有限制,

Electron

是一个单独的exe程序,exe程序是不需要这个重定位表的,因为最先映射的就是exe,所以不存在抢

占问题。指哪儿哪儿就是基址。再而

Electron

的代码体积巨大,也因此这个重定位表的体积也是相当的吓人。看下图:

这个4.0.0版本的

Electron

的重定位表体积,就已经达到了惊人的2M+。所以还是移除比较科学。

准备修改编译选项,打开

electron_

文件:

搜索

/FIXED$:NO

并替换成

/FIXED

,(V4.2.9里面有两处)

搜索

/DYNAMICBASE

并替换成

/DYNAMICBASE$:NO

至此编译出来的程序就没有重定位表了,且不会对原本程序有任何影响。途径5:移除

devtools_

(又可以减少5M左右)

devtools_

的文件在新版本的

Electron

目录中已经不能直接被看到了,这个文件被嵌入到

中,

devtools_

发行的版本并不需要这个文件,那么完全可以干掉。裁掉之前文件约为8.31M,移除之后文件

体积约为2.42M。如图:

准备修改编译选项,打开

文件:

搜索

repack

, 删除该条命令中的

gen/content/browser/devtools/devtools_

,然后保存即可。

执行resources的编译任务。(名称忘了,注意:此处不是重新编译

Electron

其他途径:

删除代码里面的字符串:函数

PostTask

用到的

FROM_HERE

宏里面传递了函数名称和代码位置,移除可以使体积略微减小;他的反调试

意义大于裁剪意义;(有关于安全保护相关的帖子,请看我的另一篇同系列帖子《》)

使用7Z极限压缩;当使用7Z极限压缩时,文件的体积可以压缩接近至30%。意思是100M的文件,压缩下来大概为30M左右。

删除目录中非必须的文件,如下:

1. ,;

2. locales目录中的不用支持的语言;

3. d3dcompiler_;

4.

(视使用场景而定)

移除node_modules打包目录中的文件,主要包含如下类型文件:

1.

2. AUTHORS

3.

4. LICENSE

5. SAMPLES

6. 工程临时文件

7. 等等非依赖文件