构建用途:
构建就是做这件事情,把源代码转换成发布到线上的可执行 JavaScrip、CSS、HTML 代码,包括如下内容。
代码转换:TypeScript 编译成 JavaScript、SCSS 编译成 CSS 等。
文件优化:压缩 JavaScript、CSS、HTML 代码,压缩合并图片等。
代码分割:提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载。
模块合并:在采用模块化的项目里会有很多个模块和文件,需要构建功能把模块分类合并成一个文件。
自动刷新:监听本地源代码的变化,自动重新构建、刷新浏览器。
代码校验:在代码被提交到仓库前需要校验代码是否符合规范,以及单元测试是否通过。
自动发布:更新完代码后,自动构建出线上发布代码并传输给发布系统。
Npm Script
Npm 是在安装 Node.js 时附带的包管理器,Npm Script 则是 Npm 内置的一个功能,允许在 package.json 文件里面使用 scripts 字段定义任务
里面的 scripts 字段是一个对象,每个属性对应一段 Shell 脚本
"scripts": {
"start": "cross-env node build/devServer.js",
"dev": "cross-env node build/devServer.js",
}
其底层实现原理是通过调用 Shell 去运行脚本命令,例如执行 npm run dev
命令等同于执行命令 cross-env node build/devServer.js
Grunt
Grunt 和 Npm Script 类似,也是一个任务执行者。Grunt 有大量现成的插件封装了常见的任务,也能管理任务之间的依赖关系,自动化执行依赖的任务,每个任务的具体执行代码和依赖关系写在配置文件 Gruntfile.js
里
module.exports = function(grunt) {
// 所有插件的配置信息
grunt.initConfig({
// uglify 插件的配置信息
uglify: {
app_task: {
files: {
'build/app.min.js': ['lib/index.js', 'lib/test.js']
}
}
},
// watch 插件的配置信息
watch: {
another: {
files: ['lib/*.js'],
}
}
});
// 告诉 grunt 我们将使用这些插件
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
// 告诉grunt当我们在终端中启动 grunt 时需要执行哪些任务
grunt.registerTask('dev', ['uglify','watch']);
};
Grunt的优点是:
灵活,它只负责执行你定义的任务;
大量的可复用插件封装好了常见的构建任务。
Grunt的缺点是集成度不高,要写很多配置后才可以用,无法做到开箱即用
Gulp
Gulp 是一个基于流的自动化构建工具。 除了可以管理和执行任务,还支持监听文件、读写文件。Gulp 被设计得非常简单,只通过下面5种个方法就可以胜任几乎所有构建场景:
- 通过
gulp.task
注册一个任务; - 通过
gulp.run
执行任务; - 通过
gulp.watch
监听文件变化; - 通过
gulp.src
读取文件; - 通过
gulp.dest
写文件。
// 引入 Gulp
var gulp = require('gulp');
// 引入插件
var jshint = require('gulp-jshint');
var sass = require('gulp-sass');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
// 编译 SCSS 任务
gulp.task('sass', function() {
// 读取文件通过管道喂给插件
gulp.src('./scss/*.scss')
// SCSS 插件把 scss 文件编译成 CSS 文件
.pipe(sass())
// 输出文件
.pipe(gulp.dest('./css'));
});
// 合并压缩 JS
gulp.task('scripts', function() {
gulp.src('./js/*.js')
.pipe(concat('all.js'))
.pipe(uglify())
.pipe(gulp.dest('./dist'));
});
// 监听文件变化
gulp.task('watch', function(){
// 当 scss 文件被编辑时执行 SCSS 任务
gulp.watch('./scss/*.scss', ['sass']);
gulp.watch('./js/*.js', ['scripts']);
});
Gulp 的优点是:
好用又不失灵活,既可以单独完成构建也可以和其它工具搭配使用。其缺点是和 Grunt 类似,集成度不高,要写很多配置后才可以用,无法做到开箱即用
Fis3
常用构建功能,如下所述。
读写文件:通过 fis.match 读文件,release 配置文件输出路径。
资源定位:解析文件之间的依赖关系和文件位置。
文件指纹:通过 useHash 配置输出文件时给文件 URL 加上 md5 戳来优化浏览器缓存。
文件编译:通过 parser 配置文件解析器做文件转换,例如把 ES6 编译成 ES5。
压缩资源:通过 optimizer 配置代码压缩方法。
图片合并:通过 spriter 配置合并 CSS 里导入的图片到一个文件来减少 HTTP 请求数。
// 加 md5
fis.match('*.{js,css,png}', {
useHash: true
});
// fis3-parser-typescript 插件把 TypeScript 文件转换成 JavaScript 文件
fis.match('*.ts', {
parser: fis.plugin('typescript')
});
// 对 CSS 进行雪碧图合并
fis.match('*.css', {
// 给匹配到的文件分配属性 `useSprite`
useSprite: true
});
// 压缩 JavaScript
fis.match('*.js', {
optimizer: fis.plugin('uglify-js')
});
// 压缩 CSS
fis.match('*.css', {
optimizer: fis.plugin('clean-css')
});
// 压缩图片
fis.match('*.png', {
optimizer: fis.plugin('png-compressor')
});
Fis3的优点是:
集成了各种 Web 开发所需的构建功能,配置简单开箱即用。其缺点是:目前官方已经不再更新和维护,不支持最新版本的 Node.js。
Webpack
Webpack 是一个打包模块化 JavaScript 的工具,在 Webpack 里一切文件皆模块,通过 Loader 转换文件,通过 Plugin 注入钩子,最后输出由多个模块组合成的文件。
Webpack 专注于构建模块化项目,经过 Webpack 的处理,最终会输出浏览器能使用的静态资源。
Webpack的优点是:
专注于处理模块化的项目,能做到开箱即用一步到位;
通过 Plugin 扩展,完整好用又不失灵活;
使用场景不仅限于 Web 开发;
社区庞大活跃,经常引入紧跟时代发展的新特性,能为大多数场景找到已有的开源扩展;
良好的开发体验。
Webpack的缺点是只能用于采用模块化开发的项目。
- Webpack 已经成为构建工具中的首选,这是有原因的:
大多数团队在开发新项目时会采用紧跟时代的技术,这些技术几乎都会采用“模块化+新语言+新框架”,Webpack 可以为这些新项目提供一站式的解决方案;
Webpack 有良好的生态链和维护团队,能提供良好的开发体验和保证质量;
Webpack 被全世界的大量 Web 开发者使用和验证,能找到各个层面所需的教程和经验分享。
Rollup
Rollup 是一个和 Webpack 很类似但专注于 ES6 的模块打包工具。 Rollup 的亮点在于能针对 ES6 源码进行 Tree Shaking 以去除那些已被定义但没被使用的代码,以及 Scope Hoisting 以减小输出文件大小提升运行性能。 然而 Rollup 的这些亮点随后就被 Webpack 模仿和实现
Rollup 在用于打包 JavaScript 库时比 Webpack 更加有优势,因为其打包出来的代码更小更快。 但功能不够完善,很多场景都找不到现成的解决方案。
内容参考: 深入浅出webpack