前端工程化
主要解决的问题
- 传统语言或语法的弊端
- 无法使用模块化/组件化
- 重复的机械式工作
- 代码风格统一、质量保证
- 依赖后端服务接口支持
- 整体依赖后端项目
工程化表现
一切以提高效率、降低成本、质量保证为目的的手段都属于工程化
一切重复的工作都应该被自动化
自动化构建
自动化构建工作流
把开发中的源代码,自动化的转换成生产代码,脱离运行环境兼容带来的问题,使用提高效率的语法、规范和标准。
例如使用ECMAScript最新标准提高编码效率和质量,利用SASS增强CSS的可编程性,借助模板引擎抽象抽象HTML,这些用法大都不被浏览器直接支持,
所以通过自动化构建的方式转换那些不被支持的特性。
常见的自动化构建工具
Grunt
插件系统非常完善,由于工作过程基于临时文件实现的,所以构建速度相对较慢,例如使用Grunt完成项目中,
SASS文件的构建,一般会先对SASS文件做编译操作,然后自动添加私有属性前缀,最后压缩代码,这个过程中,
Grunt每一步都有磁盘读写操作,例如SASS编译后,Grunt会将结果写入一个临时的文件,然后下一个插件再去
读取这个临时文件进行下一步操作,所以大型项目中,处理的文件越多,构建的越慢
// Grunt 入口文件
// 用于定义grunt自动执行的任务
// 需要导出一个函数
// 此函数接受一个grunt形参,内部提供一些创建任务时可以用到的API
module.exports = grunt => {
// 注册任务 npx grunt foo
grunt.registerTask('foo', () => {
console.log('grunt11111')
})
// 任务描述 npx grunt --help
grunt.registerTask('bar', '任务描述', () => {
})
// 默认任务 名称为default会成为grunt的默认任务
// npx grunt
// grunt.registerTask('default', () => {
//
// })
// 一般会用default映射一些其他的任务
grunt.registerTask('default', ['foo', 'bar'])
// 异步任务
grunt.registerTask('async-tast', function () {
const done = this.async()
setTimeout(() => {
console.log(111111)
done()
}, 1000)
})
// 配置方法
grunt.initConfig({
qwe: 'bar',
a: {
b:1
},
build: { // 多目标配置必须是对象
options: {
// options中指定的信息会作为任务的配置选项出现
qqq: 'bar'
},
css: {
options: {
// 键重复时会覆盖build中的options
qqq: '123'
}
},
js: '2',
}
})
grunt.registerTask('qwe', () => {
console.log(grunt.config('qwe'));
console.log(grunt.config('a.b'))
})
// 多目标任务
// 多目标模式可以让任务根据配置形成多个子任务
// 通过initConfig配置目标
// 如果想指定目标: npx grunt build:css
grunt.registerMultiTask('build', function () {
console.log(this.target, this.data)
console.log(this.options())
})
// 加载插件
// 名称规范grunt-contrib-Task(任务名) npx grunt clean
grunt.loadNpmTasks('grunt-contrib-clean')
}
Gulp
对于文件的处理环节都是基于内存实现的,相对于磁盘读写快了很多,很好的解决了Grunt临时文件的问题,
默认支持同时执行多个任务
// gulpfile入口文件
// 运行在node环境,可以使用CommonJS规范
// 新版本的gulp取消了同步代码模式,约定每个任务必须是一个异步任务
// 当任务执行完成需要调用回调函数或其他方式标记任务已经完成
exports.foo = done => {
console.log('gulp working')
// 标识任务完成
done()
}
// defalut 默认任务
exports.default = done => {
done()
}
// 4.0版本以前,需要gulp模块中的方法注册任务
const gulp = require('gulp')
gulp.task('bar', done => {
done()
})
// gulp异步任务
exports.cb = done => {
done() // 通过调用回调函数通知标识任务完成
// 这个回调函数与node中回调函数是同一个标准,都是错误优先的回调函数
// 如果想在运行中抛出一个错误,阻止剩下任务的执行
// done(new Error('xxxx'))
}
// gulp同样也支持promise的方式
exports.promise = () => {
// 成功任务
return Promise.resolve() // 不需要传值,gulp会忽略掉传值
// 也可以返回失败任务,结束后续任务执行
// return Promise.reject(new Error('12111'))
}
// 也支持async...await
let time = time => {
return new Promise(res => {
setTimeout(res, time)
})
}
exports.async = async() => {
await time(1000)
console.log(111)
}
// 常用的就是文件流方式
const fs = require('fs')
exports.stream = () => {
const readStream = fs.createReadStream('package.json')
const writeStream = fs.createWriteStream('temp11.txt')
readStream.pipe(writeStream)
return readStream
// stream中都有一个end事件,任务结束的时机就是readStream end的时候
// 当读取文件的文件流完成以后会触发end事件
// gulp接收到stream之后会注册一个end事件
// readStream.on('end', () => {
// done()
// })
}
// gulpfile入口文件
// 运行在node环境,可以使用CommonJS规范
// 新版本的gulp取消了同步代码模式,约定每个任务必须是一个异步任务
// 当任务执行完成需要调用回调函数或其他方式标记任务已经完成
exports.foo = done => {
console.log('gulp working')
// 标识任务完成
done()
}
// defalut 默认任务
exports.default = done => {
done()
}
// 4.0版本以前,需要gulp模块中的方法注册任务
const gulp = require('gulp')
gulp.task('bar', done => {
done()
})
// gulp异步任务
exports.cb = done => {
done() // 通过调用回调函数通知标识任务完成
// 这个回调函数与node中回调函数是同一个标准,都是错误优先的回调函数
// 如果想在运行中抛出一个错误,阻止剩下任务的执行
// done(new Error('xxxx'))
}
// gulp同样也支持promise的方式
exports.promise = () => {
// 成功任务
return Promise.resolve() // 不需要传值,gulp会忽略掉传值
// 也可以返回失败任务,结束后续任务执行
// return Promise.reject(new Error('12111'))
}
// 也支持async...await
let time = time => {
return new Promise(res => {
setTimeout(res, time)
})
}
exports.async = async() => {
await time(1000)
console.log(111)
}
// 常用的就是文件流方式
const fs = require('fs')
exports.stream = () => {
const readStream = fs.createReadStream('package.json')
const writeStream = fs.createWriteStream('temp11.txt')
readStream.pipe(writeStream)
return readStream
// stream中都有一个end事件,任务结束的时机就是readStream end的时候
// 当读取文件的文件流完成以后会触发end事件
// gulp接收到stream之后会注册一个end事件
// readStream.on('end', () => {
// done()
// })
}
// gulp构建过程核心工作原理
const fs = require('fs')
const { Transform } = require('stream')
exports.default = () => {
// 创建文件读取流
let read = fs.createReadStream('demo.js')
// 文件写入流
let write = fs.createWriteStream('demo11.min.js')
// 文件转换流
let transform = new Transform({
transform(chunk, encoding, callback) {
// 核心转换过程
// chunk -> 读取流中读取道德内容(Buffer)
// 由于读取出来的是字节数组所以通过toString方法转换为字符串
let input = chunk.toString()
// 替换空白字符和注释
let output = input.replace(/\s+/g, '').replace(/\/\*.+?\*\//g, '')
// 错误优先的回调,第一个参数是错误回调,没有错误传入noll
callback(null, output)
}
})
// 把读取出来的文件流导入到写入文件流
read.pipe(transform) //转换
.pipe(write)
// return 后 gulp会根据流的状态判断任务是否完成
return read
}
// gulp的官方定义就是the streaming build system 基于流的构建系统
// gulp希望实现一个构建管道的概念,这样后续做扩展插件的时候就会有一个统一的方式
FIS
百度前端团队推出的一款构建系统,相对于Grunt和Gulp,FIS更像一种捆绑套餐,它把项目中典型的需求尽可能的集成在了内部,
例如资源加载、模块化开发、代码部署、性能优化