代码
const gulp = require('gulp');
const clean = require('gulp-clean');
const fileinclude = require('gulp-file-include');
const rev = require('gulp-rev');
const revReplace = require('gulp-rev-replace');
const uglify = require('gulp-uglify');
const cssmin = require('gulp-cssmin');
const spriter = require('gulp-css-spriter');
const plumber = require('gulp-plumber');
const htmlmin = require('gulp-htmlmin');
const sass = require('gulp-sass');
const runSequence = require('run-sequence');
const webpackStream = require('webpack-stream');
const named = require('vinyl-named');
const path = require('path');
const config = {
'ENV': 'dev',//dev or product
'public': path.resolve(__dirname, '../public'), //发布静态资源 css js img 路径
'view': path.resolve(__dirname, '../views') //发布'html路径'
};
const webpackConfig = {
module: {
loaders: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader',
query: {
presets: ['es2015']
}
}
],
externals:['$','zepoto']
}
};
const tempdir = path.resolve(__dirname, 'temp');//临时目录
//清理目标文件夹/文件
gulp.task('clean', function () {
return gulp.src([config.public, config.view, tempdir])
.pipe(clean({force: true}));
});
//用于在html文件中直接include文件 并保存到目标路径
gulp.task('fileinclude', function () {
return gulp.src(['html/*.html'])
.pipe(plumber())
.pipe(fileinclude({
prefix: '@@',
basepath: '@file'
}))
.pipe(gulp.dest(config.view));
});
//将图片拷贝到目标目录
gulp.task('copy:img', function () {
return gulp.src('img/**/*')
.pipe(gulp.dest(path.join(config.public, 'img')));
});
//css 压缩 文件名添加MD5
gulp.task('build:css', function () {
const timestamp = +new Date();
return gulp.src(['css/*.css', 'css/*.scss'])
.pipe(plumber())
.pipe(rev()) //添加MD5
.pipe(sass().on('error', sass.logError))
.pipe(spriter({
includeMode: 'implicit',//explicit:默认不加入雪碧图,,implicit:默认加入雪碧图/* @meta {"spritesheet": {"include": true}} */
spriteSheet: config.public + '/img/spritesheet' + timestamp + '.png',//img保存路径
pathToSpriteSheetFromCSS: '../img/spritesheet' + timestamp + '.png'//在css文件中img的路径
}))
.pipe(cssmin()) //压缩
.pipe(gulp.dest(path.join(config.public, 'css')))
.pipe(rev.manifest())
.pipe(gulp.dest(path.join(tempdir, 'rev/css')));
});
//js 打包 压缩 混淆 文件名添加MD5
gulp.task('build:js', function () {
return gulp.src('js/*.js')
.pipe(plumber())
.pipe(named())
.pipe(webpackStream(webpackConfig))
.pipe(rev()) //添加MD5
.pipe(uglify()) //压缩 混淆
.pipe(gulp.dest(path.join(config.public, 'js')))
.pipe(rev.manifest())
.pipe(gulp.dest(path.join(tempdir, 'rev/js')));
});
// 将html的css js 引用路径 替换为 修改(增加MD5)后的路径 并压缩
gulp.task("revreplace", function () {
const manifest = gulp.src(path.join(tempdir, 'rev/**/rev-manifest.json'));
//noinspection JSUnusedGlobalSymbols
const revReplaceOptions = {
manifest: manifest,
replaceInExtensions: ['.js', '.css', '.html', '.scss'],
modifyUnreved: (filename) => {
if (filename.indexOf('.js') > -1) {
return '../js/' + filename;
}
if (filename.indexOf('.scss') > -1) {
return '../css/' + filename;
}
},
modifyReved: (filename) => {
if (filename.indexOf('.js') > -1) {
return '/js/' + filename;
}
if (filename.indexOf('.css') > -1) {
return '/css/' + filename;
}
}
};
return gulp.src(config.view + '/*.html')
.pipe(revReplace(revReplaceOptions))
.pipe(htmlmin({collapseWhitespace: true}))
.pipe(gulp.dest(config.view));
});
const watchFiles = ['js/**/*.js', 'css/*.css', 'css/*.sass', 'css/**/*.scss', 'html/**/*.html'];
gulp.task('watch', function () {
gulp.watch(watchFiles, function (event) {
gulp.start('default', function () {
console.log('File ' + event.path + ' was ' + event.type + ', build finished');
});
});
});
gulp.task('dev', ['default', 'watch']);
gulp.task('default', function (done) {
runSequence('clean',
['fileinclude', 'copy:img', 'build:css', 'build:js'],
'revreplace',
done);
});
串行方式运行任务,亦即,任务依赖
默认情况下,任务会以最大的并发数同时运行 – 也就是说,它会不做任何等待地将所有的任务同时开起来。如果你希望创建一个有特定顺序的串行的任务链,你需要做两件事:
gulp 的任务运行不能很好的控制顺序 使用run-sequence
gulp运行任务出错时 就会退出程序不再监控 使用gulp-plumber 防止css js 出错时退出
监控js css html img
任务default是一个完整的流程 文件的拷贝 压缩 打包 等
监控时应根据不同的文件变更 执行相应任务 这样效率更佳
但是每个一个文件变更导致其它任务也应执行,还是执行完整任务来的简单且不易出错 效率不行的话 就换电脑
每一个页面具有共性:都会有一个头部和底部 都有一个和页面名相同的css,js文件 都会加载一个网站的base.css,base.js等 使用一个nodejs 脚本来完成这些。
命令形式 node new
const readline = require('readline');
const fs = require("fs") ;
let pagename = null;
//创建readline接口实例
const rl = readline.createInterface({
input:process.stdin,
output:process.stdout
});
rl.question("页面名是什么?",function(answer){
rl.close();
pagename = answer;
if(fs.existsSync(__dirname + `/html/${pagename}.html`)){
console.log(`页面${pagename}已经存在`);
process.exit(0);
}
let basehtml=`
base page
"utf-8"/>
'description' content=''>
"viewport" content="width=device-width, initial-scale=1"/>
"keywords" content=""/>
"author" content="" />
"icon" href="/favicon.ico" type="image/x-icon"/>
"//cdn.bootcss.com/ionicons/2.0.1/css/ionicons.min.css" rel="stylesheet">
"stylesheet" type="text/css" href="../css/base.scss">
"stylesheet" type="text/css" href="../css/${pagename}.scss">
@@include('./common/head.html')
'container'>
@@include('./common/foot.html')
`;
fs.writeFile(__dirname + `/html/${pagename}.html`, basehtml, {flag: 'a'}, function (err) {
if(err) {
console.error(err);
} else {
console.log(`创建${pagename}.html`);
}
});
fs.writeFile(__dirname + `/css/${pagename}.scss`, '', {flag: 'a'}, function (err) {
if(err) {
console.error(err);
} else {
console.log(`创建${pagename}.scss`);
}
});
fs.writeFile(__dirname + `/js/${pagename}.js`, '', {flag: 'a'}, function (err) {
if(err) {
console.error(err);
} else {
console.log(`创建${pagename}.js`);
}
});
});
modifyUnreved: (filename) => {
if (filename.indexOf('.js') > -1) {
return '../js/' + filename;
}
if (filename.indexOf('.less') > -1) {
return '../css/' + filename;
}
},
modifyReved: (filename) => {
return '/' + filename
}