美文网首页
编译阶段优化

编译阶段优化

作者: 欢欣的膜笛 | 来源:发表于2021-04-27 22:57 被阅读0次

对于 Compiler 实例⽽⾔,耗时最⻓的显然是⽣成编译过程实例后的 make 阶段,在这个阶段⾥,会执⾏模块编译到优化的完整过程。

对于 Compilation 实例的⼯作流程来说,不同的项⽬和配置各有不同,但总体⽽⾔,编译模块和后续优化阶段的⽣成产物并压缩代码的过程都是⽐较耗时的。
真正影响整个构建效率的还是 Compilation 实例的处理过程,即编译模块和优化处理。

编译模块阶段所耗的时间是从单个⼊⼝点开始,编译每个模块的时间的总和。要提升这⼀阶段的构建效率,⼤致可以分为三个⽅向:

  1. 减少执⾏构建的模块。
  2. 提升单个模块构建的速度。
  3. 并⾏构建以提升总体效率。

减少执⾏构建的模块

  1. IgnorePlugin
    可在构建模块时直接剔除那些需要被排除的模块,从⽽提升构建模块的速度,并减少产物体积。
    有的依赖包,除了项⽬所需的模块内容外,还会附带⼀些多余的模块。典型的例⼦是 moment 这个包,⼀般情况下在构建时会⾃动引⼊其 locale ⽬录下的多国语⾔包;但对于⼤多数情况⽽⾔,项⽬中只需要引⼊本国语⾔包即可。⽽ Webpack 提供的 IgnorePlugin 即可在构建模块时直接剔除那些需要被排除的模块,从⽽提升构建模块的速度,并减少产物体积。

    new webpack.IgnorePlugin({
        resourceRegExp: /^\.\/locale$/,
        contextRegExp: /moment$/,
    })
    
  2. 按需引⼊类库模块
    ⼀般适⽤于⼯具类库性质的依赖包的优化,典型例⼦是 lodash 依赖包。
    要解决这个问题,效果最佳的⽅式是在导⼊声明时只导⼊依赖包内的特定模块,这样就可以⼤⼤减少构建时间,以及产物的体积。还可以使⽤ babel-plugin-lodash 或 babel-plugin-import 等插件达到同样的效果。
    另外,Tree Shaking,这⼀特性也能减少产物包的体积,但是这⾥有两点需要注意:

    • Tree Shaking 需要相应导⼊的依赖包使⽤ ES6 模块化,⽽ lodash 还是基于 CommonJS,需要替换为 lodash-es 才能⽣效。
    • 相应的操作是在优化阶段进⾏的,换句话说,Tree Shaking 并不能减少模块编译阶段的构建时间。
  3. DllPlugin
    核⼼思想是将项⽬依赖的框架等模块单独构建打包,与普通构建流程区分开。

  4. Externals
    Webpack 配置中的 externals 和 DllPlugin 解决的是同⼀类问题:将依赖的框架等模块从构建过程中移除。它们的区别在于:

    • 在 Webpack 的配置⽅⾯,externals 更简单,⽽ DllPlugin 需要独⽴的配置⽂件。的
    • DllPlugin 包含了依赖包独⽴构建流程,⽽ externals 配置中不包含依赖框架的⽣成⽅式,通常使⽤已传⼊ CDN 的依赖包。
    • externals 配置的依赖包需要单独指定依赖模块的加载⽅式:全局对象、CommonJS、AMD 等。
    • 在引⽤依赖包的⼦模块时,DllPlugin ⽆须更改,⽽ externals 则会将⼦模块打⼊项⽬包中。

