前端工程化及自动化

前端工程化

主要解决的问题

  • 传统语言或语法的弊端
  • 无法使用模块化/组件化
  • 重复的机械式工作
  • 代码风格统一、质量保证
  • 依赖后端服务接口支持
  • 整体依赖后端项目

工程化表现

一切以提高效率、降低成本、质量保证为目的的手段都属于工程化
一切重复的工作都应该被自动化

自动化构建

自动化构建工作流

把开发中的源代码,自动化的转换成生产代码,脱离运行环境兼容带来的问题,使用提高效率的语法、规范和标准。
例如使用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更像一种捆绑套餐,它把项目中典型的需求尽可能的集成在了内部,
例如资源加载、模块化开发、代码部署、性能优化

你可能感兴趣的:(前端工程化及自动化)