12

前文

端技术范围不断发展,前端开发不仅限于直接编写html,css和javascript,Web应用日益庞大,代码也更加庞大,因此许多新的思想(例如模块化和工程化等)和框架(React和Vue等),以及新的语言(Es6 TypeScript)随之出现,而构建工具则承担起了中间的桥梁作用。

正文

构建工具最直接的作用是:将源码转换成可执行的js,csshtml,具体包括:

  • 代码转换:ts->js,scss->css
  • 文件优化:压缩js,css,html,压缩合并图片等
  • 代码分割:提取公共代码。
  • 模块合并:将模块化里的多个模块和文件合并到一个文件
  • 自动刷新:监听本地代码,自动重新构建,刷新浏览器。(热重载)
  • 代码校验:代码被提交到仓库前需要校验规范
  • 自动发布:更新代码后,自动构建出线上发布代码,传输给发布系统

构建其实是工程化和自动化思想的再前端的体现:将一系列流程用代码自动去实现,解放生产力。

常见前端构建工具的分类和对比

1. Npm Script

npm是nodejs附带的包管理器,npm script是npm内置的一个功能,允许在package.json文件里面使用script字段定义任务:

{
    "scripts":{
        "dev":"node dev.js",
        "pub":"node build.js"
    }
}

在这里,一个属性对应一段shell脚本,原理是通过调用shell去运行脚本命令

优点
  • 内置,无需安装其他依赖
缺点
  • 功能简单,不方便管理多个任务依赖

2. Grunt

  • Grunt与npm script类似,也是通过shell运行脚本命令。
  • Grunt与大量封装好的插件,可以用于常见任务,也能管理任务之间的依赖。
  • grunt的具体执行代码和依赖关系写在配置文件的里,例如:
module.exports = function(grunt){
    //插件的配置信息
    grunt.initConfig({
        uglify:{
            app_task:{
                files:{
                    'build/app.min.js':['lib/index.js','lib/test.js']
                }
            }
        }
    })
    ...
}
优点
  • 灵活,只执行我们定义的任务
  • 有大量现成的插件
缺点
  • 集成度不高,需要些大量配置
  • 相当于进阶版npm script

3. Gulp

基于的自动化构建工具。除了可以管理和执行任务,还支持监听读写文件。简单例子:

var gulp = require('gulp');     //引用基础模块
var uglify = require('gulp-uglify');    //js压缩模块

gulp.task('script',function(){  //启动任务script
  gulp.src('js/*.js')           //找到文件
  .pipe(uglify())               //压缩文件
  .pipe(gulp.dest('dist/js'))   //另存压缩文件
});
//监听
gulp.task('auto',function () {
  gulp.watch('js/*.js',['script']);     //监听script任务
  gulp.watch('css/*.css',['css']);      //监听css任务
  gulp.watch('images/*.*',['images']);  //监听images任务
});
优点
  • 灵活,可单独使用也可搭配其他工具
  • 集成度不高
缺点
  • 加强版Grunt,增加文件监听,文件读写,流式处理任务
  • 相当于进阶版npm script

4. fis3

fis3相对于前面的工具,集成了Web开发中常用的构建功能:

  • 资源定位:分离开发路径与部署路径之间的关系,工程师只需要使用相对路径来定位自己的开发资源,代码容易移植
  • 文件指纹:输出文件时,为文件url+md5戳,优化缓存
  • 文件编译:通过parser配置文件解析器做文件转换
  • 压缩资源:在文件中通过match配置压缩器,实现前端工程优化
  • 图片合并:CssSprite(雪碧图)配置,合并多个css导入的图片到一个图片,减少http请求
优点
  • 灵活,只执行我们定义的任务
  • 有大量现成的插件
缺点
  • 集成了Web开发中常用的构建功能,配置简单,开箱即用
  • 官方不再维护和更新,不支持最新版本的node.js
  • 是一个专注于web开发的完整解决方案

5. Webpack

webpack是一个打包模块化js的工具,在webpack里,一切文件都是模块,通过Loader转换文件,通过plugin注入钩子,最后输出由多个模块组成的文件。webpack专注于构建模块化项目。

优点
  • 专注于模块化,开箱即用一步到位
  • 通过plugin拓展,完整好用又不失灵活
  • 使用场景不局限于web开发
  • 社区庞大活跃
  • 良好的开发体验
缺点
  • 只能用于模块化开发

6.Rollup

Rollup是一个类似于Webpack模块打包工具,但专注于ES6的模块化。

优点:
  • 能对es6的源码进行Tree Shaking(简单介绍剔除无效代码,稍微详细点就是可以去除已经被定义却没被使用的代码并进行Scope Hoisting(作用域提升),以减小输出文件的大小和提升运行性能。)