提升单个模块构建的速度

  1. include/exclude
    include 的⽤途是只对符合条件的模块使⽤指定 Loader 进⾏转换处理。⽽ exclude 则相反,不对特定条件的模块使⽤该 Loader。

    • 通过 include/exclude 排除的模块,并⾮不进⾏编译,⽽是使⽤ Webpack 默认的 js 模块编译器进⾏编译(例如推断依赖包的模块类型,加上装饰代码等)。
    • 在⼀个 loader 中的 include 与 exclude 配置存在冲突的情况下,优先使⽤ exclude 的配置,⽽忽略冲突的 include 部分的配置。
  2. noParse
    Webpack 配置中的 module.noParse 则是在上述 include/exclude 的基础上,进⼀步省略了使⽤默认 js 模块编译器进⾏编译的时间。

  3. Source Map
    对于⽣产环境的代码构建⽽⾔,会根据项⽬实际情况判断是否开启 Source Map。在开启 Source Map 的情况下,优先选择与源⽂件分离的类型,例如 "source-map"。

  4. TypeScript 编译优化
    Webpack 中编译 TS 有两种⽅式:使⽤ ts-loader 或使⽤ babel-loader。
    在使⽤ tsloader 时,由于 ts-loader 默认在编译前进⾏类型检查,因此编译时间往往⽐较慢,通过加上配置项 transpileOnly: true,可以在编译时忽略类型检查,从⽽⼤⼤提升 TS 模块的编译速度。
    babel-loader 则需要单独安装 @babel/preset-typescript 来⽀持编译 TS(Babel 7 之前的版本则还是需要使⽤ ts-loader)。

  5. Resolve
    Webpack 中的 resolve 配置制定的是在构建时指定查找模块⽂件的规则,例如:

    • resolve.modules:指定查找模块的⽬录范围。
    • resolve.extensions:指定查找模块的⽂件类型范围。
    • resolve.mainFields:指定查找模块的 package.json 中主⽂件的属性名。
    • resolve.symlinks:指定在查找模块时是否处理软连接。

并⾏构建以提升总体效率

  1. HappyPack 与 thread-loader
    这两种⼯具的本质作⽤相同,都作⽤于模块编译的 Loader 上,⽤于在特定 Loader 的编译过程中,以开启多进程的⽅式加速编译。HappyPack 诞⽣较早,⽽ thread-loader 参照它的效果实现了更符合 Webpack 中 Loader 的编写⽅式。

  2. parallel-webpack
    并发构建的第⼆种场景是针对于多配置构建。Webpack 的配置⽂件可以是⼀个包含多个⼦配置对象的数组,在执⾏这类多配置构建时,默认串⾏执⾏,⽽通过 parallel-webpack,就能实现相关配置的并⾏处理。

相关文章

  • 编译阶段优化

    对于 Compiler 实例⽽⾔,耗时最⻓的显然是⽣成编译过程实例后的 make 阶段,在这个阶段⾥,会执⾏模块编...

  • ✅**iPA包体积优化 和编译速度优化**

    一、链接时间优化 链接时间优化,链接阶段执行模块间优化 在编译阶段,clang将发出LLVM bitcode而不是...

  • 要点提炼| 理解JVM之程序编译&代码优化

    本篇将介绍程序编译时期的代码优化手段,分成两个阶段: 概述 早期(编译期)优化 晚期(运行期)优化 1.概述 a....

  • java关于String的编译优化

    输出: 编译器优化是有选择的,其实只要记住一句话就行了:只有编译阶段能确定的值,编译器才可以进行优化。我们回过头来...

  • 编译原理——寄存器

    •代码生成是编译器的最后阶段。代码生成器通过前端产生的中间表示法或者通过代码优化器在代码优化阶段,映射到目标程序中...

  • LLVM

    一、编译器 性能优化:启动优化、界面优化、架构优化 编译型语言:OC(编译器是clang)、C(编译器可以直接执行...

  • 第一章绪论

    编译过程和编译程序结构 五个阶段: 词法分析 语法分析 语义分析和中间代码生成 优化 目标代码生成 编译程序的开发...

  • iOS编译优化--带你深入浅出了解HMap

    前言: 编译阶段的优化除了组件二进制化可以实现提前编译 .O文件外,还有没有更进一步的优化方案呢? 首先看下 组件...

  • Build settings探究之—编译优化

    Build settings探究之—编译优化 Build settings探究之—编译优化

  • iOS的性能优化

    1、ipa包体积优化 1.1 编译配置优化:编译器代码层面优化Optimize Level;Bitcode(较难...

网友评论

      本文标题:编译阶段优化

      本文链接:https://www.haomeiwen.com/subject/adfprltx.html