做前端项目,如果没有一个自动化构建工具,手动处理那简直就是坑爹O(∩_∩)O。于是上网了解了下,grunt用的人不少,功能也挺强大。看了一下grunt的配置(包括gulp),感觉稍显复杂。当时项目结构非常简单,就是单文件夹下的html文件,再加上js、css、图片。需要的功能也就js的合并和压缩,html和css的简单格式化,功能简单,So easy……开搞,搞定第一版,一直用到今年。最近整理项目,感觉只支持单一文件夹,功能全内置,实在不够灵活,于是重写了第二版。功能实现没什么难的,麻烦的是打造一个可扩展性良好的架构,要配置简单,任务流程完全自主配置,插件、执行顺序完全可控,文本还要能单独处理,最好能和任务一样配置、控制方便。终于搞定了!一个良好的架构真是很花时间和精力,大家推荐支持一下呗O(∩_∩)O

关于Qbuild.js(姑且这么叫之吧)

  • 轻量高效,易于配置。支持js压缩、文件合并、格式化、复制和重命名等。
  • 基于js的配置文件,支持自定义任务模块和文本处理,支持模块重用。
  • 灵活的文件扫描规则,支持通配符(*和**),支持正则表达式,支持排除规则。
  • 自动跳过未更新的文件,大大提升处理效率。
  • 重命名文件时,自动更新文件引用(可配置)。
  • 自定义输出目录,并保持文件引用(可配置)。
  • 支持将通过 document.write 输出内容的js文件,直接将js引用替换为输出内容。

最后一点可能有人不了解,比如一个html网站,头部和尾部内容在很多html文件里是一样的,便于开发(避免变动一处要修改n个文件),可以将内容整合到js文件中,通过 document.write(html) 输出,而发布时却想将内容直接集成到html文件里(考虑到SEO优化、加载性能等),可以使用本工具实现。我承认这个功能比较蛋疼,可能很多人并不会用到,不过既然实现了,就放上来了,而且对后面实现文件重命名(比如js、css)后自动更新文件(比如html文件)引用有不少帮助。最重要的是全插件模式,任君配置。

先看下运行效果:

以下是 demo/index.html 文件的变化,输出文件夹为 release/www/index.html

第二次运行,仅修改 demo/index.html 文件,截取部分运行结果

如何使用

1. 安装Node.js和压缩工具(uglify或 Google Closure Compiler(需java支持))

2. 下载示例代码,将build文件夹放到你的项目中,配置好build.data.js,执行 node build/build.js (Windows 可直接运行 build.bat )

3. 示例配置见 build/build.data.js 和 demo/build/build.data.js ,2种不同的情况,可供参考

更多见 https://github.com/devin87/build.js

配置代码(build.data.js)

由于注释较多,默认折叠

 //build 配置文件
