前端工程化及自动化

前端工程化

主要解决的问题

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

工程化表现

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

自动化构建

自动化构建工作流

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,542评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,822评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,912评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,449评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,500评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,370评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,193评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,074评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,505评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,722评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,841评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,569评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,168评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,783评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,918评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,962评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,781评论 2 354