一、什么是前端工程化

前端工程化是使用软件工程的方法来解决前端的开发流程中模块化、组件化、规范化、自动化的问题,其主要目的为了提高效率和降低成本。

二、为什么需要前端工程化?

Web业务日益复杂化和多元化,现在随便找个前端项目,都已经不是过去的拼个页面+搞几个jQuery插件就能完成的了。代码量可能从以前的千行到如今的万行,甚至十万行。人数从一个人变成了N个一起协作开发。所以在业务上,我们要去思考这些复杂和多元的场景,而产生的问题,如:

  • 如何扩展javascript、html、css本身的语言能力
  • 如何进行高效的多人协作
  • 如何解决功能复用和变更问题
  • 如何保证项目的规范性
  • 如何实现重复的劳动简单化

要实现前端工程化,就要解决以上的几个问题。

三、如何实现前端工程化?

1.如何扩展javascript、html、css本身的语言能力?

 (1)TypeScript

typeScript是javascript的超集,扩展了语法(类Classes,接口interfaces,模块Modules,类型注解Type annotaions,编译时类型检查Compiletime type checking,Arrow函数(类似c#的Lambda))使得JavaScript变得更强大,对于面向对象编程更好的支持。

(2)CSS预处理器:SASS 、LESS、 Stylus。

它们基于CSS扩展了一套属于自己的DSL(Domain Specific Language领域特定语言 ),来解决我们书写CSS时难以解决的问题:

  • 语法不够强大,比如无法嵌套书写导致模块化开发中需要书写很多重复的选择器;
  • 没有变量和合理的样式复用机制,使得逻辑上相关的属性值必须以字面量的形式重复输出,导致难以维护。

所以这就决定了CSS预处理器的主要目标:提供CSS缺失的样式层复用机制、减少冗余代码,提高样式代码的可维护性。

2.如何进行高效的多人协作

模块化

简单来说,模块化就是将一个大文件拆分成相互依赖的小文件,再进行统一的拼装和加载。只有这样,才有多人协作的可能。

JS的模块化

浏览器端模块化的问题:

  • 效率问题:精细的模块划分带来了更多的JS文件,更多的JS文件带来了更多的请求,降低了页面访问效率
  • 兼容性问题:浏览器目前仅支持ES6的模块化标准,并且还存在兼容性问题
  • 工具问题:浏览器不支持npm下载的第三方包

在ES6之前,JavaScript一直没有模块系统,这对开发大型复杂的前端工程造成了巨大的障碍。对此社区制定了一些模块加载方案,如CommonJS、AMD和CMD等,某些框架也会有自己模块系统,比如Angular1.x。现在ES6已经在语言层面上规定了模块系统,完全可以取代现有的CommonJS和AMD规范,而且使用起来相当简洁,并且有静态加载的特性。

规范确定了,然后就是模块的打包和加载问题:

  • 用Webpack+Babel将所有模块打包成一个文件同步加载,也可以打成多个chunk异步加载;
  • 用SystemJS+Babel主要是分模块异步加载;
  • 用浏览器的<script type="module">加载

目前Webpack远比SystemJS流行。Safari已经支持用type="module"加载了。

CSS的模块化

(1)类名冲突

当你写一个css类的时候,你是写全局的类呢,还是写多个层级选择后的类呢?

你会发现,怎么都不好

  • 过深的层级不利于编写、阅读、压缩、复用
  • 过浅的层级容易导致类名冲突

一旦样式多起来,这个问题就会变得越发严重,其实归根结底,就是类名冲突不好解决的问题

解决类名冲突

一些第三方机构提出了一些方案来解决该问题,常见的解决方案如下:

命名约定:即提供一种命名的标准,来解决冲突,常见的标准有:

  • BEM
  • OOCSS
  • AMCSS
  • SMACSS
  • 其他

(2)重复样式

这种问题就更普遍了,一些重复的样式值总是不断的出现在css代码中,维护起来极其困难。

比如一个网站的主题颜色改变,这些颜色会充斥到背景、文字、边框中,一旦颜色调整,就是一个非常大的工程。

解决重复样式的问题:

  • css in js

这种方案虽然可以利用js语言解决重复样式值的问题,但由于太过激进,很多习惯写css的开发者编写起来并不是很适应

它的核心思想是:用一个JS对象来描述样式,而不是css样式表,至于如何把样式应用到界面上,不是它所关心的事情,你可以用任何技术、任何框架、任何方式将它应用到界面。

  • 预编译器

有些第三方搞出一套css语言的进化版来解决这个问题,它支持变量、函数等高级语法,然后经过编译器将其编译成为正常的css

这种方案特别像构建工具,不过它仅针对css

常见的预编译器支持的语言有:

  • less
  • sass

(3)css文件细分

在大型项目中,css也需要更细的拆分,这样有利于css代码的维护。

不同的功能依赖不同的css样式、公共样式可以单独抽离,这样就形成了不同于过去的css文件结构:文件更多、拆分的更细

而同时,在真实的运行环境下,我们也希望文件越少越好,这种情况和JS遇到的情况是一致的,因此,对于css,也需要工程化管理。

解决css文件细分问题

这一部分,就要依靠构建工具,例如webpack来解决了:利用一些loaderplugin来打包、合并、压缩css文件

3.如何解决功能复用和性能问题

为了解决复用问题,引入组件化的概念。何以提高代码的复用性。

组件化

首先,组件化≠模块化。好多人对这两个概念有些混淆。

模块化只是在文件层面上,对代码或资源的拆分;

而组件化是在设计层面上,对UI(用户界面)的拆分。从UI拆分下来的每个包含模板(HTML)+样式(CSS)+逻辑(JS)功能完备的结构单元,我们称之为组件。

其实,组件化更重要的是一种分治思想。页面上所有的东西都是组件。页面是个大型组件,可以拆成若干个中型组件,然后中型组件还可以再拆,拆成若干个小型组件,小型组件也可以再拆,直到拆成DOM元素为止。DOM元素可以看成是浏览器自身的组件,作为组件的基本单元。

4.如何保证项目的规范性

模块化和组件化确定了开发模型,而这些东西的实现就需要规范去落实。

规范化其实是工程化中很重要的一个部分,项目初期规范制定的好坏会直接影响到后期的开发质量。

比如:

  • 目录结构的制定
  • 编码规范(eslint)
  • 前后端接口规范(swagger)
  • 文档规范( js注释规范jsdoc)
  • 组件管理
  • Git分支管理
  • Commit描述规范(commitlint)
  • 定期CodeReview
  • 视觉图标规范

5.如何实现重复的劳动简单化

为什么要借助自动化工具呢?

在浏览器端,开发时态(devtime)和运行时态(runtime)的侧重点不一样

开发时态,devtime:

1. 模块划分越细越好

2. 支持多种模块化标准

3. 支持npm或其他包管理器下载的模块

4. 能够解决其他工程化的问题(模块化、组件化、规范化)

运行时态,runtime:

1. 文件越少越好

2. 文件体积越小越好

3. 代码内容越乱越好

4. 所有浏览器都要兼容

5. 能够解决其他运行时的问题,主要是执行效率问题

这种差异在小项目中表现的并不明显,可是一旦项目形成规模,就越来越明显,如果不解决这些问题,前端项目形成规模只能是空谈

解决办法

既然开发时态和运行时态面临的局面有巨大的差异,因此,我们需要有一个工具,这个工具能够让开发者专心的在开发时态写代码,然后利用这个工具将开发时态编写的代码转换为运行时态需要的东西。

这样的工具,叫做自动化构建工具

用网上比较流行的话来说就是,前端工程化的很多脏活累活都应该交给自动化工具来完成。现在比较流行的前端自动化构建工具有 gulpwebpackvite

在之后的章节会详细讲解 webpack 的基本使用和构建原理,敬请期待~

推荐阅读:

高性能WEB开发:Javascript自身执行效率

JS事件冒泡、事件捕获、默认事件、事件对象那些事

高性能WEB开发:深入理解页面呈现、重绘、回流

40 行代码简单实现vue3的响应系统

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