加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
gulpfile.js 13.55 KB
一键复制 编辑 原始数据 按行查看 历史
wingmeng 提交于 2018-01-08 11:49 . :sparkles:新增压缩任务
const fs = require('fs'),
http = require('http'),
gulp = require('gulp'),
del = require('del'), // 删除
toIco = require('to-ico'), // 转换 ico
replace = require('gulp-replace'), // 替换
uglify = require('gulp-uglify'), // 压缩JS
rename = require('gulp-rename'), // 重命名
argv = require('minimist')(process.argv.slice(2)), // 命令行传参
sass = require("gulp-sass"), // 编译 Sass
cleanCss = require('gulp-clean-css'), // 压缩 CSS
zip = require('gulp-zip'), // 创建压缩包
autoprefix = require("gulp-autoprefixer"); // 处理 CSS 浏览器前缀
const devPath = 'source/',
pagePath = 'pages/',
jsPath = {source: devPath + 'js/', dest: 'include/js/'},
cssPath = {source: devPath + 'scss/', dest: 'include/css/'},
fontPath = {dest: 'include/fonts/'};
//\\----------------------------------------------------------------------------//\\
/**
* JS 任务
* @desc 复制并压缩 js
* @param {string} fileName - 用以动态匹配文件名,如果是 * 则代表全部
*/
function runJSTask(fileName) {
gulp.src(jsPath.source + fileName) // 1. 找到文件
.pipe(uglify({ mangle: false })) // 2. 压缩文件
.pipe(rename({suffix: '.min'})) // 3. 重命名
.pipe(gulp.dest(jsPath.dest)) // 4. 另存文件
.on('end', function() {
console.log('[Done] JS 任务处理完毕');
});
}
//\\----------------------------------------------------------------------------//\\
/**
* CSS 任务
* @desc 编译并压缩 css
* @param {string} fileName - 参考 JS 任务
*/
function runCSSTask(fileName) {
gulp.src(cssPath.source + fileName) // 1. 找到文件
.pipe(sass()) // 2. 编译 Sass
.pipe(autoprefix({ // 3. 处理浏览器前缀
browsers: ['last 10 versions', '> 5%', 'ie 9']
}))
.pipe(cleanCss()) // 4. 压缩 CSS
.pipe(rename({suffix: '.min'})) // 5. 重命名
.pipe(gulp.dest(cssPath.dest)) // 6. 另存文件
.on('end', function() {
console.log('[Done] CSS 任务处理完毕');
});
}
/*
function concatCSS(fontCSSPath) {
var publicCSSName = 'public.min.css',
publicCSSPath = cssPath.dest + publicCSSName;
gulp.src([publicCSSPath, fontCSSPath])
.pipe(concatCss(publicCSSName.split('.')[0] + '.pack.css'))
.pipe(cleanCss())
.pipe(gulp.dest(cssPath.dest))
.on('end', function() { // 任务流结束后执行
// 清理合并后的原文件
del([publicCSSPath, fontCSSPath]);
});
console.log('[Done] 已合并 CSS:' + publicCSSPath + ', ' + fontCSSPath);
}
*/
//\\----------------------------------------------------------------------------//\\
/**
* 拉取第三方网站上生成的 iconfont 资源
* @desc 资源拉取自:阿里巴巴矢量图标库 (iconfont.cn)
*/
function runIconFontTask() {
loadConfigFile(function(data) {
var iconfontURL = data.iconfont.url,
fontType = data.iconfont.type;
http.get('http:' + iconfontURL, function(res) {
res.setEncoding('utf8');
var cssContent = ''; // 内容字符串
// 下载数据
res.on('data', function(chunk) {
cssContent += chunk;
});
// 下载完成
res.on('end', function() {
var regRule = new RegExp(/(?=url\(\W)\S+(?=\W\))/, 'g'); // output: url('//xxx//xx.xx?t=xxxxx
var fontURLs = getFontURLs(cssContent, fontType, regRule);
modifyFontCSS(fontURLs, cssContent, regRule);
downloadFonts(fontURLs);
});
});
});
}
/**
* 从 CSS 文本中解析出字体的地址
* @param {string} content - 下载的 iconfont CSS 文件文本内容
* @param {object} regEx - 正则表达式
*/
function getFontURLs(content, fontType, regEx) {
var fontURLs = []; // output: url('//xxx//xx.xx?t=xxxxx
content.replace(regEx, function(match) {
fontURLs.push(match); // 保存从 CSS 文件中解析出的字体地址
});
// 处理 fontURLs 使其格式合法化
fontURLs = fontURLs.map(function(item) {
if (item.indexOf('data:application') === -1) { // base64 形式的字体
item = item.replace(/url\(\W/, '').split('?t=')[0]; // output: //xxx//xx.xx
// 筛选 fontType 中设置的字体类型
for (var i = 0; i < fontType.length; i++) {
if (item.lastIndexOf('.' + fontType[i]) > 0) {
return item;
}
}
}
});
return removeRepeat(fontURLs); // 移除空值,合并重复 url
}
/**
* 修改 CSS 中字体远程路径为本地路径
* @param {array} fonts - 字体路径数组
* @param {string} data - CSS 文本内容
* @param {regExp} regEx - 正则
*/
function modifyFontCSS(fonts, data, regEx) {
fonts.forEach(item => {
var fontName = returnFontName(item),
fontHost = item.replace(fontName, ''),
regEx = new RegExp(fontHost + fontName, 'g');
data = data.replace(regEx, function(match) {
return '../fonts/' + fontName;
});
});
// 将调整完字体路径的 CSS 写入本地
var cssName = 'iconfont.css',
localCSSFile = cssPath.source + cssName;
fs.writeFile(localCSSFile, data, function (err) {
if (err) {
throw err;
}
runCSSTask(cssName);
});
}
/**
* 从远程地址下载字体到本地
* @param {array} urlArr - 字体远程地址
*/
function downloadFonts(urlArr) {
urlArr.forEach(url => {
var fileName = returnFontName(url),
fileStream = fs.createWriteStream(
fontPath.dest + fileName
);
http.get('http:' + url, function(res) {
res.pipe(fileStream); // 文件流写入
// 下载完成
res.on('end', function() {
console.log('[Done] 下载成功:' + fileName);
});
});
});
}
/**
* 返回 url 地址中的字体名称
* @param {string} url - 字体 url 地址
* @returns {string} 字体名称
*/
function returnFontName(url) {
return url.substr(url.lastIndexOf('/') + 1);
}
//\\----------------------------------------------------------------------------//\\
// 生成 favicon.ico
function runFaviconTask(logoPath) {
var files = [fs.readFileSync(logoPath)];
toIco(files, {
resize: true,
sizes: [32] // 默认尺寸为 32*32px
}).then(buf => {
fs.writeFile('favicon.ico', buf, function(err) {
if (err) {
throw err;
}
console.log('[Done] 生成文件:favicon.ico');
});
});
}
//\\----------------------------------------------------------------------------//\\
function runBuildTask(isForce) {
loadConfigFile(function(data) {
buildEntryFile(data.project);
buildNavJson(data.nav);
buildInnerPage(data.nav, isForce);
});
}
// 构建入口文件 index.html
function buildEntryFile(data) {
gulp.src(devPath + 'models/index.html')
.pipe(replace('{{ title }}', function() {
return data.title;
}))
.pipe(replace('{{ name }}', function() {
return data.name;
}))
.pipe(replace('{{ logoPath }}', function() {
return data.logo;
}))
.pipe(rename(data.entry))
.pipe(gulp.dest('./'))
.on('end', function() {
console.log('[Done] 生成文件:' + data.entry);
});
}
// 构建导航文件 - nav.json
function buildNavJson(data) {
fs.writeFile('include/js/nav.json', JSON.stringify(data, null, 2), function(err) {
if (err) {
throw err;
}
console.log('[Done] 已生成 nav.json 文件');
});
}
// 根据导航构建内页
function buildInnerPage(data, isForce) {
var _getFileName = function(url) {
if (url.indexOf('/') > -1) { // 多级目录
return url.substr(url.lastIndexOf('/'));
}
return url
};
data.forEach(nav => {
if (nav['subNav'] && nav['subNav'].length) { // 有二级导航
var base = nav['base'] || '';
nav['subNav'].forEach(subNav => {
var filePath = base + subNav['url'],
fileName = _getFileName(subNav['url']);
buildFrameFile(subNav, filePath, fileName, isForce);
});
} else {
var filePath = nav['url'],
fileName = _getFileName(nav['url']);
buildFrameFile(nav, filePath, fileName, isForce);
}
});
}
// 构建内页栏目页面
function buildFrameFile(data, filePath, fileName, isForce) {
fs.exists(filePath, function(isExists) {
if (isExists && !isForce) {
console.log('[warning] ' + filePath + ' 已存在,跳过该文件');
} else {
gulp.src(devPath + 'models/frame.html')
.pipe(replace(/\{\{\stitle\s\}\}/g, function() {
return data['name'];
}))
.pipe(replace(/\{\{\spath\s\}\}/g, function() {
var pathStr = '';
for (var i = 0; i < filePath.split('/').length - 1; i++) {
pathStr += '../'; // 基于 include 的相对位置
}
return pathStr;
}))
.pipe(rename(fileName))
.pipe(gulp.dest(filePath.replace(fileName, '')))
.on('end', function() {
console.log('[Done] 生成文件:' + filePath);
});
}
});
}
//\\----------------------------------------------------------------------------//\\
// 启动 HTTP 服务
function startHTTPServe() {
let url = require('url'),
path = require('path'),
mine = {
'css' : 'text/css',
'gif' : 'image/gif',
'html': 'text/html',
'ico' : 'image/x-icon',
'jpeg': 'image/jpeg',
'jpg' : 'image/jpeg',
'js' : 'text/javascript',
'json': 'application/json',
'pdf' : 'application/pdf',
'png' : 'image/png',
'svg' : 'image/svg+xml',
'tiff': 'image/tiff',
'txt' : 'text/plain'
},
port = 8888;
// 写入页面并启动服务
http.createServer(function(req, res) {
var pathname = url.parse(req.url).pathname,
realPath = path.join('./', pathname),
ext = path.extname(pathname);
ext = ext ? ext.slice(1) : 'unknown';
fs.exists(realPath, function(exists) {
if (!exists) {
res.writeHead(404, {
'Content-Type': 'text/plain'
});
res.write('This request URL ' + realPath + ' was not found on this server.');
res.end();
} else {
fs.readFile(realPath, 'binary', function(err, file) {
if (err) {
res.writeHead(500, {
'Content-Type': 'text/plain'
});
res.end(err);
} else {
var contentType = mine[ext] || 'text/plain';
res.writeHead(200, {
'Content-Type': contentType
});
res.write(file, 'binary');
res.end();
}
});
}
});
}).listen(port);
console.log('HTTP 服务已启动');
// 开启网页
var cmd = require('child_process');
cmd.exec('start http://127.0.0.1:' + port + '/index.html');
}
//\\----------------------------------------------------------------------------//\\
/**
* 获取文件名
*/
function getFileName(param, type) {
var fileName = '*.' + type;
if (param && typeof param === 'string') {
var flag = param.lastIndexOf('.' + type);
if (flag > 0) {
fileName = param;
} else {
fileName = param + '.' + type;
}
}
return fileName;
}
/**
* 数组去重、去空值
* @param {array} arr - 待处理数组
* @returns {array} 合并重复项的数组
*/
function removeRepeat(arr) {
var result = [],
hash = {};
for (var i = 0, elm; i < arr.length; i++) {
if (arr[i]) {
(elm = arr[i]) != null;
if (!hash[elm]) {
result.push(arr[i]);
hash[elm] = true;
}
}
}
return result;
}
/**
* 读取配置文件
* @param {function} callback - 回调函数
*/
function loadConfigFile(callback) {
fs.readFile(devPath + 'project.json', {
encoding: 'utf-8'
}, function(err, data) {
var data = JSON.parse(data);
callback(data);
});
}
//\\----------------------------------------------------------------------------//\\
gulp.task('default', function() {
var graphic =
'+--------------------------------------------------------+\n' +
'| //  ///////// // // |\n' +
'| // //  // // // // // // |\n' +
'| // //  ////////// // //// // |\n' +
'| //////////  // // // // // |\n' +
'| // // // ////// // // |\n' +
'+--------------------------------------------------------+\n';
console.log(graphic);
});
/**
* @example
* 1. gulp js - 处理所有 js 文件
* 2. gulp js --name index.js - 只处理 index.js
*/
gulp.task('js', function() {
// 编译指定文件:gulp js --name public.js
var param = getFileName(argv.name, 'js');
runJSTask(param);
});
gulp.task('css', function() {
var param = getFileName(argv.name, 'scss');
runCSSTask(param);
});
gulp.task('font', function() {
del([fontPath.dest + '*.*']).then(function(paths) {
console.log('[Done] 已清理旧字体文件:\n', paths.join('\n'));
runIconFontTask();
});
});
gulp.task('favicon', function() {
var param = argv.name,
path = 'include/images/' + param;
if (param && typeof param === 'string') {
runFaviconTask(path);
} else {
loadConfigFile(function(data) {
runFaviconTask(data.project.logo);
});
}
});
gulp.task('build', function() {
var isForce = argv.force; // 是否强制模式
runBuildTask(isForce);
});
gulp.task('serve', function() {
startHTTPServe();
});
gulp.task('zip', function() {
const output = 'export',
zipFile = 'armui_dist.zip';
console.log('[Running] 打包中...');
// 生产包
gulp.src(['include*/**', '*.html', 'favicon.ico'])
.pipe(zip(zipFile))
.pipe(gulp.dest(output))
.on('end', function() {
fs.exists(output + '/' + zipFile, function(isExists) {
if (isExists) {
console.log('[Done] 打包完成:' + zipFile);
} else {
console.log('[Error] 打包失败,请重试!');
}
});
});
});
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化