1、

传统语言或语法的弊病:

无奈应用模块化/组件化

通过机器去取代人的一些重复性工作

多人合作开发,无奈硬性对立大家的代码格调,从仓库pull回来

局部性能须要期待后端服务接口提前完成

整体依赖后端我的项目(公布的时候)

2、

工程化体现

创立

编码 :对立代码格调

预览 :web/mock ;live/reloading/hmr ; source map

提交:git hook、lint-staged、继续集成

部署:CI/CD,主动公布

3、

工程化不是等于某个工具吗,工具只是咱们用来落地实现,工程化则是一整个布局

一些成熟的工程化集成:create-react-app,vue-cli

4、

工程化是由node赋能的

脚手架工具

1、罕用的脚手架工具

重点关注几个有代表性的工具

2、Yeoman

Yeo次要是一种通用的脚手架工具

3、根本应用

add yo

4、sub generator

yo node:cliyarn link

5、惯例应用步骤

明确你的需要

找到适合的generator

全局范畴内装置generator

通过yo运行generator

通过命令行填写generator选项

生成所需的我的项目构造

yarn global add generator

6、自定义generator

基于yeoman搭建本人的脚手架

generator实质上就是npm模块

命名必须是generator-<name>

yarn add yeoman-generator 通过这条命令来增加

7、依据模板创立文件

8、承受用户的输出

// 此文件作为 Generator 的外围入口// 须要导出一个继承自 Yeoman Generator 的类型// Yeoman Generator 在工作时会主动调用咱们在此类型中定义的一些生命周期办法// 咱们在这些办法中能够通过调用父类提供的一些工具办法实现一些性能,例如文件写入const Generator = require('yeoman-generator')module.exports = class extends Generator {  prompting () {    // Yeoman 在询问用户环节会主动调用此办法    // 在此办法中能够调用父类的 prompt() 办法收回对用户的命令行询问    return this.prompt([      {        type: 'input',        name: 'name',        message: 'Your project name',        default: this.appname // appname 为我的项目生成目录名称      }    ])    .then(answers => {      // answers => { name: 'user input value' }      this.answers = answers //最初会被赋值到context当中    })  }  writing () {    // Yeoman 主动在生成文件阶段调用此办法    // // 咱们这里尝试往我的项目目录中写入文件    // this.fs.write(    //   this.destinationPath('temp.txt'),    //   Math.random().toString()    // )    // -------------------------------------------------------    // // 通过模板形式写入文件到目标目录    // // 模板文件门路    // const tmpl = this.templatePath('foo.txt')    // // 输入指标门路    // const output = this.destinationPath('foo.txt')    // // 模板数据上下文    // const context = { title: 'Hello zce~', success: false }    // this.fs.copyTpl(tmpl, output, context)    // -------------------------------------------------------    // 模板文件门路    const tmpl = this.templatePath('bar.html')    // 输入指标门路    const output = this.destinationPath('bar.html')    // 模板数据上下文    const context = this.answers    this.fs.copyTpl(tmpl, output, context)  }}

9、plop

一个小而美的脚手架工具

会依据之前的配置主动创立文件

10、plop具体应用

将plop模块作为我的项目开发依赖

在我的项目根目录下创立一个plopfile.js文件

在plopfile.js文件中定义脚手架工作

编写用于生成特定类型文件的模板

通过plop进步的cli运行

10、脚手架工作原理

11、罕用的自动化构建工具

grunt:最早的,构建速度较慢,因为其基于临时文件

gulp :构建速度较快

Fis:比拟容易动手

12、grunt

应用grunt.registerTask来注册工作

(default,[foo,bar]) 顺次执行

13、

应用return false ;done(false)来终止工作

14、initConfig设置,config(‘foo’)去取

15、多指标工作

grunt里配置build

grunt.initConfig({    build: {      options: {        msg: 'task options'      },      foo: {        options: {          msg: 'foo target options'        }      },      bar: '456'    }  })

16、grunt插件应用

