本篇文章主要是介绍了目前前端工程化做一次详细的对比和目前流程的工程框架的优缺点。
背景
随着2009年 Node.js
的横空出世,对于前端来说,也是一个历史性的时刻。随着 Node.js 一同出现的还有两个大哥一块诞生 CommonJS 规范和 npm 包管理机制。随后也卷出了 Grunt、Gulp、Webpack 等一系列基于 Node.js 的前端开发构建工具。 2013 年的哪个时候,前端三大框架 React.js/Angular/Vue.js 相继发布第一个版本。我们可以从以往基于一个个页面的开发,变为基于一个个组件进行开发。开发完成后使用 webpack 等工具进行打包构建,并通过基于 Node.js 实现的命令行工具将构建结果发布上线。前端开发开始变得规范化、标准化、工程化。
任务构建工具
概述
任务构建工具(task-runner)就是一些自动化组织、执行任务的工具,用来执行一些命令或利用插件处理文件,比如压缩、转换、格式化等,比较传统的工具包括 gulp,grunt
,还有npm自带的npm script。
框架对比
框架 | Github | Npm(weekly down) |
---|---|---|
gulp | Star: 32.4K, Fock: 4.4K, User: 1.6M | 1,434,891 |
grunt | Star: 12.1K, Fock: 1.5K, User: 889K | 710,405 |
通过上述表格我们可以看出gulp的使用数量明显多于grunt,gulp是在保留grunt精华的基础上做了改进,甚至能使用后者的插件。gulp有专门人在持续维护,grunt有半年多没有更新了,下面我们对两者进行细化区分
Grunt
一套前端自动化构建工具,一个基于nodeJs的命令行工具,它是一个任务运行器, 配合其丰富强大的插件
特点:
- 合并文件(js/css)
- 压缩文件(js/css)
- 语法检查(js)
- less/sass预编译处理
该框架属于比较老的框架了,目前状态被拍在了沙滩上
Gulp
gulp
是与grunt
功能类似的前端项目构建工具, 虽然这哥俩都是基于Nodejs的自动任务运行器,而且能自动化地完成 javascript/coffee/sass/less/html/image/css 等文件的合并、压缩、检查、监听文件变化、浏览器自动刷新、测试等任务gulp更高效(异步多任务), 更易于使用, 插件高质量。它要比grunt
强大的多。特定如下:
- 代码优于配置、node 最佳实践、精简的 API 集,gulp 让工作前所未有的简单。
- 基于 node 强大的流(stream)能力,gulp 在构建过程中并不把文件立即写入磁盘,从而提高了构建速度。
- 遵循严格的准则,确保我们的插件结构简单、运行结果可控。
秘籍修炼,直接看API就行了
随便写了个监听文件,仅供参考,请勿吐槽
const watch = require('gulp-watch')
const start = require('./scripts/changeMd')
watch(['packages/*/*.md'], function() {
start()
});
function defaultTask() {
start()
}
exports.default = defaultTask
复制代码
npm script
前面是我们所熟悉 gulp
和 grunt
的工作模式。虽然他们对我们项目友好的做了构建,但是也存在问题:需要借助插件;本身有自己的构建语言,使用起来繁琐。
通过以上内容我们可以npm script
加打包工具进行
模块打包工具
啥是模块打包器呢?——就是把几个模块打包成一个或者几个文件中去,然后去引用。当然还有一种概念————就是es module,这种其实是scritps 中 mode 的一种概念。就是可以引用局部js。究其这这些我们主要解决了作用域的问题,在es5中除了全局作用域还有函数作用域,那么我们可以将代码拆分到不同函数作用域中。现在主流的这些大哥们都有什么呢,给大家一一介绍下(不常用的就算了)。
框架 | Github | Npm(weekly down) |
---|---|---|
vite | Star: 3.5K, Fock: 2.5K, User: 85.3K | 409,938 |
webpack | Star: 60K, Fock: 8.1K, User: 8M | 19,690,682 |
rollup | Star: 21K, Fock: 1.1K, User: 1.3M | 5,996,992 |
parcel | Star: 39.7K, Fock: 2K, User: 165K | 79,546 |
browserify | Star: 13.9K, Fock: 1.2K, User: 376K | 1,844,003 |
通过以上表格我们可以看出webpack
是最常用的打包器。vite是最近最火的框架。接下来我要介绍一下这些大哥们有什么区别。
Vite
Vite(法语意为 "快速的",发音 /vit/,发音同 "veet")是一种新型前端构建工具,能够显著提升前端开发体验。它主要由两部分组成:一个开发服务器,它基于 原生 ES 模块 提供了 丰富的内建功能,如速度快到惊人的 模块热更新(HMR);一套构建指令,它使用 Rollup 打包你的代码,并且它是预配置的,可输出用于生产环境的高度优化过的静态资源。
上面有点太官方了,实际上就是利用Rollup的东西,再利用 ES 模块进一步的封装。node服务选用的是koa。看目前最近更新有着自己的服务器了。
在我们用 script 标签 type=module
时就会发起一个 get 请求
<scripts type="module" src="./app.js"></scripts>
复制代码
举一个Vue文件的例子,在main.js中时如何调用的。
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
复制代码
内部含有的import
包就会直接进行 get 请求
GET http://localhost:3000/@modules/vue.js
GET http://localhost:3000/src/App.vue
复制代码
大哥通过这些骚操作,就可以去劫持浏览器的请求并将项目中的文件进行简单的分解和接触。vite在这个过程中没哟对文件进行打包和编译,在运行速度上面要比 webpack 的速度快。
当然它也有某些缺点:
- 项目的开发浏览器要支持esmodule
- 不能识别commonjs语法
- 生态少
总而言之,vite在如今编译大环境下做了很多处理,也是在自己组建库里使用了,没有任何问题。我只能说一句————真香
Webpack
先整点官方的哈:webpack 是一个模块打包器。它的主要目标是将 JavaScript 文件打包在一起,打包后的文件用于在浏览器中使用,但它也能够胜任转换(transform)、打包(bundle)或包裹(package)任何资源(resource or asset)。
大哥是10年前开发发布的,说实话真心为维护这些的大哥们点个赞,一直更新着新技术,真的不容易。我们可以叫他硬哥。
Webpack 一直在紧随现在技术的更新迭代,而且有着大量的市场。
说说它的原理:
- 确定入口,找到所有的入口文件
- 根据 npm 逐级递归识别依赖,构建依赖树
- 将代码转化成 AST 抽象语法树
- 在 AST 阶段中去处理代码
- 把 AST 抽象语法树变成浏览器可以识别的代码, 然后输出
webpack 说实话对于大型项目是真心不错的。它主要有以下技术特点:代码分割;支持加载器(Loader);智能解析;插件系统。技术能力绝对杠杠的。比如涉及到css、html,涉及到复杂的代码拆分合并等复杂场景建议使用 webpack
webpack 也是有缺点的,webpack服务前去急切地抓取和构建你的整个应用,启动服务会变得很慢。
Rollup
Rollup 是一个 JavaScript 模块打包器,可以将小块代码编译成大块复杂的代码,例如 library 或应用程序。Rollup 对代码模块使用新的标准化格式,这些标准都包含在 JavaScript 的 ES6 版本中,而不是以前的特殊解决方案。ES6 模块可以使你自由、无缝地使用你最喜爱的 library 中那些最有用独立函数,而你的项目不必携带其他未使用的代码。
官方说的有点繁琐了,实际上 rollup 就是一个模块化的打包工具,去合并项目中的文件。打包的过程中不需要担心它的顺序和命名参数。支持多种格式的输出:
- amd - AMD
- cjs -CommonJS
- es - ES6 modules
- umd - UMD
- system - SystemJS loader
有些格式的输出需要配合rollup的插件去维护。
这位猛士原理大致如下,整体跟webpack类似,但细节处理上有很大不同
- 获取入口文件的内容,包装成 module,生成抽象语法树
- 对入口文件抽象语法树进行依赖解析
- 根据以来解析生成我们需要的代码
- 最终写入目标文件
rollup比较倾向于 js 库,做ES转换,模块解析,可以使用Rollup。
Parcel
Parcel 是 Web 应用打包工具,优秀的开发者使用体验使 Parcel 区别于其他同类工具。Parcel 利用多核处理器提供了极快的速度,并且不需要任何配置。
官方说的打包速度很快,实测了一下确实快了不少,可以减少一倍的时间。对于我们开发的话,可以大大减少编译时间。功能其实都差不多:模块化、编译、压缩、热替换。
原理上其实都差不多
- 初始化配置
- 递归编译
- 构建 Bundle 树
- 生成我们需要的代码
跟上面的框架基本上都很雷同了。不过对于我们开发编译已经很友好了,对于新手来说简直就是神奇。
Browserify
Browserify 可以让你使用类似于 node 的 require() 的方式来组织浏览器端的 Javascript 代码,通过预编译让前端 Javascript 可以直接使用 Node NPM 安装的一些库。
大哥已经1年多不更新,使用的用法就跟原来 commonjs 一样,所有操作都是命令行,对于前端其实不太友好。还是不推荐大家使用了
打包工具还有很多,有兴趣的大哥可以来补充哈,像fis3、roadhog、create-react-app等也都是很好的。
包管理工具
node 发布之后,npm 也跟着就出来了,大家也都是一直使用npm包管理工具。后续在npm上面也推出了很多工具,再次给大家介绍一下。
框架 | Github | Npm(weekly down) |
---|---|---|
npm | Star: 17.3K, Fock: 3.2K, User: — | 3,769,724 |
yarn | Star: 40.3K, Fock: 2.8K, User: 89.1K | 2,603,440 |
cnpm | Star: 3.5K, Fock: 763, User: - | 6,745 |
pnpm | Star: 14.2K, Fock: 385, User: 1.9K | 411,146 |
tyarn | Star: 108, Fock: 13, User: - | 981 |
Npm
这是大家所常用的,在这就不多说了。npm 说实话是 Node.js 能够如此成功的主要原因之一。npm 通过在自己的代码仓库中存储各个包、在自己的数据库中存储各个包的信息,然后通过npm的命令对包进行管理。
它得运行机制如下:
- 通过config信息远程获取包信息。
- 构建依赖树,将里面递归到所有的包扁平化
- 下载包到 node_modules 文件下,生成lock文件。
Yarn
它是Google 和 Facebook 等国际大公司开发的包管理工具,引得源还是一个,它主要是解决了 npm 的很多缺陷:下载速度慢;安装速度慢;没有统一的版本控制。
大致原理是一致的,说一下它跟 npm 的不同吧:
- 并行下载,提高了包的下载速度
- 引入了 yarn.lock 文件,存储包之间的依赖关系
- 通过 yarn.lock 文件,不用每次计算各个包之间的版本依赖,安装速度更快
Cnpm
这是淘宝推出的工具。主要是为了解决国内使用npm缓慢喝掉线的问题,因此退出了自己的源https://registry.npm.taobao.org
。 说实话并没有解决实质的问题,只是将 npm 的包cope到了国内服务器镜像上。10分钟的同步对国内的开发者已经很友好了。
Tyarn
这个我就不多说了,就是yarn的国内镜像了。淘宝开发的。
Pnpm
我们最后讲个大哥,最先进的包管理工具。performant npm
,官方上给了几个特点
- pnpm 比替代方案快 2 倍
- Node_modules 中的文件是从一个单一的可内容寻址的存储中链接过来的
- pnpm 内置支持了单仓多包
- pnpm 创建了一个非平铺的 node_modules,因此代码无法访问任意包
自己也是亲测了一下,简直6的飞起,目前我也是正在逐步替换 yarn。
简单的说一下原理:
- 通过package.json查询依赖关系
- 判断是否有缓存,如果没有,下载到缓存中,如果有,则进入下一步
- 创建 node_modules 目录,在目录下
.pnpm
进行结构初始化 - 从缓存的对应包中使用硬链接放置文件到相应包代码目录中
- 使用符号链接,将每个包的直接依赖放置到自己的目录中
- 在工程的node_modules目录中使用符号链接,放置直接依赖,就是将上面
.pnpm
中的东西拿到node_modules该目录下直接使用。
整个的链路就通了。大哥就是将下载的包缓存起来以便下一次更方便使用。想法很前卫。大家可以一块试试。目前国内字节已经大范围使用了。
总结:目前就先总结到这了。任务构建工具、模块打包、包管理三个方面进行分析各自框架的优缺点。后期会将单测、mock等工具也会输入进去。 前端技术的更新越来越快,我也就能跟的上这些了。比前几年那就懵懂的小菜鸟强了一丢丢。大家可以尽情提意见、虚心听取。