缺点:
  • 打包时不支持code Spliting(对打包生成的bundle.js文件进行分割成chunk块),所以没有模块加载、执行和缓存的代码。好处是打包js库时,文件更小,但是功能不够完善
  • 插件库比较少,社区不够活跃

7.parcel

parcel是一款刚诞生不久的新型打包器,并且短短几周内就获得大量赞同。

优点:
  • 快速打包:parcel使用工作进程启用多核编译,并且有文件系统缓存,重新启动后也可以快速构建
  • 打包所有资源:支持JS,CSS,HTML,文件资源等等 - 不需要安装任何插件。
  • 自动转换:在需要时,代码使用 Babel,PostCSS 和 PostHTML 自动转换
  • 零配置代码拆分:使用动态 import() 语法拆分您的输出包,所以只加载初始加载时所需的内容。
  • 模块热替换:在开发过程中进行更改时,Parcel 会自动更新浏览器中的模块,不需要进行任何配置。
  • 友好的错误记录
缺点:
  • 不支持 SourceMap :在开发模式下,Parcel 也不会输出 SourceMap,目前只能去调试可读性极低的代码;
  • 不支持剔除无效代码 ( TreeShaking ):很多时候我们只用到了库中的一个函数,结果 Parcel 把整个库都打包了进来;
  • 零配置的实现实质是默认值,Parcel 只要在目录中发现这些配置文件就会认为该项目中的代码需要被处理,导致某些已经被处理的库可能会被多次处理
  • 某些配置被关闭,在特定场景不适用
  • 只专注于构建用于运行在浏览器中的网页,不像webpack一样可以打包发布npm的库,构建nodejs同构应用等

发展历史

  • npm script 和grunt, web开发要做的事情变多,流程复杂,引入自动化思想
  • Gulp时代,出现一些新语言提高开发效率,流式处理思想的出现,简化了文件转换的流程
  • webpack时代,单页应用流行,网页功能更加复杂和庞大,web开发向模块化改进,

作用

1. 实现模块化和版本管理

当项目比较庞大时,需要引入不同的库,带来了以下问题:

不同库命名空间冲突(例如jq和zepto都使用了window.$)
库之间有依赖,需要控制加载顺序
需要管理库的版本
这种情况下,模块化的思想出现了:将复杂系统分割成多个模块以方便开发。 主要的模块划规范:

commonJS

一种js模块化规范,commonJS的核心是通过requrire方法,同步加载所依赖的其他模块,通过module.exports导出需要的接口,具体使用方式在此不深入

优点
  • 代码在nodeJS的环境下能运行
  • Npm发布的第三方模块很多都采用了commonJS规范:
缺点
  • 无法直接运行在浏览器环境,必须借助工具转换
AMD

另一种js模块化规范,与 commonJS的关键区别是异步加载所依赖的模块。AMD主要针对浏览器环境的模块化,代表实现是requirejs

优点
  • 可直接运行于浏览器
  • 可以异步加载
  • 可以并行加载多个依赖
  • 代码可运行在浏览器和nodejs环境
缺点
  • 需要先引入实现了AMD的库才能使用
ES6模块化

ES6在语言层面实现模块化,通过使用importexport导入和导出模块。ES6的模块化将要逐渐取代Commonjs和AND规范,是模块化的终极解决方案。

优点
  • 是模块化的终极解决方案
缺点
  • 目前无法直接运行在大部分的js运行环境,需要借助构建工具等转换成es5

2. 实现工程化和自动化

前端工程化的意义,是为了提高编码->测试->维护 的运行效率,主要从开和部署两方面来入手:开发方面需要做好代码规范和开发模块化;部署阶段的主要流程包括:

  1. 代码检查
  2. 代码合并和压缩
  3. 代码编译
  4. 单元测试

工程化就是借助构建工具实现流程自动化,而前端自动化可以理解为在工程化上做更进一步的自动化。

3. 性能优化

从前文对构建工具的介绍可以看出,这里的性能优化主要以下方面:

  1. 代码文件压缩,压缩Html、Css、Javascript等文件,减小体积
  2. 图片压缩和合并,例如广为人知的Sprite(雪碧图)技术

4. 提供热重载

热重载也就是自动刷新,主要是监听本地源代码变化,自动重新构建和刷新浏览器,随着新的技术框架的出现,例如Vue,React等,这门技术也基本成为了开发标配。

小结

如果内容有错误的地方欢迎指出(觉得看着不理解不舒服想吐槽也完全没问题);如果对你有帮助,欢迎点赞和收藏,转载请征得同意后著明出处,如果有问题也欢迎私信交流,主页有邮箱地址

参考资料,吴浩麟《深入浅出 Webpack》


安歌
7k 声望5.5k 粉丝

目前就职于Ringcentral厦门,随缘答题, 佛系写文章,欢迎私信探讨.