module.exports = grunt => {  grunt.initConfig({   须要配置clean关键字    clean: {         temp: 'temp/**'      //找到temp下的所有子目录    }  })    grunt.loadNpmTasks('grunt-contrib-clean')}

17、

const sass = require('sass')const loadGruntTasks = require('load-grunt-tasks')module.exports = grunt => {  grunt.initConfig({    sass: {      options: {        sourceMap: true, //生成sourcemap文件        implementation: sass //生成sass文件      },      main: {        files: {          'dist/css/main.css': 'src/scss/main.scss'          // 输入门路:输出门路        }      }    },    babel: {      options: {        sourceMap: true,        presets: ['@babel/preset-env']//preset-env默认依据最新的es进行转换      },      main: {        files: {          'dist/js/app.js': 'src/js/app.js'        }      }    },    watch: {      // grunt-contrib-watch插件      js: {        files: ['src/js/*.js'],//须要监督的文件        tasks: ['babel'] //须要执行什么工作      },      css: {        files: ['src/scss/*.scss'],//须要监督的文件        tasks: ['sass'] //须要执行sass工作      }    }  })  // grunt.loadNpmTasks('grunt-sass')  loadGruntTasks(grunt) // 主动加载所有的 grunt 插件中的工作  grunt.registerTask('default', ['sass', 'babel', 'watch'])}

18、gulp根本应用

都是用yarn gulp 对应输入函数名

// // 导出的函数都会作为 gulp 工作// exports.foo = () => {//   console.log('foo task working~')// }// gulp 的工作函数都是异步的// 能够通过调用回调函数标识工作实现exports.foo = done => {  console.log('foo task working~')  done() // 标识工作执行实现}// default 是默认工作// 在运行是能够省略工作名参数exports.default = done => {  console.log('default task working~')  done()}// v4.0 之前须要通过 gulp.task() 办法注册工作const gulp = require('gulp')gulp.task('bar', done => {  console.log('bar task working~')  done()})

19、gulp组合工作

// 让多个工作依照程序顺次执行exports.foo = series(task1, task2, task3)// 让多个工作同时执行exports.bar = parallel(task1, task2, task3)

20、gulp异步工作的三种形式

exports.promise_error = () => {  console.log('promise task')  return Promise.reject(new Error('task failed'))}应用promiseconst timeout = time => {  return new Promise(resolve => {    setTimeout(resolve, time)  })}exports.async = async () => {  await timeout(1000)  console.log('async task')}应用async语法糖exports.stream = () => {  const read = fs.createReadStream('yarn.lock')  const write = fs.createWriteStream('a.txt')  read.pipe(write)  return read}返回read,会等到read里的end事件触发的时候

21、gulp构建过程外围工作原理

  // 文件读取流  const readStream = fs.createReadStream('normalize.css')  // 文件写入流  const writeStream = fs.createWriteStream('normalize.min.css')  // 文件转换流  const transformStream = new Transform({    // 外围转换过程    // chunk =》 读取流中读取到的内容    transform: (chunk, encoding, callback) => {      const input = chunk.toString()      const output = input.replace(/\s+/g, '').replace(/\/\*.+?\*\//g, '')      callback(null, output)    }  })  return readStream    .pipe(transformStream) // 转换    .pipe(writeStream) // 写入

22、gulp文件操作api和插件的应用

exports.default = () => {  return src('src/*.css')    .pipe(cleanCSS())    .pipe(rename({ extname: '.min.css' }))    .pipe(dest('dist'))}

23、gulp脚本编译

const sass = require('gulp-sass')const babel = require('gulp-babel')const script = () => {  return src('src/assets/scripts/*.js', { base: 'src' })    .pipe(babel({ presets: ['@babel/preset-env'] }))    .pipe(dest('temp'))}

24、自动化加载插件

const loadPlugins = require('gulp-load-plugins')const plugins = loadPlugins()应用plugins.sass({ outputStyle: 'expanded' })

25、开发服务器

const serve = () => {  //应用各种文件  watch('src/assets/styles/*.scss', style)  watch('src/assets/scripts/*.js', script)  watch('src/*.html', page)  // watch('src/assets/images/**', image)  // watch('src/assets/fonts/**', font)  // watch('public/**', extra)  watch([    'src/assets/images/**',    'src/assets/fonts/**',    'public/**'  ], bs.reload)//更新图片字体后,bs.reload会从新发动对于src,public地址下的申请推送到浏览器  bs.init({    notify: false, //关掉提醒    port: 2080,  //指定端口    // open: false, //主动关上浏览器    // files: 'dist/**',  //监听对应的文件    server: {      baseDir: ['temp', 'src', 'public'],    //这样配置就能够顺次申请,找不到就找下一个,这样比方图片、字体这些货色就不必每次都编译了      //baseDir: 'dist',//读取的地址为编译后的文件      routes: {        '/node_modules': 'node_modules'//先看routes里的配置,如果没有      }    }  })}

26、文件援用解决

const useref = () => {  return src('temp/*.html', { base: 'temp' })//文件操作,批改正文实现文件的复制与合并    .pipe(plugins.useref({ searchPath: ['temp', '.'] }))    // html js css     .pipe(plugins.if(/\.js$/, plugins.uglify()))   //须要先执行compile,因为useref执行后会删掉正文,所以执行compile标出正文    .pipe(plugins.if(/\.css$/, plugins.cleanCss()))    .pipe(plugins.if(/\.html$/, plugins.htmlmin({      collapseWhitespace: true, //去除换行符      minifyCSS: true, //sytle标签压缩      minifyJS: true     })))    .pipe(dest('dist'))}

27、重构构建过程

// 上线之前执行的工作const build =  series(  clean,  parallel(    series(compile, useref),    image,    font,    extra  ))

创立temp文件地址,平时compile都放到这里,最初通过useref放到dis

28、gulp补充

自动化构建案例

module.exports = {  clean,  build,  develop}

其余的工作都是这些大工作里的子工作

29、解决模块中的问题

const cwd = process.cwd()//读取文件中pages.config文件try {  const loadConfig = require(`${cwd}/pages.config.js`)  config = Object.assign({}, config, loadConfig)} catch (e) {}