module.exports = {
//根目录,默认为配置文件所在路径,所有目录均基于此目录
//绝对路径优先;若以./开头则基于配置文件路径(下同)
root: "../",
//输入目录,以下所有dir目录均基于此目录(若以/开头则直接基于根目录)
dir: "demo",
//输出目录,同上
output: "release", //是否自动跳过未更新的文件
//若任务对象有同名属性,则以任务对象的值为主 eg: dir、output、skipOutput、autoSkip、enable、preload、rename、registerText、runText
autoSkip: true, //不保存自定义存储数据
//noStore: false, //文件重命名
//rename: "%f.name%.%date('yyyyMMddHHmm')%%f.ext%",
//清理上次生成的文件
//cleanDest: true, //注册任务处理模块,基于根目录,默认导入./module/*.js
/*register: {
concat: "./module/concat.js",
format: "./module/format.js",
cmd: "./module/cmd.js", //若处理程序相同,可重用已注册的模块 eg: copy:"format"
copy: "./module/copy.js"
},*/ //注册文本处理模块,基于根目录,默认导入./module/text/*.js
//registerText: {},
//registerText: "./module/text/*.js", //默认执行的文本处理模块(按顺序执行),*表示其它模块
runText: ["replace", "before", "after", "*"], //任务:文件合并
concat: {
title: "文件合并", //指定要运行的文本模块和执行顺序
//runText: ["replace", "before", "after", "*"], dir: "js/src",
output: "js-concat", //可以简写为 {"src/a.js":["a/t1.js", "a/t2.js", "a/t3.js"]}
list: [
{
dir: "a",
src: ["t1.js", "t2.js", "t3.js"],
dest: "src/a.js"
},
{
dir: "b",
src: ["t1.js", "t2.js", "D:/t.js"],
dest: "src/b.js"
},
{
//不从父级继承,以/开头直接基于root定义的目录
dir: "/release/js-concat/src",
src: ["a.js", "b.js"],
dest: "ab.js"
}
], //在文件内容之前添加文本,见 ./module/text/append.js
before: [
"//build:%NOW% by Qbuild.js devin87@qq.com\n", //给不同文件追加不同文本,不适用有同名文件的情况
{
//其它文件追加的文本
"def": "//%f.fullname%\n",
//ab.js追加的文本
"ab.js": "//a.js+b.js\n"
}
], //在文件内容之后添加文本,同上,见 ./module/text/append.js
after: [
{
"ab.js": "\n//append after test!"
}
], replace: [
//移除\r字符,第一个参数可以是正则表达式或字符串,若是字符串,则需要指定第3个参数(正则表达式标记 eg:g、i、m或其组合)
[/\r/g, ""],
//移除VS引用
[/\/\/\/\s*<reference path="[^"]*" \/>\n/gi, ""]
], //禁用文件重命名
rename: false
}, //任务:文件格式化
format: [
{
title: "格式化html文件",
//autoSkip: false, //注册单独的文本处理模块
registerText: {
include: "./module/text/custom/document.write.js"
}, //传给 document.write.js 的参数
include: "/demo/js/**(head|bottom).js", //dir: "", //一般output可省略,将自动保持原始文件夹结构
//output: "", //要匹配的文件,可为数组 eg:["about/*.html", "m/*.html"]
//*可匹配斜杆之外的字符,2个*可匹配所有字符
match: "**.html",
//要排除的文件
exclude: "**.old.html", //默认会优化匹配规则以加速扫描 eg:[ab]/*.js => { dir:"[ab]",match:"*.js" }
//若想在一些特殊情况下使用正则表达式,可以关闭优化
//matchOptimize: true, replace: [
//移除html注释
[/(<!--(?!\[if\s)([^~]|~)*?-->)/gi, ""],
//移除无效的空格或换行
[/(<div[^>]*>)[\s\r\n]+(<\/div>)/gi, "$1$2"],
//移除多余的换行
[/(\r?\n)(\r?\n)+/g, "$1"],
//移除首尾空格
[/^\s+|\s+$/, ""]
]
},
{
title: "格式化css文件",
//enable: false, dir: "css",
match: "*.css", replace: [
//移除css注释
[/\/\*([^~]|~)*?\*\//g, ""],
//移除多余的换行
[/(\r?\n)(\r?\n)+/g, "$1"],
//移除首尾空格
[/^\s+|\s+$/, ""]
]
}
], //任务:调用命令行压缩js
cmd: [
{
title: "压缩js", //cmd: "java -jar D:\\tools\\compiler.jar --js=%f.fullname% --js_output_file=%f.dest%",
cmd: "uglifyjs %f.fullname% -o %f.dest% -c -m", match: ["js/**.js", "m/js/**.js"],
exclude: "js/data/**.js|js/error.js", replace: [
//去掉文件头部压缩工具可能保留的注释
[/^\/\*([^~]|~)*?\*\//, ""]
], //可针对单一的文件配置 before、after,def 表示默认
before: [
{
"def": "//devin87@qq.com\n",
"Q.js": "//Q.js devin87@qq.com\n"
},
"//build:%NOW%\n"
]
}
], //任务:文件同步(复制)
copy: [
{
title: "同步js数据",
dir: "js/data",
match: "**.js"
},
{
title: "同步图片",
dir: "images",
match: "**"
}
], //要启动的任务,按顺序执行,不支持*
run: ["concat", "format", "cmd", "copy"]
};

代码下载

Qbuild.js 源码+示例代码

写在最后

由于图片较多,暂时先介绍到这。下次再介绍运行机制及插件的编写。

如果本文或本项目对您有帮助的话,请不吝点个赞。欢迎交流!

grunt配置太复杂?发布一个前端构建工具,简单高效,自动跳过未更新的文件的更多相关文章

  1. parceljs 基本使用———又一个前端构建工具

    备注:      又一个新的前端构建工具 1. 安装 yarn global add parcel-bundler 2. 初始化项目 yarn init -y 3. 基本代码 a. 创建 index. ...

  2. grunt配置太复杂?使用Qbuild进行文件合并、压缩、格式化等处理

    上次简单介绍了下Qbuild的特点和配置,其实实现一个自动化工具并不复杂,往简单里说,无非就是筛选文件和处理文件.但Qbuild的源码也并不少,还是做了不少工作的. 1. 引入了插件机制.在Qbuil ...

  3. 前端构建工具gulpjs的使用介绍及技巧

    gulpjs是一个前端构建工具,与gruntjs相比,gulpjs无需写一大堆繁杂的配置参数,API也非常简单,学习起来很容易,而且gulpjs使用的是nodejs中stream来读取和操作数据,其速 ...

  4. 前端构建工具gulp介绍

    2016年3月3日 10:46:08     晴 前端构建工具gulpjs的使用介绍及技巧 gulpjs是一个前端构建工具,与gruntjs相比,gulpjs无需写一大堆繁杂的配置参数,API也非常简 ...

  5. 前端构建工具gulpjs

    gulpjs是一个前端构建工具,与gruntjs相比,gulpjs无需写一大堆繁杂的配置参数,API也非常简单,学习起来很容易,而且gulpjs使用的是nodejs中stream来读取和操作数据,其速 ...

  6. [转载]前端构建工具gulpjs的使用介绍及技巧

    转载地址:http://www.cnblogs.com/2050/p/4198792.html gulpjs是一个前端构建工具,与gruntjs相比,gulpjs无需写一大堆繁杂的配置参数,API也非 ...

  7. 前端构建工具gulpjs的使用介绍及技巧(一)

    原文链接:http://www.cnblogs.com/2050/p/4198792.html gulpjs是一个前端构建工具,与gruntjs相比,gulpjs无需写一大堆繁杂的配置参数,API也非 ...

  8. JS 前端构建工具gulpjs的使用介绍及技巧

    gulpjs是一个前端构建工具,与gruntjs相比,gulpjs无需写一大堆繁杂的配置参数,API也非常简单,学习起来很容易,而且gulpjs使用的是nodejs中stream来读取和操作数据,其速 ...

  9. [转]前端构建工具gulpjs的使用介绍及技巧

    本文转自:http://www.cnblogs.com/2050/p/4198792.html gulpjs是一个前端构建工具,与gruntjs相比,gulpjs无需写一大堆繁杂的配置参数,API也非 ...

随机推荐

  1. spring下载及部署

    网址http://repo.spring.io/release/org/springframework/spring Bean配置项 Id : 在IOC容器中此Bean唯一标识 Class : 要实例 ...

  2. android嵌套unity3d

    最近因为跟小伙伴在制作一个App参加比赛,由于有unity的开发经验,突发奇想的想要在Android应用中内嵌unity提供模型展示的功能. 为此,我们查阅了不少资料.大多发现的是unity中内嵌An ...

  3. MongoDB学习笔记(索引)

    一.索引基础:    MongoDB的索引几乎与传统的关系型数据库一模一样,这其中也包括一些基本的优化技巧.下面是创建索引的命令:    > db.test.ensureIndex({" ...

  4. jquery高级函数

    .get() 将jq对象转成js $('#div1').get(0).innerHTML.text() 给标签添加文本 .detach() 和remove方法一样,但保留删除元素的所有行为$('div ...

  5. 美国安全公司HBGary——国家授命的黑客

         入侵电脑,窃听用户,假身份上网——美国安全公司HBGary是电脑防护和间谍软件的供应商.而其客户中就有美国的国家安全机构.现在,该公司被偷的电子邮件可以让我们对其数字化战争中的业务做一个初步 ...

  6. JS function document.onclick(){}报错Syntax error on token "function", delete this token

    JS function document.onclick(){}报错Syntax error on token "function", delete this token func ...

  7. JAVA学习笔记(1-32)

    1:数据的输入中,也需要提前声明变量.java区分大小写,注意保留字的问题,注意分号. 2:用import调用一个类.用new新建一个对象,相当于c中的malloc. 3:用final定义一个宏,相当 ...

  8. jdk1.7和jdk1.8的String的getByte方法的差异

    最近遇到一个奇葩的bug,jdk1.7下正常的程序到了jdk1.8下就不能用了,经过查找原因发现是因为jdk版本升级导致的获取的getbyte时得到的byte数组不同造成的.

  9. 使用Gson解析json

    前边的博客说过将json解析成java的方法,使用的是 这几个jar包,但是在解析时层遇到一个问题,就是在将时间字符串转换为java的Timestamp对象时会抛出异常,这个问题一直放在哪里没有去解决 ...

  10. kettle定时任务_第三方合作方有订单自动发送邮件通知_20161214

    由于和第三方合作,需要知道第三方合作方有了订单后通知对方,如果每天查看数据太麻烦了,因此想到了用Kettle定时任务,先判断系统里有没有订单,如果有就执行查询调取订单数据并发送邮件作业,如果没有则不执 ...