elpis 前端的工程化搭建 & 前端基础建设

73 阅读5分钟

前言:上一篇文章中完成了 elpis core 的若干loader的编写,后续也引入了 koa router 、"koa-static" 、 "koa-nunjucks-2" 和 "koa-bodyparser" 等中间件,使得 elpis 运行起来后具有了相应的能力。

在这篇文章中将简单讲讲是如何在 elpis 中从 0 到 1,搭建前端工程和前端基础建设的

前端工程化

前端工程化的搭建,选择了较为成熟的 webpack 5。 对于 elpis 其功能形态注定我们将会基于 webpack 5 配置出能构建出多页面入口的能力,除此之外呢,为了优化开发体验,热更新是必不可少的;为了性能/制品用户的使用体验,构建制品过程中分包的能力也是需要的。那么总结下来,接下来要搭建的这个前端工程至少要有以下的能力:

  1. 支持多入口/页面开发
  2. 分环境构建
  3. 支持热更新
  4. 打包构建过程中具备分包的能力

支持多入口/页面开发

如果是使用CRA 或者 vue-cli 这类的脚手架,它们默认提供的是SPA的开发目录结构 众所周知,webpack是一个现代 JavaScript 应用程序的静态模块打包工具,其工作流程不算太长:

工作流程

  1. 解析入口文件:Webpack 从配置的入口文件开始,递归地分析所有依赖的模块。
  2. 应用 Loader:在解析模块的过程中,根据配置的 Loader 规则,对不同类型的文件进行处理。
  3. 生成依赖图:Webpack 构建出一个包含所有模块及其依赖关系的依赖图。
  4. 打包输出:依据依赖图,将所有模块打包成一个或多个文件,并输出到指定的目录。

为了支持多入口开发,那么我们可以从工作流程1入手,具体实施可以在webpack的配置文件中:

image.png

对于多入口的每个入口文件,类似于服务端的各个模块一样,都规定了一个相似的文件名格式,我们借助 path 模块和 glob 模块动态的获取指定目录下符合规定格式的js文件,用一个变量 entrylist 储存它们,最后将其赋值给 webpack 配置对象的 entry 属性。当然了,这里如图中所写的,是每次打包都会把每个入口都进行打包的。这里是可以通过 node 的命令行参数 传入想要构建的入口进行优化的。

分环境构建

一般来说,在实际开发中,我们往往会有三种环境:开发环境、测试环境和生产环境。这三种环境往往对于打包的结果产物会有一些区别,那么它们相应的webpack配置也有有一些差异的,这里借助面向对象的编程思想。我们可以构建出一份基础的 webpack 构建配置,然后在基于环境去继承基础的 webpack 配置去拓展出适合各个环境的配置。这里对于elpis来说暂时就只有两种环境:生产环境和开发环境

image.png 除了需要两份配置以外,也需要两份构建脚本的js文件。

支持热更新

对于开发环境来说,打包性能的问题的优先级相较于开发体验的优先级会较小。而热更新这种功能对于开发者来说是可以大大改善开发体验的。平时咱们使用高度封装的脚手架一般都是会自带热更新的。那么现在我们要自己手搓热更新了,其原理如下:

  1. 在开发服务器和浏览器之间建立WebSocket连接
  2. 当文件发生变化时,webpack重新编译相关模块
  3. 通过WebSocket将更新后的模块发送到浏览器
  4. 浏览器接收更新并替换对应模块,保持应用状态

具体在 webpack 5 中我们需要这样实现:

  1. 引入 express 作为热更新服务器的支持
  2. 引入 webpack 在开发环境的配置文件 image.png
  3. 借助express自带的static指定静态目录;
  4. 借助 express 的 webpack-dev-middleware 中间件对于 webpack执行了webpack dev 配置的complier结果进行落地文件和监听文件变化 image.png
  5. 借助 express 的 webpack-hot-middleware 中间件和complier对于浏览器的文件进行热替换 image.png

打包构建过程中具备分包的能力

在生产环境中,我们往往对于打包构建的产物是有大小要求的,无论是SPA还是MPA,在复杂的前端工程中,模块往往会相互引用的,这会导致打包过程极其容易出现重复打包的情况:

  1. 会拖慢打包构建速度
  2. 会让打包产物文件大小变大(eg: 共同依赖的第三方库,都分别重复打包了)

为了解决这个问题,业界常用的解决方案是分包,在前端工程项目,代码模块可以简要分为三类:

  1. 业务代码模块(修改频次高,且特异性较高)
  2. 业务代码公共模块(修改频次相较于业务模块低一些,且可复用性高,往往在较多业务代码中被引用)
  3. 第三方库代码模块(修改频次与第三方库版本更新挂钩,不更新的话就不会修改,可复用性较高)

基于这三类模块的更新频次及可复用性,结合浏览器的缓存机制 & webpack 的构建缓存机制可以对构建产物进行分包,在webpack中,我们可以通过 splitChunks 配置实现分包: image.png

当然除了分包以外,在生产环境中还有其他的优化手段,如:

  1. 代码压缩和混淆:使用TerserPlugin等工具
  2. CSS提取和优化:使用MiniCssExtractPlugin和CssMinimizerPlugin
  3. 多线程构建:使用HappyPack(webpack 5的支持不太好,可用thread-loader)等工具加速构建过程
  4. Tree Shaking:移除未使用的代码

引用: 抖音“哲玄前端”《大前端全栈实践》