前端工程化
浅浅想一些思路吧...
分离和聚合
前端的工作流程是,把目标业务分离成一个个功能的代码文件和片段(开发阶段),然后聚合在一起。
- 分离是指现有的各种文件。每个文件的语法规范、应该处于文件目录中的位置,是工程化要解决的问题。
- 怎么把现有的这些文件聚合在一起,即各种构建工具的使用,是工程化要解决的问题。
- 聚合后代码应该在服务端工作还是客户端工作,如何工作,也是工程化要解决的问题。
开发环境
开发环境,就是写代码的环境。流程大致包括:
- 确定选用的主要技术栈;
- 确定标准化的工程目录结构;
- 代码编辑器的选择与基本配置;
- 书写代码时,配置编译器得到正确的语法规范检查;书写代码增强,包括代码格式化和自动修正
- 运行/调试代码的开发服务器配置封装、
mock
服务; - 构建生产代码的配置封装。
- 自动化流程工具的配置。
构建
其实最艰难的一部分,主要是上面提到的倒数第二点:构建生产代码。这就主要涉及到构建工具的配置了。这部分,无论是发布 npm
包,还是构建跑在生产环境的代码都避不开。
随着新的上层语言(比如 .vue
, .ts/.tsx
, .ejs
等)的出现,构建工具开始承担编译器的角色。这意味着,它将管理着:
- 代码将会如何被编译成底层的
js
,css
等最原始的文件 js
模块的导入所需要的路径寻找策略是怎样的
之所以存在第二点,是因为 js
的语言规范本身并没有提供模块解析的相关算法。开发阶段,上层语言的编译器(主要就是 typescript
)会根据自己的模块解析策略识别目录并产生语法提示,而这一行为必须要和未来的构建工具所执行的模块解析的路径查找策略保持完全一致,才能构建出正确的产物。tsconfig.json
为这一点做出了相当复杂的努力。
一个构建工具的配置文件,大概会囊括这些内容:
- 目标语法:环境下支持的 js 版本不同,导致一些新的语法无法使用。通过一些工具将新版本的 js 文件转为老旧的 js 语法。比如 babel
- 目标环境:一些老旧的(浏览器环境的,或者 js 版本) API 可能没有实现,或实现有差异。需要提供 polyfill,来覆盖 API 的实现。比如 core-js
js
模块路径查找策略- 产物体积与运行时性能:构建工具提供代码分割策略、体积优化(如
tree-shaking
)的插件配置。 - 构建工具除了充当打包代码的作用,往往还会提供一个内置的
watch
服务器,让我们在代码开发的时候实时就能看到打包的最终产物,根据结果进行调试。
常见 vue 工程化选择
技术栈
ts + vue + vite + eslint (+ prittier)
可能是最流行的解决方案了。
nuxt.js
太重了,适用于 SSR
。它的启动速度和热更新速度一定不如原生 vue
好。小项目不推荐。
目录结构
目录结构对于vue
是比较固定的,遵循其默认初始化的目录结构即可。
编辑器
清一色 vscode
。基本配置如字体大小、缩进。
语法增强
.vue/.ts/.jsx/... 这部分主要是编译器(也就是 vscode 插件)的事情。vue-official
, eslint
, prittier
都在这一步配置。
开发服务器与构建生产环境代码
即 vite
的配置。
自动化
自动化即在代码写好之后,顺序的执行一些事情,比如:
- push 前严格模式执行代码检查,给出不符合规范的代码警告,从而提高仓库代码质量;
- push 的时候自动构建;
- 构建后自动对代码进行一些包体积的分析,并生成可视化图像;
- 构建后自动生成镜像并部署。
可以看到,自动化很大的提高了团队工作的速度和质量。
对于比较简单的项目,自动化完全可以通过 npm-run-all
一把梭来实现。
如果不够用,考虑常见的流程控制工具如 gulp
。
维护与改进
一个工程,能够长久的运行,离不开维护人员。维护、改进,并与时俱进,是一个工程不考虑非技术因素能够良好运作下去的关键。我们造轮子,当更重要的是怎么做,才能不重复的造轮子,而仅仅是修轮子。
文档
其实,规范化文档更多的是参考,而不是强制约束。
- 开发规范,如编码规范, git commit 规范,code review 规范
- 发布规范,版本迭代文档,git tag/release 标签规范
我们应该定期的更新上游依赖
主依赖
定期更新主依赖是最简单的提高性能的方法。
所谓的主依赖,就是指项目非常依赖的第三方库。比如 vue
的项目依赖 vite
和 vue
等。
定期的更新依赖将带来额外的时间成本,来解决升级所导致的破坏性变化。但这从长远来讲,这是值得的。保持依赖的最新(LTS)让我们的项目能够享受到当前能获得的最好的开发体验、最新的稳定 API、最好的性能、以及最活跃的生态。而如果一个项目长时间不动,那么它的迁移成本将变得非常巨大。
上游依赖
有的项目可能会用到自己开发的上游依赖,比如自己写的组件库、工具库。这些库的更新其实更多的是增量更新,因为组件库是自己写的,所以一般不会想要产生破坏性的变化。
想办法提高性能
这就是老生常谈的话题了,从开发到构建,每个阶段都能调优。
- 良好的开发配置以提高项目的开发速度
- 代码和静态资源的打包分割策略与压缩
- 在开发代码中使用懒加载、防抖与节流等工作
- 缓存与 CDN
这部分非常杂,但最终的目标都是为了提高性能。