常用的自动化构建工具 Grunt Gulp FIS
image.png-
Grunt
yarn init --yes 添加package.json
yarn add grunt 添加grunt模块
code gruntfile.js 添加gruntfile文件 (Grunt 的入口文件,用于定义一些需要Grunt自动执行的任务)使用
// Grunt 的入口文件
// 用于定义一些需要Grunt自动执行的任务
/**
* 需要导出一个函数
* 次函数接收一个grunt的形参,内部提供一些创建任务时候可以用到的API
*
*/
module.exports = grunt => {
// 使用registerTask 注册一个任务
grunt.registerTask('foo', () => {
console.log('hello grunt 测试');
})
grunt.registerTask('bar', '任务描述', () => {
console.log('第二个参数是当前任务的描述');
})
// grunt.registerTask('default',() => {
// console.log('默认任务,调用不需要指定人物名');
// })
// grunt.registerTask('default', ['foo', 'bar']); //默认同时执行两个任务
grunt.registerTask('asyncTask', () => {
setTimeout(() => {
console.log('grunt 默认支持同步任务当前写法不打印');
}, 1000);
})
grunt.registerTask('asyncTask1', function () {
const done = this.async();
setTimeout(() => {
console.log('grunt 异步 需要使用this,所以不使用箭头函数,当done()被执行,grunt才会结束任务');
done();
}, 1000);
})
}
yarn grunt <任务名> 执行
- Grunt标记任务失败
grunt.registerTask('foo', () => {
console.log('hello grunt 测试');
return false;
})
grunt.registerTask('bad', () => {
console.log('hello grunt 测试');
})
grunt.registerTask('far', () => {
console.log('hello grunt 测试');
})
grunt.registerTask('default', ['bad', 'foo','far']);
grunt.registerTask('fooAsync', () => {
const done = this.async();
setTimeout(() => {
console.log('grunt 异步 需要使用this,所以不使用箭头函数,当done()被执行,grunt才会结束任务');
done(false);
}, 1000);
})
当任务里有return false,后面的语句将都不会执行;
当运行yarn grunt default --force ,即使运行失败了,后面也会执行
异步任务标记失败,需要在done()中传递实参false,既done(false)
- Grunt 配置方法
grunt.initConfig({
foo:{
bar:123
},
red:132
})
grunt.registerTask('init-config', () => {
console.log(grunt.config('foo.bar'));
console.log(grunt.config('red'));
})
- Grunt 多任务
module.exports = grunt => {
grunt.initConfig({
build: {
options: { //配置选项
foo: "bar"
},
css: '1',
js: '2',
vue: {
options: { //配置选项
foo: "baz";//会覆盖原有的配置项
},
}
}
})
// 多目标模式,可以让任务根据配置形成多个子任务
grunt.registerMultiTask('build', function () {
console.log(this.options()); //可以获取配置选项
console.log(`target:${this.target},data:${this.data}`); //target:css,data:1; target:js,data:2
})
}
- Grunt 插件的使用
安装插件
yarn add grunt-contrib-clean
gruntfile.js
module.exports = grunt =>{
grunt.initConfit({
clean:{
temp:'temp/***'
}
})
grunt.loadNpmTasks('grunt-contrib-clean')
}
- Grunt 常用插件及总结
sass的基本使用
yarn add grunt-sass sass --dev
gruntfile.js
const sass = require("sass");
module.exports = (grunt) => {
grunt.initConfig({
sass: {
options: {
sourceMap: true,
implementation: sass,
},
main: {
files: {
"dist/css/main.css": "src/scss/main.scss",
},
},
},
});
grunt.loadNpmTasks("grunt-sass");
};
//执行
yarn grunt sass
es6语法编译器
yarn add grunt-babel @babel/core @babel/preset-env --dev
减少loadNpmTasks的使用
yarn add load-grunt-tasts --dev
const loadGruntTasks = require("load-grunt-tasks");
module.exports = (grunt) => {
grunt.initConfig({
babel: {
options: {
presets: ["@babel/preset-env"],
},
main: {
files: {
"dist/js/app.js": "src/js/app.js",
},
},
},
});
loadGruntTasks(grunt); //自动加载所有的grunt插件中的任务
};
//执行任务
yarn grunt babel
自动编译插件
yarn add grunt-contrib-watch --dev
const sass = require("sass");
const loadGruntTasks = require("load-grunt-tasks");
module.exports = (grunt) => {
grunt.initConfig({
sass: {
options: {
sourceMap: true,
implementation: sass,
},
main: {
files: {
"dist/css/main.css": "src/scss/main.scss",
},
},
},
babel: {
options: {
presets: ["@babel/preset-env"],
},
main: {
files: {
"dist/js/app.js": "src/js/app.js",
},
},
},
watch: {
js: {
files: ["src/js/*.js"],
tasks: ["babel"],
},
css: {
files: ["src/scss/*.scss"],
tasks: ["sass"],
},
},
});
// grunt.loadNpmTasks("grunt-sass");
loadGruntTasks(grunt); //自动加载所有的grunt插件中的任务
grunt.registerTask("default", ["sass", "babel", "watch"]);
// 运行 yarn grunt
};
-
Gulp 的基本使用
yarn init --yes 添加package.json
yarn add gulp --dev 添加gulp 模块
code gulpfile.js 添加gulpfile文件 (gulp 的入口文件,用于定义一些需要gulp 自动执行的任务)使用
gulpfile.js
// glup 入口文件
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('bar working');
done();
})
- Gulp 的组合任务
// glup 入口文件
const {series,parallel} = require('gulp')
const task1 = done =>{
setTimeout(()=>{
console.log('task1 working');
done();
},1000)
}
const task2 = done =>{
setTimeout(()=>{
console.log('task2 working');
done();
},1000)
}
const task3 = done =>{
setTimeout(()=>{
console.log('task3 working');
done();
},1000)
}
exports.foo = series(task1,task2,task3);// series自动按照顺序自动执行任务
exports.bar = parallel(task1,task2,task3) // parallel 并行执行任务
执行 yarn gulp foo
执行 yarn gulp bar
image.png
- Gulp 的异步任务
// glup 入口文件
const fs = require('fs');
exports.callback = done =>{
console.log('callback task~');
done();
}
exports.callback_error = done =>{
console.log('callback task~');
done(new Error('task failed!')); //错误信息
}
exports.promise =()=>{
console.log('promise task!');
return Promise.resolve();
}
exports.promise_error =()=>{
console.log('promise task!');
return Promise.reject(new Error('task failed!'));
}
const timeout = time=>{
return new Promise(resolve=>{
setTimeout(resolve,time)
})
}
exports.async = async()=>{
await timeout(1000)
console.log('async task~');
}
exports.stream = ()=>{
const readStream = fs.createReadStream('package.json')
const writeStream = fs.createWriteStream('temp.txt')
readStream.pipe(writeStream)
return readStream
}
exports.stream_end = (done)=>{
const readStream = fs.createReadStream('package.json')
const writeStream = fs.createWriteStream('temp2.txt')
readStream.pipe(writeStream)
readStream.on('end',()=>{
console.log('OK!');
done();
})
}
- Gulp 构建过程核心工作原理
const fs = require('fs')
const {Transform} = require('stream')
exports.default = ()=>{
// 读取文件流
const read = fs.createReadStream('normalize.css')
// 文件写入流
const write = fs.createWriteStream('normalize.min.css')
// 文件转换流
const transform = new Transform({
transform:(chunk,encoding,callback)=>{
// 核心转换过程
// chunk ==>读取流中的内容(Buffer)
const input = chunk.toString();
const output = input.replace(/\s+/g,'').replace(/\/\*.+?\*\//g,'')
callback(null,output)
}
})
// 把读取数来的文件流倒入写入文件流
read.pipe(transform).pipe(write)
return read;
}
- Gulp 文件操作API
压缩转换css流
yarn add gulp-clean-css --dev
后缀重命名
yarn add gulp-rename --dev
const { src, dest } = require("gulp");
const cleanCss = require("gulp-clean-css"); //压缩css插件
const rename = require("gulp-rename"); //重命名的扩展名
exports.default = () => {
// return src("src/index.css").pipe(dest("dist"));
return src("src/*.css")
.pipe(cleanCss())
.pipe(rename({ extname: ".min.css" }))
.pipe(dest("dist"));
};
- Gulp 案例-样式编译
yarn add gulp --dev // 安装gulp
code gulpfile.js //新建gulpfile.js 入口文件
yarn add gulp-sass sass --dev //安装sass 依赖
- Gulp 案例- 脚本编译
yarn add gulp-babel @babel/core @babel/preset-env --dev //安装babel 依赖
- Gulp 案例- 页面模板编译
yarn add gulp-swig --dev //安装swig依赖
- Gulp 案例 - 其他文件及文件清除
yarn add gulp-imagemin@7 --dev 安装压缩图片依赖
因为依赖包里面有二进制文件,这些二进制文件不好下载,所以当下在包出现问题的时候可以参考
yarn add del --dev //安装清除模块
- Gulp 案例 - 自动加载插件
yarn add gulp-load-plugins --dev
- Gulp 案例- 开发服务器
yarn add browser-sync --dev //会提供给我们一个开发服务器
- Gulp 案例- 监视变化以及构建优化
watch("src/assets/styles/*.scss", style);
watch("src/assets/scripts/*.js", script);
watch("src/*.html", page);
watch(
["src/assets/styles/*.scss", "src/assets/scripts/*.js", "src/*.html"],
bs.reload
); //优化上面写法
- Gulp 案例- useref文件引用处理
yarn add gulp-useref --dev //下载插件
- Gulp 案例 - 文件压缩
yarn add gulp-htmlmin gulp-uglify gulp-clean-css --dev //下载压缩html js css 插件
yarn add gulp-if --dev //判断文件类型的插件
// 实现这个项目的构建任务
const { src, dest, parallel, series, watch } = require("gulp");
const del = require("del"); //引入del
const browserSync = require("browser-sync"); //引入服务器browserSync
const loadPlugins = require("gulp-load-plugins"); //引入自动加载模块
const plugins = loadPlugins();
const bs = browserSync.create(); //创建一个服务器
const sass = require("gulp-sass")(require("sass")); //引入gulp-sass
// const babel = require("gulp-babel"); //引入gulp-babel
// const swig = require("gulp-swig"); //引入swig
// const imagemin = require("gulp-imagemin"); //引入gulp-imagemin 压缩图片和svg
const style = () => {
// base:基本路径,保存src下面的文件结构
// outputStyle:'expanded' css中{ } 完全展开
return src("src/assets/styles/*.scss", { base: "src" })
.pipe(sass({ outputStyle: "expanded" }))
.pipe(dest("temp"))
.pipe(bs.reload({ stream: true })); //自动以流的方式推送到浏览器bs.reload({ stream: true })
};
const script = () => {
return src("src/assets/scripts/*.js", { base: "src" })
.pipe(plugins.babel({ presets: ["@babel/preset-env"] }))
.pipe(dest("temp"))
.pipe(bs.reload({ stream: true })); //自动以流的方式推送到浏览器bs.reload({ stream: true })
};
const data = {
menus: [
{
name: "Home",
icon: "aperture",
link: "index.html",
},
{
name: "About",
link: "about.html",
},
{
name: "Contact",
link: "#",
children: [
{
name: "Twitter",
link: "https://twitter.com/w_zce",
},
],
},
],
// pkg: require("./package.json"),
date: new Date(),
};
const page = () => {
// src/**/*.html **下面所有的*.html文件
return src("src/*.html", { base: "src" })
.pipe(
plugins.swig({
data,
defaults: {
// 可能会因为swig模板引擎缓存机制导致页面不变化 所以修改为false 不缓存
cache: false,
},
})
)
.pipe(dest("temp"))
.pipe(bs.reload({ stream: true })); //自动以流的方式推送到浏览器bs.reload({ stream: true })
};
// 图片转换
const image = () => {
return src("src/assets/images/**", { base: "src" })
.pipe(plugins.imagemin())
.pipe(dest("dist"));
};
// 文字转换
const font = () => {
return src("src/assets/fonts/**", { base: "src" })
.pipe(plugins.imagemin())
.pipe(dest("dist"));
};
// 额外的任务
const extra = () => {
return src("public/**", { base: "public" }).pipe(dest("dist"));
};
// 清除
const clean = () => {
// del方法返回的是pormise 会标记任务结束
return del(["dist", "temp"]);
};
// 创建服务器的相关配置
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/styles/*.scss", "src/assets/scripts/*.js", "src/*.html"],
bs.reload
); //优化上面写法
bs.init({
notify: false, //浏览器右上角提示
port: 2021, //端口
// open:false,//是否自动打开浏览器
//当什么文件发生变化时候刷新页面 为路径
// 当.pipe(bs.reload({stream:true})); 存在可以省略files
// files: "dist/**",
server: {
baseDir: ["temp", "src", "public"],
routes: {
"/node_modules": "node_modules", //映射里面引用的node_module里面js等css的引用
},
},
});
};
// 文件引用处理
const useref = () => {
return (
src("temp/*.html", { base: "dist" })
.pipe(plugins.useref({ searchPath: ["dist", "."] }))
//判断是否为html js css
.pipe(plugins.if(/\.js$/, plugins.uglify()))
.pipe(plugins.if(/\.css$/, plugins.cleanCss()))
.pipe(
plugins.if(
/\.html$/,
plugins.htmlmin({
collapseWhitespace: true,
minifyCSS: true,
minifyJS: true,
})
)
)
.pipe(dest("dist"))
);
};
// 组合任务
const compile = parallel(style, script, page);
const develop = series(compile, serve); //先进性编译样式脚本页面,然后在启动服务器
// 上线之前执行的任务
const build = series(
clean,
parallel(series(compile, useref), image, font, extra)
);
module.exports = {
clean,
build,
develop,
};
总结--流程
安装并且引入gulp yarn add gulp
安装并且引入gulp-sass yarn add gulp-sass sass --dev 用于转换sass
安装并且引入babel yarn add gulp-babel @babel/core @babel/preset-env --dev 用于编译js
安装并且引入swig yarn add gulp-swig --dev 用于页面模板编译
安装并且引入imagemin yarn add gulp-imagemin@7 --dev 用于压缩图片svg
安装并引入del yarn add del --dev 用于清空删除
安装并引用自动加载插件 yarn add gulp-load-plugins --dev 替换之前引入的sass 为plugins.sass 等
安装一个服务器插件 yarn add browser-sync --dev 用于创建启动一个服务器
安装一个useref文件处理器 yarn add gulp-useref --dev
下载压缩html js css 插件 yarn add gulp-htmlmin gulp-uglify gulp-clean-css --dev
判断文件类型的插件 yarn add gulp-if --dev
最终整理组合任务为 清空clean 启动服务器develop 打包 build
运行分别方式为 yarn gulp clean
运行方式为 yarn gulp develop
运行方式为 yarn gulp build
可以配置package.json 的scripts为
"clean": "gulp clean",
"build": "gulp build",
"develop": "gulp develop",
后运行方式分别为 yarn clean
后运行方式分别为 yarn develop
后运行方式分别为 yarn build
网友评论