使用 Make 命令构建网站
网站开发正变得越来越专业,涉及到各种各样的工具和流程,迫切需要构建自动化。
所谓”构建自动化”,就是指使用构建工具,自动实现”从源码到网页”的开发流程。这有利于提高开发效率、改善代码质量。
本文介绍如何使用make命令,作为网站的构建工具。以下内容既是make语法的实例,也是网站构建的实战教程。你完全可以将代码略作修改,拷贝到自己的项目。

(题图:国家考古博物馆,西班牙,摄于2014年8月)
一、Make的优点
首先解释一下,为什么要用Make。
目前,网站项目(尤其是Node.js项目)有三种构建方案。
我觉得,make是大型项目的首选方案。npm run可以认为是make的简化形式,只适用于简单项目,而Grunt、Gulp那样的工具,有很多问题。
(1)插件问题
Grunt和Gulp的操作,都由插件完成。即使是文件改名这样简单的任务,都要写插件,相当麻烦。而Make是直接调用命令行,根本不用担心找不到插件。
(2)兼容性问题
插件的版本,必须与Grunt和Gulp的版本匹配,还必须与对应的命令行程序匹配。比如,grunt-contrib-jshint插件现在是0.11.0版,对应Grunt 0.4.5版和JSHint 2.6.0版。万一Grunt和JSHint升级,而插件没有升级,就有可能出现兼容性问题。Make是直接调用JSHint,不存在这个问题。
(3)语法问题
Grunt和Gulp都有自己的语法,并不容易学,尤其是Grunt,语法很罗嗦,很难一眼看出来代码的意图。当然,make也不容易学,但它有复用性,学会了还可以用在其他场合。
(4)功能问题
make已经使用了几十年,全世界无数的大项目都用它构建,早就证明非常可靠,各种情况都有办法解决,前人累积的经验和资料也非常丰富。相比之下,Grunt和Gulp的历史都不长,使用范围有限,目前还没有出现它们能做、而make做不到的任务。
基于以上理由,我看好make。
二、常见的构建任务
下面是一些常见的网站构建任务。
- 检查语法
- 编译模板
- 转码
- 合并
- 压缩
- 测试
- 删除
这些任务用到 JSHint、handlebars、CoffeeScript、uglifyjs、mocha 等工具。对应的package.json文件如下。
"devDependencies": {
"coffee-script": "~1.9.1",
"handlebars": "~3.0.0",
"jshint": "^2.6.3",
"mocha": "~2.2.1",
"uglify-js": "~2.4.17"
}
我们来看看,Make 命令怎么完成这些构建任务。
三、Makefile的通用配置
开始构建之前,要编写Makefile文件。它是make命令的配置文件。所有任务的构建规则,都写在这个文件(参见《Make 命令教程》)。
首先,写入两行通用配置。
PATH := node_modules/.bin:$(PATH) SHELL := /bin/bash
上面代码的PATH和SHELL都是BASH变量。它们被重新赋值。
PATH变量重新赋值为,优先在 nodemodules/.bin 目录寻找命令。这是因为(当前项目的)node模块,会在 nodemodules/.bin 目录设置一个符号链接。PATH变量指向这个目录以后,调用各种命令就不用写路径了。比如,调用JSHint,就不用写 ~/node_modules/.bin/jshint ,只写 jshint 就行了。
SHELL变量指定构建环境使用BASH。
四、检查语法错误
第一个任务是,检查源码有没有语法错误。
js_files = $(shell find ./lib -name '*.js')
lint: $(js_files)
jshint $?
上面代码中,shell函数调用find命令,找出lib目录下所有js文件,保存在变量js_files。然后,就可以用jshint检查这些文件。
使用时调用下面的命令。
$ make lint
五、模板编译
第二个任务是编译模板。假定模板都在templates目录,需要编译为build目录下的templates.js文件。
build/templates.js: templates/*.handlebars
mkdir -p $(dir $@)
handlebars templates/*.handlebars > $@
template: build/templates.js
上面代码查看build目录是否存在,如果不存在就新建一个。dir函数用于取出构建目标的路径名(build),内置变量$@代表构建目标(build/templates.js)。
使用时调用下面的命令。
$ make template
六、Coffee脚本转码
第三个任务是,将CofferScript脚本转为JavaScript脚本。
source_files := $(wildcard lib/*.coffee)
build_files := $(source_files:lib/%.coffee=build/%.js)
build/%.js: lib/%.coffee
coffee -co $(dir $@) $<
coffee: $(build_files)
上面代码中,首先获取所有的Coffee脚本文件,存放在变量sourcefiles,函数wildcard用来扩展通配符。然后,将变量sourcefiles中的coffee文件名,替换成js文件名,即 lib/x.coffee 替换成 build/x.js 。
使用时调用下面的命令。
$ make coffee
七、合并文件
使用cat命令,合并多个文件。
JS_FILES := $(wildcard build/*.js)
OUTPUT := build/bundle.js
concat: $(JS_FILES)
cat $^ > $(OUTPUT)
使用时调用下面的命令。
$ make concat
八、压缩JavaScript脚本
将所有JavaScript脚本,压缩为build目录下的app.js。
app_bundle := build/app.js
$(app_bundle): $(build_files) $(template_js)
uglifyjs -cmo $@ $^
min: $(app_bundle)
使用时调用下面的命令。
$ make min
还有另一种写法,可以另行指定压缩工具。
UGLIFY ?= uglify
$(app_bundle): $(build_files) $(template_js)
$(UGLIFY) -cmo $@ $^
上面代码将压缩工具uglify放在变量UGLIFY。注意,变量的赋值符是 ?= ,表示这个变量可以被命令行参数覆盖。
调用时这样写。
$ make UGLIFY=node_modules/.bin/jsmin min
上面代码,将jsmin命令给变量UGLIFY,压缩时就会使用jsmin命令。
九、删除临时文件
构建结束前,删除所有临时文件。
clean:
rm -rf build
使用时调用下面的命令。
$ make clean
十、测试
假定测试工具是mocha,所有测试用例放在test目录下。
test: $(app_bundle) $(test_js)
mocha
当脚本和测试用例都存在,上面代码就会执行mocha。
使用时调用下面的命令。
$ make test
十一、多任务执行
构建过程需要一次性执行多个任务,可以指定一个多任务目标。
build: template concat min clean
上面代码将build指定为执行模板编译、文件合并、脚本压缩、删除临时文件四个任务。
使用时调用下面的命令。
$ make build
如果这行规则在Makefile的最前面,执行时可以省略目标名。
$ make
通常情况下,make一次执行一个任务。如果任务都是独立的,互相没有依赖关系,可以用参数 -j 指定同时执行多个任务。
$ make -j build
十二、声明伪文件
最后,为了防止目标名与现有文件冲突,显式声明哪些目标是伪文件。
.PHONY: lint template coffee concat min test clean build
十三、Makefile文件示例
下面是两个简单的Makefile文件,用来补充make命令的其他构建任务。
实例一。
PROJECT = "My Fancy Node.js project"
all: install test server
test: ;@echo "Testing ${PROJECT}....."; \
export NODE_PATH=.; \
./node_modules/mocha/bin/mocha;
install: ;@echo "Installing ${PROJECT}....."; \
npm install
update: ;@echo "Updating ${PROJECT}....."; \
git pull --rebase; \
npm install
clean : ;
rm -rf node_modules
.PHONY: test server install clean update
实例二。
all: build-js build-css build-js: browserify -t brfs src/app.js > site/app.js build-css: stylus src/style.styl > site/style.css .PHONY build-js build-css
十四、参考链接
- Jess Telford, Example using Makefile for cloverfield
- Oskar Schöldström, How to use Makefiles in your web projects
- James Coglan, Building JavaScript projects with Make
- Rob Ashton, The joy of make
使用 Make 命令构建网站的更多相关文章
- Nodejs学习笔记(七)--- Node.js + Express 构建网站简单示例
目录 前言 新建项目.建立数据库以及其它准备工作 新建express + ejs 项目:sampleEjs 创建数据库 修改package.json文件,安装session和mysql模块 样式和JQ ...
- Nodejs学习笔记(六)--- Node.js + Express 构建网站预备知识
目录 前言 新建express项目并自定义路由规则 如何提取页面中的公共部分? 如何提交表单并接收参数? GET 方式 POST 方式 如何字符串加密? 如何使用session? 如何使用cookie ...
- Nodejs学习笔记(七)—Node.js + Express 构建网站简单示例
前言 上一篇学习了一些构建网站会用到的一些知识点:https://www.cnblogs.com/flyingeagle/p/9192936.html 这一篇主要结合前面讲到的知识,去构建一个较为完整 ...
- Nodejs学习笔记(六)—Node.js + Express 构建网站预备知识
前言 前面经过五篇Node.js的学习,基本可以开始动手构建一个网站应用了,先用这一篇了解一些构建网站的知识! 主要是些基础的东西... 如何去创建路由规则.如何去提交表单并接收表单项的值.如何去给密 ...
- modeJS 深了解(1): Node.js + Express 构建网站预备知识
转载:http://www.cnblogs.com/zhongweiv/p/nodejs_express_webapp1.html 目录 前言 新建express项目并自定义路由规则 如何提取页面中的 ...
- 记不住git命令?试试这个命令浏览网站
Find the right git commands without digging through the web. 找 git 命令,无需谷歌百度,无需 git -help,这个网站以图形界面的 ...
- Python+Bottle+Sina SAE快速构建网站
Bottle是新生一代Python框架的代表,利用Bottle构建网站将十分简单. Sina SAE是国内较出名的云平台之一,十分适用于个人网站的开发或创业公司网站开发. 下面将介绍如果通过Pytho ...
- 迎接 Windows Azure 和 DNN 挑战,几分钟内快速构建网站!
编辑人员注释:本文章由高级商务策划师兼开发平台推广者 Neeti Gupta 撰写. 曾几何时,构建一个简单的网站需要耗费好几个月的时间.在过去,.NET 开发人员和设计社区的一些成员使用 DNN(以 ...
- Nodejs学习笔记(十五)--- Node.js + Koa2 构建网站简单示例
目录 前言 搭建项目及其它准备工作 创建数据库 创建Koa2项目 安装项目其它需要包 清除冗余文件并重新规划项目目录 配置文件 规划示例路由,并新建相关文件 实现数据访问和业务逻辑相关方法 编写mys ...
随机推荐
- SPOJ 345 - Mixtures 区间动态规划
有n个混合物排成一排,每个混合物有一个颜色值0<=color<=99, 规定合并只能合并相邻两个, 将颜色a的混合物与颜色b的混合物合并后,颜色为( a+b ) % 100,并产生a*b的 ...
- Python中利用函数装饰器实现备忘功能
Python中利用函数装饰器实现备忘功能 这篇文章主要介绍了Python中利用函数装饰器实现备忘功能,同时还降到了利用装饰器来检查函数的递归.确保参数传递的正确,需要的朋友可以参考下 " ...
- .ignore插件自动忽略
AS自带的.ignore文件 在AS中新建项目时,默认会创建一个.ignore文件,其中默认忽略的是 *.iml .gradle /local.properties /.idea/workspace. ...
- 怎么在后台修改前台html页面的key、title、description
public void UpdateMeta(string title, string keyword, string desc) { ; i >= ; i--) { if (this.Head ...
- 此方法显式使用的 CAS 策略已被 .NET Framework 弃用
用vs2008开发的应用程序在vs2012中打开时提示如下: 此方法显式使用的 CAS 策略已被 .NET Framework 弃用.若要出于兼容性原因而启用 CAS 策略,请使用 NetFx40_L ...
- 关于timestamp的二三事
之所以要写timestamp的随笔,是因为之前对它的理解存在误区,so. I have to remind myself by writing this informal essay. 微软文档链接: ...
- 解决ASP.NET中ReportView与IE11的兼容性问题
前久发现以前用ReportView开发的一个软件的报表,在IE11上运行时出错,陆续查了好几天才解决了问题. 开发环境: VS2010,ReportView 10.0.402,RDLC报表模板 问题: ...
- Xcode 的正确打开方式——Debugging(转)
转自CocoaChina http://www.cocoachina.com/ios/20150225/11190.html 程序员日常开发中有大量时间都会花费在 debug 上,从事 iOS 开发不 ...
- QT实现单个EXE文件
有时候发布用Qt写的软件是件令人烦恼的事情,明明发布的只是一个简单功能的小软件,非得再附上一堆超大的动态链接库,实在让人觉得汗颜 . 在可执行文件单文件化方面,有多种方法.常用的是编译并使用静态 Qt ...
- shell每日发邮件
LOGFILE="$fank/"`date +"%Y%m%d"`"data"#每日文件 from="abc@123.com&quo ...