前端工程化
TIP
前端工程化 相关笔记
什么是"前端工程化"
在一个大型前端开发的过程中遇到的痛点是什么,那么工程化的过程在我的理解就是将痛点标准化、规划化。其主要目的为了提高效率和降低成本,即提高开发过程中的开发效率,减少不必要的重复工作时间。
所以我认为一位新入职的员工首先要做的就是了解入职团队的规范和标准,当前团队的 git 版本管理是如何进行的、组件是如何封装的、自动化测试是如何进行的,在了解后思考是否有不足的地方,如果有的话如何提升团队的开发效率和降低运维成本。
那么如何取做到优化整个项目的实施过程就是前端工程化。前端工程化主要分为模块化、组件化、规范化、自动化四个方面。
模块化
简单来说,模块化就是将一个大文件拆分成相互依赖的小文件,再进行统一的拼装和加载。只有这样,才有多人协作的可能。
JS 的模块化
在 ES6 之前,JavaScript 一直没有模块系统,这对开发大型复杂的前端工程造成了巨大的障碍。对此社区制定了一些模块加载方案,如 CommonJS、AMD 和 CMD 等,某些框架也会有自己模块系统,比如 Angular1.x。
现在 ES6 已经在语言层面上规定了模块系统,完全可以取代现有的 CommonJS 和 AMD 规范,而且使用起来相当简洁,并且有静态加载的特性。
规范确定了,然后就是模块的打包和加载问题:
- 用 Webpack+Babel 将所有模块打包成一个文件同步加载,也可以打成多个 chunk 异步加载;
- 用 SystemJS+Babel 主要是分模块异步加载;
- 用浏览器的
<script type="module">
加载目前 Webpack 远比 SystemJS 流行。Safari 已经支持用type="module"
加载了。
CSS 的模块化
虽然 SASS、LESS、Stylus 等预处理器实现了 CSS 的文件拆分,但没有解决 CSS 模块化的一个重要问题:选择器的全局污染问题。
按道理,一个模块化的文件应该要隐藏内部作用域,只暴露少量接口给使用者。而按照目前预处理器的方式,导入一个 CSS 模块后,已存在的样式有被覆盖的风险。虽然重写样式是 CSS 的一个优势,但这并不利于多人协作。
从工具层面,社区又创造出 Shadow DOM、CSS in JS 和 CSS Modules 三种解决方案。
- Shadow DOM 是 WebComponents 的标准。它能解决全局污染问题,但目前很多浏览器不兼容,对我们来说还很久远;
- CSS in JS 是彻底抛弃 CSS,使用 JS 或 JSON 来写样式。这种方法很激进,不能利用现有的 CSS 技术,而且处理伪类等问题比较困难;
- CSS Modules 仍然使用 CSS,只是让 JS 来管理依赖。它能够最大化地结合 CSS 生态和 JS 模块化能力,目前来看是最好的解决方案。Vue 的 scoped style 也算是一种。
资源的模块化
Webpack 的强大之处不仅仅在于它统一了 JS 的各种模块系统,取代了 Browserify、RequireJS、SeaJS 的工作。更重要的是它的万能模块加载理念,即所有的资源都可以且也应该模块化。
资源模块化后,优点是:
- 依赖关系单一化。所有 CSS 和图片等资源的依赖关系统一走 JS 路线,无需额外处理 CSS 预处理器的依赖关系,也不需处理代码迁移时的图片合并、字体图片等路径问题;
- 资源处理集成化。现在可以用 loader 对各种资源做各种事情,比如复杂的 vue-loader 等等;
- 项目结构清晰化。使用 Webpack 后,你的项目结构总可以表示成这样的函数:
dest = webpack(src, config)
。
组件化
从 UI 拆分下来的每个包含模板(HTML)+样式(CSS)+逻辑(JS)功能完备的结构单元,我们称之为组件。
组件化 ≠ 模块化。模块化只是在文件层面上,对代码或资源的拆分;而组件化是在设计层面上,对 UI(用户界面)的拆分。
页面上所有的东西都是组件。页面是个大型组件,可以拆成若干个中型组件,然后中型组件还可以再拆,拆成若干个小型组件,小型组件也可以再拆,直到拆成 DOM 元素为止。DOM 元素可以看成是浏览器自身的组件,作为组件的基本单元。
传统前端框架/类库的思想是先组织 DOM,然后把某些可复用的逻辑封装成组件来操作 DOM,是 DOM 优先;而组件化框架/类库的思想是先来构思组件,然后用 DOM 这种基本单元结合相应逻辑来实现组件,是组件优先。这是两者本质的区别。
其次,组件化实际上是一种按照模板(HTML)+样式(CSS)+逻辑(JS)三位一体的形式对面向对象的进一步抽象。
所以我们除了封装组件本身,还要合理处理组件之间的关系,比如 (逻辑)继承、(样式)扩展、(模板)嵌套和包含等,这些关系都可以归为依赖。
目前市面上的组件化框架很多,主要的有 Vue、React、Angular。Vue 文档中的对比其他框架一文已经讲得很详细了。
规范化
规范化其实是工程化中很重要的一个部分,项目初期规范制定的好坏会直接影响到后期的开发质量。
- 目录结构的制定
- 编码规范
- 前后端接口规范
- 文档规范
- 组件管理
- git 分支管理
- commit 描述规范
- 视觉图标规范
例子
- egg对 koa 做了重新封装,最基本的目的就是帮助开发团队和开发人员降低开发和维护成本,如果做到的呢?就是基于目录结构的的规范制定,开发插件的规范制定。
- 编码规范采用 ESLint 和 StyleLint 等强制措施,不允许不规范代码的上传
自动化
前端工程化的很多脏活累活都应该交给自动化工具来完成。需要秉持的一个理念是:任何简单机械的重复劳动都应该让机器去完成。
- 图标合并
- 持续继承
- 自动化构建
- 自动化部署
- 自动化测试
例子
- 自动化部署——在开发完成后的编译部署实现自动化,例如本博客使用的 vitepress,每次提交后会自动构建和部署。其他方式:github CI、Jenkins 等等
- 自动化测试——常用框架 karma、mocha、jest、ava 等等