文章内容输出来源:拉勾教育Java高薪训练营
Yeoman
自定义Generator
// generators/app/index.js
// Generator 核心入口
// 需要导出一个继承自Yeoman Generator的类型
// Yeoman Generator在工作中会自动调用我们在此类型中定义的一些生命周期
// 在这些方法中可以通过调用父类提供的一些工具方法实现一些功能,比如文件写入
const Generator = require('yeoman-generator')
module.exports = class extends Generator{
// yeoman 在询问用户环节会自动调用此方法
// 在此方法中可以调用父类发prompt()方法发出对用户的命令行询问
prompting(){
return this.prompt([
{
type: 'input',
name: 'title',
message: 'Your project name',
default: this.appname // appname为项目上传目录名称
}, {
type: 'input',
name: 'success',
message: 'Your project name',
default: true // appname为项目上传目录名称
}
]).then(answers=>{
this.answers = answers
})
}
writing(){
// Yeoman 自动在生成文件阶段调用此方法
// 我们在这里往项目目录中写入文件
// this.fs.write(
// this.destinationPath('temp.txt'),
// Math.random().toString()
// )
// 通过模板方式写入文件到项目目录
// 在app目录下新建templates目录,用于存放模板文件
// 模板文件路径
const tmpl = this.templatePath('foo.txt')
// 输出路径
const output = this.destinationPath('foo.txt')
// 模板数据上下文
const context = this.answers // {title: 'hello',success:true}
this.fs.copyTpl(tmpl,output,context)
}
}
提交到npm
plop
脚手架工作原理
#!/usr/bin/env node
// node CLI 应用入口文件必须要有这样的文件头
// 如果是linux和macOS系统下还需要修改此文件的读写权限 755
// 可以通过chmod 755 cli.js来实现
// 脚手架工作工程:
// 1. 通过命令行交互询问用户问题
// 2.根据用户回答的结果生成文件
// console.log('working!')
const inquirer = require("inquirer")
const path =require('path')
const fs = require('fs')
const ejs = require('ejs')
inquirer.prompt([
{
type: 'input',
name: 'name',
message: 'Your project name?'
}
]).then(answers=>{
// console.log(answers)
// 模板目录
const tmpDir = path.join(__dirname, 'templates')
// 目标目录
const destDir = process.cwd()
// 将模板下的文件全部转换到目标目录
fs.readdir(tmpDir, (err,files)=>{
if(err) throw err
files.forEach(file=>{
// console.log(file)
// 通过模板引擎渲染文件
ejs.renderFile(path.join(tmpDir,file),answers,(err,res)=>{
if (err) throw err
// console.log(res)
fs.writeFileSync(path.join(destDir,file),res)
})
})
})
})
npm script 自动化构建sass
"scripts":{
"build": "sass sass/main.scss css/main.css --watch",
// "preserve": "yarn build",
"serve": "browser-sync . --files \"css/*.css\"",
"start": "run-p build server"
}
Grunt
// Grunt 的入口文件
// 用于定义一些需要Grunt自动执行的任务
// 需要导出一个函数
// 此函数接受一个Grunt的形参,内部提供一些创建任务可以用到的API
module.exports = grunt =>{
grunt.registerTask('foo',()=>{
console.log('hello grunt~')
})
grunt.registerTask('bar',' 任务描述',()=>{
console.log('other task~')
})
// default为默认,直接执行yarn grunt
// grunt.registerTask('default',()=>{
// console.log('default task~')
// })
// 执行yarn grunt,会依次执行foo和bar
grunt.registerTask('default',['foo','bar'])
// 不支持异步
// grunt.registerTask('async-task',()=>{
// setTimeout(()=>{
// console.log("async task working!")
// },1000)
// })
// 需要this.async()来解决异步问题
// 而且不能使用箭头函数,需要使用function(){}
grunt.registerTask('async-task',function(){
const done = this.async()
setTimeout(()=>{
console.log("async task working!")
done()
},1000)
})
}
Grunt 任务失败
Grunt配置方法
module.exports = grunt =>{
grunt.initConfig({
foo: 'bar',
bar: {
foo: 'foo'
}
})
grunt.registerTask('foo',()=>{
// 显示 'bar'
console.log(grunt.config('foo'))
// 显示 'foo'
console.log(grunt.config('bar.foo'))
})
Grunt多任务
grunt.initConfig({
build:{
// 配置选项,不是任务
// 可以通过this.options()获取
options:{},
// 如果
// css: {
// 在执行css时通过this.options()获取,不会获取外部的options
// options:{}
// }
css:'1',
js:'2'
}
})
grunt.registerMultiTask('build',function(){
console.log(`target: ${this.target}, data:${this.data}`)
})
Grunt 插件的使用
grunt.initConfig({
// 插件的配置
})
grunt.loadNpmTasks('[插件名称]')
Grunt常用的插件
gulp基本使用
// gulp入口文件
exports.foo = done=>{
console.log('foo task working~')
done() // 标识任务完成
}
exports.default = done=>{
console.log('default task working~')
done() // 标识任务完成
}
// 目前不推荐使用,推荐使用上面的方式
const gulp = require('gulp')
gulp.task('bar',done=>{
console.log('var task working~')
done() // 标识任务完成
})
gulp组合任务
// gulp组合任务
const { series, parallel } = require('gulp')
const foo = done=>{
console.log('foo task working~')
done() // 标识任务完成
}
const foo1 = done=>{
console.log('foo1 task working~')
done() // 标识任务完成
}
// 执行yarn gulp task1,会依次执行foo,foo1
// 串行执行任务,就是一个个执行
exports.task1 = series(foo, foo1)
// 并行执行任务,就是一起执行
exports.task2 = parallel(foo,foo1)
gulp异步任务
//Error
// 如果时多任务执行时,报错后不执行后面的内容
exports.callback_error = done=>{
console.log('callback task working~')
done(new Error('tsak failed!'))
}
// pomise
exports.promise = ()=>{
console.log('promise task working~')
return Promise.resolve()
}
exports.promise_error = ()=>{
console.log('promise task working~')
return Promise.reject(new Error('task failed!'))
}
// async
const timeout = time=>{
return new Promise(resolve=>{
setTimeout(resolve,time)
})
}
exports.async = async ()=>{
await timeout(1000)
console.log('async task~')
}
const fs = require('fs')
// exports.stream = ()=>{
// const readStream = fs.createReadStream('package.json')
// const writeStream = fs.createWriteStream('temp.txt')
// readStream.pipe(writeStream)
// return readStream
// }
// return 可以识别为在end事件执行done()
exports.stream = done=>{
const readStream = fs.createReadStream('package.json')
const writeStream = fs.createWriteStream('temp.txt')
readStream.pipe(writeStream)
readStream.on('end',()=>{
done()
})
}
gulp压缩css
// 压缩css
const fs = require('fs')
const {Transform} = require('stream')
exports.minicss = ()=>{
const readCss = fs.createReadStream('main.css')
const writeCss = fs.createWriteStream('main.min.css')
const transform = new Transform({
transform:(chunk, encoding, callback)=>{
// 核心转换实现
// chunk=> 读取流中读取到的内容(buffer)
const input = chunk.toString()
const output = input.replace(/\s+/g,'').replace(/\/\/*.+?\*\//g,'')
// null为报错配置
callback(null,output)
}
})
readCss.pipe(transform).pipe(writeCss)
return readCss
}
使用gulp API实现css压缩
// gulp API
const {src,dest} = require('gulp')
const cleanCss = require('gulp-clean-css')
const rename = require('gulp-rename')
exports.apitest = ()=>{
return src('main.css') // src('css/*.css)
.pipe(cleanCss())
.pipe(rename({extname:'.min.css'})) // 重命名后缀
.pipe(dest('dist'))
}
gulp项目基本配置
gulp 自动加载插件
const gulp = require('gulp');
const plugins = require('gulp-load-plugins')();
gulp开发服务器
const serve = ()=>{
bs.init({
// 关闭浏览器右上方的提示
notify: false,
// localhost的端口
port:2080,
// 自动打开浏览器页面关闭
open: false,
// 监听文件,当dist下文件改动,浏览器更新
files: 'dist/**',
server:{
baseDir: 'dist',
// 将路径替换,可以是在html里的link或是script
router:{
'/node_modules': 'node_modules'
}
}
})
}
gulp源文件监听更新视图
gulp文件引用处理
gulp文件压缩
- 样式编译
- 脚本编译
- html模板编译
- 图片和字体文件编译
- 其他文件复制和dist文件自动清除
- 自动加载插件
- 开发服务器和热更新,监听dist和源码触发更新
- 监听源码优化
- 文件引用路径处理
- 文件压缩,代码混淆