Blog Archives

用UglifyJS2合并压缩混淆JS代码

从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发。Nodejs框架是基于V8的引擎,是目前速度最快的Javascript引擎。chrome浏览器就基于V8,同时打开20-30个网页都很流畅。Nodejs标准的web开发框架Express,可以帮助我们迅速建立web站点,比起PHP的开发效率更高,而且学习曲线更低。非常适合小型网站,个性化网站,我们自己的Geek网站!!

关于作者

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/nodejs-uglifyjs2-js/

nodejs-uglifyjs2

前言

做Web前端开发,总是要考虑页面的打开速度,如果文件数量越少、文件长度越小,就可以直接的提升网页的访问速度。

但在开发的时候,为了保证代码的可读性,我们写的程序文件会很多而且很大,这样就与部署的要求发生背离,通过UglifyJS2这个工具,我们可以在开发完成时,对代码文件进行 合并、混淆、压缩 等的操作,达到最优的访问性能。

目录

  1. UglifyJS介绍
  2. UglifyJS2介绍
  3. UglifyJS2安装
  4. UglifyJS2命令操作
  5. UglifyJS2的API使用

1. UglifyJS介绍

开始UglifyJS2介绍之前,我们先要说一下UglifyJS。UglifyJS是UglifyJS2的前身,是一个Javascript开发的通用的语法分析、代码压缩、代码优化的一个工具包。UglifyJS是基于Nodejs环境开发,支持CommonJS模块系统的任意的Javascript平台。

UglifyJS的实现主要分为2部分:

  • 生成JS代码的抽象语法树(AST),通过parse-js.js完成。
  • 遍历AST语法树,做各种操作,比如自动缩进、缩短变量名、删除块括号{}、去空格、常量表达式、连续变量声明、语块合并、去掉无法访问的代码等,通过process.js完成。

2. UglifyJS2介绍

UglifyJS2是作者对UglifyJS的重写,是完全的重写,而不仅仅是升级。从UglifyJS2官司方网页介绍看,UglifyJS2把整个的JS压缩过程,做了更进一步的细化。

上述所有的功能代码API是​​在6500行的左右,比其他的相同功能的开发包都要小。作者还提供了一个在线版本UglifyJS2的JS压缩工具,http://lisperator.net/uglifyjs/,大家可以测试一下。

3. UglifyJS2安装

系统环境:

  • win7 64bit
  • Nodejs:v0.10.5
  • Npm:1.2.19

UglifyJS2的安装非常简单,和Nodejs的其他包一样,全局安装使用如下命令。

npm install uglify-js -g

也可以通过github下载源代码安装。


git clone git://github.com/mishoo/UglifyJS2.git
cd UglifyJS2

我们在使用UglifyJS2的时候主要有2种方式,一种是通过命令行操作,对指定的JS文件进行压缩;另一种是通过程序的API调用,对文件或内存中的JS代码进行压缩。下面我将分两种情况进行介绍。

4. UglifyJS2命令操作

在全局安装好UglifyJS2以后,我们就可以使用UglifyJS2的命令了。

打印uglifyjs命令行的帮助信息,会打出很长一段说明。


D:\workspace\javascript\nodejs-uglifyJS2>uglifyjs -h
D:\toolkit\nodejs\\node.exe D:\toolkit\nodejs\node_modules\uglify-js\bin\uglifyjs input1.js [input2.js ...] [options]
Use a single dash to read input from the standard input.

NOTE: by default there is no mangling/compression.
Without [options] it will simply parse input files and dump the AST
with whitespace and comments discarded.  To achieve compression and
mangling you need to use `-c` and `-m`.

Options:
  --source-map                  Specify an output file where to generate source
                                map.                                    [string]
  --source-map-root             The path to the original source to be included
                                in the source map.                      [string]
  --source-map-url              The path to the source map to be added in //#
                                sourceMappingURL.  Defaults to the value passed
                                with --source-map.                      [string]
  --source-map-include-sources  Pass this flag if you want to include the
                                content of source files in the source map as
                                sourcesContent property.               [boolean]
  --in-source-map               Input source map, useful if you're compressing
                                JS that was generated from some other original
                                code.
  --screw-ie8                   Pass this flag if you don't care about full
                                compliance with Internet Explorer 6-8 quirks
                                (by default UglifyJS will try to be IE-proof).
                                                                       [boolean]
  --expr                        Parse a single expression, rather than a
                                program (for parsing JSON)             [boolean]
  -p, --prefix                  Skip prefix for original filenames that appear
                                in source maps. For example -p 3 will drop 3
                                directories from file names and ensure they are
                                relative paths. You can also specify -p
                                relative, which will make UglifyJS figure out
                                itself the relative paths between original
                                sources, the source map and the output file.
                                                                        [string]
  -o, --output                  Output file (default STDOUT).
  -b, --beautify                Beautify output/specify output options.
                                                                        [string]
  -m, --mangle                  Mangle names/pass mangler options.      [string]
  -r, --reserved                Reserved names to exclude from mangling.
  -c, --compress                Enable compressor/pass compressor options. Pass
                                options like -c
                                hoist_vars=false,if_return=false. Use -c with
                                no argument to use the default compression
                                options.                                [string]
  -d, --define                  Global definitions                      [string]
  -e, --enclose                 Embed everything in a big function, with a
                                configurable parameter/argument list.   [string]
  --comments                    Preserve copyright comments in the output. By
                                default this works like Google Closure, keeping
                                JSDoc-style comments that contain "@license" or
                                "@preserve". You can optionally pass one of the
                                following arguments to this flag:
                                - "all" to keep all comments
                                - a valid JS regexp (needs to start with a
                                slash) to keep only comments that match.
                                Note that currently not *all* comments can be
                                kept when compression is on, because of dead
                                code removal or cascading statements into
                                sequences.                              [string]
  --preamble                    Preamble to prepend to the output.  You can use
                                this to insert a comment, for example for
                                licensing information.  This will not be
                                parsed, but the source map will adjust for its
                                presence.
  --stats                       Display operations run time on STDERR.
                                                                       [boolean]
  --acorn                       Use Acorn for parsing.                 [boolean]
  --spidermonkey                Assume input files are SpiderMonkey AST format
                                (as JSON).                             [boolean]
  --self                        Build itself (UglifyJS2) as a library (implies
                                --wrap=UglifyJS --export-all)          [boolean]
  --wrap                        Embed everything in a big function, making the
                                “exports” and “global” variables available. You
                                need to pass an argument to this option to
                                specify the name that your module will take
                                when included in, say, a browser.       [string]
  --export-all                  Only used when --wrap, this tells UglifyJS to
                                add code to automatically export all globals.
                                                                       [boolean]
  --lint                        Display some scope warnings            [boolean]
  -v, --verbose                 Verbose                                [boolean]
  -V, --version                 Print version number and exit.         [boolean]
  --noerr                       Don't throw an error for unknown options in -c,
                                -b or -m.                              [boolean]

对命令参数进行解释:

  • –source-map [string],生成source map文件。
  • –source-map-root [string], 指定生成source map的源文件位置。
  • –source-map-url [string], 指定source map的网站访问地址。
  • –source-map-include-sources,设置源文件被包含到source map中。
  • –in-source-map,自定义source map,用于其他工具生成的source map。
  • –screw-ie8, 用于生成完全兼容IE6-8的代码。
  • –expr, 解析一个表达式或JSON。
  • -p, –prefix [string], 跳过原始文件名的前缀部分,用于指定源文件、source map和输出文件的相对路径。
  • -o, –output [string], 输出到文件。
  • -b, –beautify [string], 输出带格式化的文件。
  • -m, –mangle [string], 输出变量名替换后的文件。
  • -r, –reserved [string], 保留变量名,排除mangle过程。
  • -c, –compress [string], 输出压缩后的文件。
  • -d, –define [string], 全局定义。
  • -e, –enclose [string], 把所有代码合并到一个函数中,并提供一个可配置的参数列表。
  • –comments [string], 增加注释参数,如@license、@preserve。
  • –preamble [string], 增加注释描述。
  • –stats, 显示运行状态。
  • –acorn, 用Acorn做解析。
  • –spidermonkey, 解析SpiderMonkey格式的文件,如JSON。
  • –self, 把UglifyJS2做为依赖库一起打包。
  • –wrap, 把所有代码合并到一个函数中。
  • –export-all, 和–wrap一起使用,自动输出到全局环境。
  • –lint, 显示环境的异常信息。
  • -v, –verbose, 打印运行日志详细。
  • -V, –version, 打印版本号。
  • –noerr, 忽略错误命令行参数。

通过对命令行各种参数的解释,我们基本上知道了这些参数都是干什么的了,下面我就试一下。

写2个简单地JS文件,demo.js, main.js。


~ vi D:\workspace\javascript\nodejs-uglifyJS2\demo.js

'use strict';

function hello(name){
	if(name==='fens.me'){
		return "Long time no see, "+name;
	}
	return "hello "+name;
}

console.log(hello('Conan'));
console.log(hello('fens.me'));

main.js


~ vi D:\workspace\javascript\nodejs-uglifyJS2\main.js

'use strict';

function book(){
    return [
        {head:'前言',page:'/views/tpl/book-r1/preface.html',active:false},
        {head:'目录',page:'/views/tpl/book-r1/contents.html',active:true},
        {head:'代码',page:'/views/tpl/book-r1/code.html',active:false},
        {head:'试读',page:'/views/tpl/book-r1/sample.html',active:false},
        {head:'勘误',page:'/views/tpl/book-r1/mistake.html',active:false}
    ];
}

var tab=function(arr,idx){
	for(var i=0;i<arr.length;i++){
		arr[i].active = (idx==i?true:false);
	}
	return arr;
}

console.log(tab(book(),3));

接下来,用UglifyJS2命令进行操作,合并两个文件,对变量名用单字母替换,进行压缩,所有代码合并到一个函数,生成source map,指定source map来源网站。


D:\workspace\javascript\nodejs-uglifyJS2>uglifyjs main.js demo.js -o foo.min.js --source-map foo.min.js.map --source-map-root http://onbook.me -p 5 -c -m --wrap --export-all

在当前目录生成了2个新文件:foo.min.js.map, foo.min.js,分别查看这两个文件。

foo.min.js


!function(e,t){"use strict";function o(){return[{head:"前言",page:"/views/tpl/book-r1/preface.html",active:!1},{head:"目录",page:"/views/tpl/book-r1/contents.html",active:!0},{head:"代码",page:"/views/tpl/book-r1/code.html",active:!1},{head:"试读",page:"/views/tpl/book-r1/sample.html",active:!1},{head:"勘误",page:"/views/tpl/book-r1/mistake.html",active:!1}]}function n(e){return"fens.me"===e?"Long time no see, "+e:"hello "+e}t["true"]=e,console.log(a(o(),3));var a=function(e,t){for(var o=0;o

foo.min.js.map


{"version":3,"file":"foo.min.js","sources":["?"],"names":["exports","global","book","head","page","active","hello","name","console","log","tab","arr","idx","i","length","this"],"mappings":"CAAC,SAASA,EAASC,GAAnB,YAEA,SAASC,KACL,QACKC,KAAK,KAAKC,KAAK,kCAAkCC,QAAO,IACxDF,KAAK,KAAKC,KAAK,mCAAmCC,QAAO,IACzDF,KAAK,KAAKC,KAAK,+BAA+BC,QAAO,IACrDF,KAAK,KAAKC,KAAK,iCAAiCC,QAAO,IACvDF,KAAK,KAAKC,KAAK,kCAAkCC,QAAO,IANjE,QAASC,GAAMC,GACd,MAAU,YAAPA,EACK,qBAAqBA,EAEtB,SAASA,EANWN,EAAO,QAAUD,EAY7CQ,QAAQC,IAAIC,EAAIR,IAAO,GADvB,IAAIQ,GAAI,SAASC,EAAIC,GACpB,IAAI,GAAIC,GAAE,EAAEA,EAAEF,EAAIG,OAAOD,IACxBF,EAAIE,GAAGR,OAAUO,GAAKC,GAAE,GAAK,CAE9B,OAAOF,GAGRH,SAAQC,IAAIH,EAAM,UAClBE,QAAQC,IAAIH,EAAM,mBAjBTJ,UAAAI,QASLI,MAX8E,WAAW,MAAOK","sourceRoot":"http://onbook.me"}

通过一条简单的命令,就实现了对JS代码的合并、压缩等的操作,确实非常方便。

下载jquery-2.1.1.js文件自己压缩,并与官方的压缩文件进行对比。


# 下载
~ wget http://code.jquery.com/jquery-2.1.1.js
~ wget http://code.jquery.com/jquery-2.1.1.min.js

# 压缩
~ uglifyjs jquery-2.1.1.js -o jquery-2.1.1.min.uglifyjs2.js -p 5 -c -m

# 比较3个文件大小
~ ls -l
-rwx------  1 4294967295 mkpasswd 247351 Jul  6 16:26 jquery-2.1.1.js
-rwx------  1 4294967295 mkpasswd  84245 Jul  6 16:32 jquery-2.1.1.min.js
-rwx------  1 4294967295 mkpasswd  84113 Jul  6 16:28 jquery-2.1.1.min.uglifyjs2.js

我在本地压缩的文件jquery-2.1.1.min.uglifyjs2.js,与jquery官司网下载的压缩文件jquery-2.1.1.min.js大小差不多,都在84KB左右。

5. UglifyJS2的API使用

另一种使用方式是,把UglifyJS2包放到程序中,通过API对JS文件或JS代码进行压缩。首先,新建一个NPM项目文件package.json,然后在是下载UglifyJS2依赖包。

新建文件package.json


~ vi D:\workspace\javascript\nodejs-uglifyJS2\package.json


{
  "name": "nodejs-uglifyjs2",
  "version": "0.0.1",
  "description": "uglifyjs2",
  "author": "Conan Zhang ",
  "dependencies": {
  }
}

下载UglifyJS2依赖包


D:\workspace\javascript\nodejs-uglifyJS2>npm install uglify-js --save
npm WARN package.json nodejs-uglifyjs2@0.0.1 No readme data!
npm http GET https://registry.npmjs.org/uglify-js
npm http 304 https://registry.npmjs.org/uglify-js
npm http GET https://registry.npmjs.org/async
npm http GET https://registry.npmjs.org/source-map
npm http GET https://registry.npmjs.org/optimist
npm http GET https://registry.npmjs.org/uglify-to-browserify
npm http 304 https://registry.npmjs.org/uglify-to-browserify
npm http 304 https://registry.npmjs.org/optimist
npm http 304 https://registry.npmjs.org/async
npm http 304 https://registry.npmjs.org/source-map
npm http GET https://registry.npmjs.org/wordwrap
npm http GET https://registry.npmjs.org/amdefine
npm http 304 https://registry.npmjs.org/wordwrap
npm http 304 https://registry.npmjs.org/amdefine
uglify-js@2.4.14 node_modules\uglify-js
├── uglify-to-browserify@1.0.2
├── async@0.2.10
├── optimist@0.3.7 (wordwrap@0.0.2)
└── source-map@0.1.34 (amdefine@0.1.0)

我们新建一个文件uglify2.js,用于编写程序。


~ vi D:\workspace\javascript\nodejs-uglifyJS2\uglify2.js

'use strict';

var UglifyJS = require('uglify-js');

//代码压缩
var result = UglifyJS.minify("var b = function () {};", {fromString: true});
console.log("\n===========================");
console.log(result);

//文件压缩
result = UglifyJS.minify(["demo.js"]);
console.log("\n===========================");
console.log(result.code);

//多文件压缩,指定source map和网站来源
result = UglifyJS.minify(["main.js","demo.js"],{
    outSourceMap: "out.js.map",
    sourceRoot: "http://onbook.me",
    mangle:true
});
console.log("\n===========================");
console.log(result.code);
console.log(result.map);

程序输出:


D:\workspace\javascript\nodejs-uglifyJS2>node uglify2.js

===========================
{ code: 'var b=function(){};', map: 'null' }

===========================
"use strict";function hello(e){return"fens.me"===e?"Long time no see, "+e:"hello "+e}var tab=function(e,o){for(var n=0;n
<e.length;n++)e[n].active=o==n?!0:!1;return e};console.log(hello("Conan")),console.log(hello("fens.me"));

===========================
"use strict";function book(){return[{head:"前言",page:"/views/tpl/book-r1/preface.html",active:!1},{head:"目录",page:"/v
iews/tpl/book-r1/contents.html",active:!0},{head:"代码",page:"/views/tpl/book-r1/code.html",active:!1},{head:"试读",page
:"/views/tpl/book-r1/sample.html",active:!1},{head:"勘误",page:"/views/tpl/book-r1/mistake.html",active:!1}]}function he
llo(e){return"fens.me"===e?"Long time no see, "+e:"hello "+e}console.log(tab(book(),3));var tab=function(e,o){for(var t=
0;t<e.length;t++)e[t].active=o==t?!0:!1;return e};console.log(hello("Conan")),console.log(hello("fens.me"));
//# sourceMappingURL=out.js.map
{"version":3,"file":"out.js.map","sources":["main.js","demo.js"],"names":["book","head","page","active","hello","name","
console","log","tab","arr","idx","i","length"],"mappings":"AAAA,YAEA,SAASA,QACL,QACKC,KAAK,KAAKC,KAAK,kCAAkCC,QAAO,IACxD
F,KAAK,KAAKC,KAAK,mCAAmCC,QAAO,IACzDF,KAAK,KAAKC,KAAK,+BAA+BC,QAAO,IACrDF,KAAK,KAAKC,KAAK,iCAAiCC,QAAO,IACvDF,KAAK,KAAKC
,KAAK,kCAAkCC,QAAO,ICNjE,QAASC,OAAMC,GACd,MAAU,YAAPA,EACK,qBAAqBA,EAEtB,SAASA,EDMjBC,QAAQC,IAAIC,IAAIR,OAAO,GCDvB,IAAIQ,
KAAI,SAASC,EAAIC,GACpB,IAAI,GAAIC,GAAE,EAAEA,EAAEF,EAAIG,OAAOD,IACxBF,EAAIE,GAAGR,OAAUO,GAAKC,GAAE,GAAK,CAE9B,OAAOF,GAGR
H,SAAQC,IAAIH,MAAM,UAClBE,QAAQC,IAAIH,MAAM","sourceRoot":"http://onbook.me"}

我们看到用操作uglifyJS2包的API,还是挺简单的,如果对AST树有遍历需求,API提供了非常实用的函数支持。

不过我在测试API过程中,发现有2个问题。

  • 通过API设置mangle选项,但输出没有效果。
  • 没有--wrap和--export-all 命令行参数对应的API。

通过本文的介绍,我们基本上了解了uglifyJS2包的功能和使用方法,然后就可以放心大胆地对JS代码进行压缩了。在实际的前端项目中,一般不用自己配置uglifyJS2包,而是通过grunt来调用uglifyJS2进行代码发布前的压缩,关于grunt使用,请参考文章:grunt让Nodejs规范起来

转载请注明出处:
http://blog.fens.me/nodejs-uglifyjs2-js/

打赏作者

Yeoman自动构建js项目

从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发。Nodejs框架是基于V8的引擎,是目前速度最快的Javascript引擎。chrome浏览器就基于V8,同时打开20-30个网页都很流畅。Nodejs标准的web开发框架Express,可以帮助我们迅速建立web站点,比起PHP的开发效率更高,而且学习曲线更低。非常适合小型网站,个性化网站,我们自己的Geek网站!!

关于作者

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/nodejs-yeoman-intro/
yeoman

前言
有一种技术可以提高我们的工作效率,可以让我们专心做我们擅长的事,可以屏蔽复杂性,可以规范我们的架构和我们的代码,可以让我们的享受编程的乐趣。Yeoman可以做到。

很多年以前,rails刚刚出世,伴随着一个新的名词“脚手架(scaffolding)”出现了。脚手架是一种提高开发效率的工具的代名词。随后,各种编程语言都开始实现自己的“脚手架”工具。Maven重新构造了Java的世界,改变了几千万的开发者对于Java项目构建的认识。Yeoman在Javascript领域正做着同样的事情。

看着各种工具,各种语言,都在飞跃式的进化。做为一个开发者,我每天都在为变化而惊喜!

目录

  1. Yeoman介绍
  2. Yeoman工具包yo命令
  3. Yeoman工具包yo – 快速构建一个web项目
  4. Yeoman工具包bower,grunt的组合用法

1. Yeoman介绍

Yeoman是Google的团队和外部贡献者团队合作开发的,他的目标是通过Grunt(一个用于开发任务自动化的命令行工具)和Bower(一个HTML、CSS、Javascript和图片等前端资源的包管理器)的包装为开发者创建一个易用的工作流。

Yeoman主要有三部分组成:yo(脚手架工具)、grunt(构建工具)、bower(包管理器)。这三个工具是分别独立开发的,但是需要配合使用,来实现我们高效的工作流模式。

2. Yeoman工具包yo命令

yo插件都是通过npm, Node.js包管理器安装和管理的.

我的系统环境

  • win7 64bit
  • Nodejs:v0.10.5
  • Npm:1.2.19
~ D:\workspace\javascript>node -v
v0.10.5

~ D:\workspace\javascript>npm -v
1.2.19

在系统中,我们已经安装好了Nodejs和npm。win7安装nodejs请参考文章:Nodejs开发框架Express3.0开发手记–从零开始

全局安装yo

~ D:\workspace\javascript>npm install -g yo

如果你还没有安装grunt,bower,也需要一起安装

~ D:\workspace\javascript>npm install -g grunt-cli bower

接下我们看一下yo命令行操作
1). 通过help查看帮助


~ D:\workspace\javascript>yo --help
Yeoman is a mask worn by the following members of the open-source community:

  Paul Irish, Addy Osmani, Mickael Daniel, Sindre Sorhus, Eric Bidelman,
  Frederick Ros, Brian Ford, Pascal Hartig, Stephen Sawchuk, and countless
  other contributors.

Usage: yo GENERATOR [args] [options]

General options:
  -h, --help     # Print generator's options and usage
  -f, --force    # Overwrite files that already exist

Please choose a generator below.
Angular
  angular:app
  angular:common
  angular:constant
  angular:controller
  angular:decorator
  angular:directive
  angular:factory
  angular:filter
  angular:main
  angular:provider
  angular:route
  angular:service
  angular:value
  angular:view

Karma
  karma:app

Mocha
  mocha:app
  mocha:generator

Webapp
  webapp:app

yo的命令很简单:yo GENERATOR,例如:yo webapp, yo angular
Please choose a generator below: 下面列出了我的系统中,已经安装的generator的库,例如:Angular,Karma,Mocha,Webapp

2). 查询yo的支持库


~ D:\workspace\javascript>yo
Yeoman is a mask worn by the following members of the open-source community:

  Paul Irish, Addy Osmani, Mickael Daniel, Sindre Sorhus, Eric Bidelman,
  Frederick Ros, Brian Ford, Pascal Hartig, Stephen Sawchuk, and countless
  other contributors.

[?] What would you like to do? (Use arrow keys)
 > Install a generator
   Find some help
   Get me out of here!

命令行会提示,我们想要的操作。这里选择”Install a generator”


[?] What would you like to do? Install a generator
[?] Search NPM for generators:web

系统继续提示,我们要查找的包,我们输入web

3). 安装generator-webapp库


[?] Here's what I found. Install one? (Use arrow keys)
 > generator-armadillo
   generator-bones
   generator-btapp
   generator-fe
   generator-flight
   generator-hazdev-webapp
   generator-hbswebapp
   generator-html5-site
   generator-jing
   generator-lessapp
   generator-nodestrap
   generator-sails
   generator-server-configs
   generator-starter
   generator-starttter
   generator-ultimate
   generator-webapp
   generator-webapp-bfytw
   generator-webapp-fintan
   generator-weblog
   generator-website
   Search again
   Return home

yo列出了,所有在官方已经注册的,web关键字相关的包,我们选择“generator-webapp”

yo通过npm开始下载generator-webapp安装包


[?] What would you like to do? Install a generator
[?] Search NPM for generators: web
[?] Here's what I found. Install one? generator-webapp

generator-webapp@0.2.7 D:\toolkit\nodejs\node_modules\generator-webapp
├── cheerio@0.12.1 (entities@0.3.0, underscore@1.4.4, htmlparser2@3.1.4, cheerio-select@0.0.3)
└── yeoman-generator@0.12.3 (dargs@0.1.0, diff@1.0.5, debug@0.7.2, async@0.2.9, mime@1.2.11, mkdirp@0.3.5, isbinaryfi
le@0.1.9, underscore.string@2.3.3, shelljs@0.1.4, iconv-lite@0.2.11, lodash@1.3.1, rimraf@2.1.4, nopt@2.1.2, cli-table@0
.2.0, tar@0.1.18, glob@3.2.6, inquirer@0.2.4, request@2.21.0)

I just installed your generator by running:
    npm install -g generator-webapp

然后,我们退出yo命令行,选择“Get me out of here!”


[?] What would you like to do? Get me out of here!

Bye from us! Chat soon.
            Addy Osmani
          Sindre Sorhus
        Brian Ford
     Eric Bidelman
              Paul Irish
     Mickael Daniel
          Pasca1 Hartig
      Stephen S.wchuk
    Frederick R0s

上面的退出的文字是开发者的名字,很有意思一点是,竖着看最中间一行的文字排列是,yeoman1.0,也就是yeoman这个项目的得名了。

4). 注:上面的过程,也可以直接用命令

npm install -g generator-webapp

3. Yeoman工具包yo – 快速构建一个web项目

当我们安装了generator-webapp后,我们就可以,以非常优雅的方式来构建工程了。

1). 创建nodejs-yo目录,并构建webapp工程


~ D:\workspace\javascript>mkdir nodejs-yo
~ D:\workspace\javascript>cd nodejs-yo
~ D:\workspace\javascript\nodejs-yo>yo webapp

     _-----_
    |       |
    |--(o)--|   .--------------------------.
   `---------´  |    Welcome to Yeoman,    |
    ( _´U`_ )   |   ladies and gentlemen!  |
    /___A___\   '__________________________'
     |  ~  |
   __'.___.'__
 ´   `  |° ´ Y `

Out of the box I include HTML5 Boilerplate, jQuery and Modernizr.
[?] What more would you like?
  [ ] Twitter Bootstrap for Sass
 >[X] RequireJS
  [X] Autoprefixer for your CSS

对选项的解释:

  • Twitter Bootstrap for Sass:SASS是一种CSS的开发工具,提供了许多便利的写法,大大节省了设计者的时间,使得CSS的开发,变得简单和可维护。
  • RequireJS 可以帮助用户异步按需的加载 JavaScript 代码,并解决 JavaScript 模块间的依赖关系,提升了前端代码的整体质量和性能。
  • Autoprefixer解析CSS文件并且添加浏览器前缀到CSS规则里,使用Can I Use的数据来决定哪些前缀是需要的。

上面3个选择,由于Sass是基于Ruby的,我本机没有安装ruby,取消Twitter Bootstrap for Sass的勾选。

2). 查看安装日志:


Out of the box I include HTML5 Boilerplate, jQuery and Modernizr.
[?] What more would you like? RequireJS, Autoprefixer for your CSS
   create Gruntfile.js
   create package.json
   create .gitignore
   create .gitattributes
   create .bowerrc
   create bower.json
   create .jshintrc
   create .editorconfig
   create app/favicon.ico
   create app/404.html
   create app/robots.txt
   create app/.htaccess
   create app/styles/main.css
   create app/scripts/app.js
   create app/scripts/main.js
   create app/index.html
   create app/scripts/hello.coffee
   invoke   mocha:app
   create     test\index.html
   create     test\lib\chai.js
   create     test\lib\expect.js
   create     test\lib\mocha\mocha.css
   create     test\lib\mocha\mocha.js
   create     test\spec\test.js

I'm all done. Running bower install & npm install for you to install the required dependencies. If this fails, try running the command yourself.

项目骨架已经建好了。还包括了很多的配置文件.gitignore,bower.json,Gruntfile.js,favicon.ico, robots.txt, .htaccess。太神奇了,Cool!!

一下子装备都齐全了,打仗的事就交给我们自己吧。

4. Yeoman工具包bower,grunt的组合用法

有关bower的介绍,请参考:bower解决js的依赖管理
有关grunt的介绍,请参考:grunt让Nodejs规范起来

1). 使用bower命令查看项目依赖:


~ D:\workspace\javascript\nodejs-yo>bower list
bower check-new     Checking for new versions of the project dependencies..
nodejs-yo#0.0.0 D:\workspace\javascript\nodejs-yo
├── jquery#1.9.1 (latest is 2.0.3)
├── modernizr#2.6.2
└── requirejs#2.1.8

我们发现生成的webapp中,有4个依赖库,jquery,modernizr,requirejs。

2). 使用grunt命令执行单元测试


D:\workspace\javascript\nodejs-yo>grunt test
Running "clean:server" (clean) task
Cleaning ".tmp"...OK

Running "concurrent:test" (concurrent) task

Running "copy:styles" (copy) task

Running "coffee:dist" (coffee) task

Running "autoprefixer:dist" (autoprefixer) task
File ".tmp/styles/main.css" created.

Running "connect:test" (connect) task
Starting connect web server on localhost:9000.

Running "mocha:all" (mocha) task
Testing: http://localhost:9000/index.html

  .

  1 test complete (107 ms)

>> 1 passed! (0.11s)

Done, without errors.

3). 使用grunt命令启动一个node服务器


~ D:\workspace\javascript\nodejs-yo>grunt server
Running "server" task

Running "clean:server" (clean) task

Running "concurrent:server" (concurrent) task
    Warning: Running "compass:dist" (compass) task
Warning: You need to have Ruby and Compass installed and in your system PATH for this task to work. More info: https://g
ithub.com/gruntjs/grunt-contrib-compass Use --force to continue. Use --force to continue.

    Aborted due to warnings.

启动时,我们发现报错了。由于我没有装Ruby的环境,所以compass:dist的命令不能运行。

强制启动grunt


~ D:\workspace\javascript\nodejs-yo>grunt server --force
D:\workspace\javascript\nodejs-yo>grunt server --force
Running "server" task

Running "clean:server" (clean) task
Cleaning ".tmp"...OK

Running "concurrent:server" (concurrent) task

Running "coffee:dist" (coffee) task
    Warning: Running "compass:dist" (compass) task
Warning: You need to have Ruby and Compass installed and in your system PATH for this task to work. More info: https://
ithub.com/gruntjs/grunt-contrib-compass Use --force to continue. Used --force, continuing.

Running "compass:dist" (compass) task
Warning: You need to have Ruby and Compass installed and in your system PATH for this task to work. More info: https://
ithub.com/gruntjs/grunt-contrib-compass Use --force to continue.

Running "copy:styles" (copy) task

Running "autoprefixer:dist" (autoprefixer) task
File ".tmp/styles/main.css" created.

Running "connect:livereload" (connect) task
Starting connect web server on localhost:9000.

Running "open:server" (open) task

Running "watch" task
Waiting...

后台日志显示了“watch”的task,说明代码文件被监控着,如有修改网页会自动更新。

浏览器被自动打开,http://localhost:9000/
yeoman1

4). 修改app/index.html代码,增加对canvas的检查。


~ vi app/index.html

<script>
window.onload = function () {
if (canvasSupported()) {
alert('canvas supported');
}
};

function canvasSupported() {
var canvas = document.createElement('canvas');
return (canvas.getContext && canvas.getContext('2d'));
}
</script>

浏览器显示:
yeoman2

5). 通过bower增加库jquery-pjax


~ D:\workspace\javascript\nodejs-yo>bower install jquery-pjax
bower jquery-pjax#*         not-cached git://github.com/defunkt/jquery-pjax.git#*
bower jquery-pjax#*            resolve git://github.com/defunkt/jquery-pjax.git#*
bower jquery-pjax#*           download https://github.com/defunkt/jquery-pjax/archive/v1.7.3.tar.gz
bower jquery-pjax#*            extract archive.tar.gz
bower jquery-pjax#*           resolved git://github.com/defunkt/jquery-pjax.git#1.7.3
bower jquery#>=1.8              cached git://github.com/components/jquery.git#2.0.3
bower jquery#>=1.8            validate 2.0.3 against git://github.com/components/jquery.git#>=1.8
bower jquery-pjax#~1.7.3       install jquery-pjax#1.7.3

jquery-pjax#1.7.3 app\bower_components\jquery-pjax
└── jquery#2.0.3

~ D:\workspace\javascript\nodejs-yo>bower list
bower check-new     Checking for new versions of the project dependencies..
nodejs-yo#0.0.0 D:\workspace\javascript\nodejs-yo
├── jquery#1.9.1 (latest is 2.0.3)
├─┬ jquery-pjax#1.7.3 extraneous
│ └── jquery#1.9.1 (2.0.3 available)
├── modernizr#2.6.2
└── requirejs#2.1.8

Yeoman已经成功地帮助我们打造出一个项目的原型了,接下来我们可以针对自己的项目,自己熟悉的框架组合,构建一个属于自己的骨架模板,并发布到Yeoman的generator库中。

后面的内容会更精彩,敬请期待…!!

转载请注明出处:
http://blog.fens.me/nodejs-yeoman-intro/

打赏作者

bower解决js的依赖管理

从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发。Nodejs框架是基于V8的引擎,是目前速度最快的Javascript引擎。chrome浏览器就基于V8,同时打开20-30个网页都很流畅。Nodejs标准的web开发框架Express,可以帮助我们迅速建立web站点,比起PHP的开发效率更高,而且学习曲线更低。非常适合小型网站,个性化网站,我们自己的Geek网站!!

关于作者

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/nodejs-bower-intro/

bower

前言
一个新的web项目开始,我们总是很自然地去下载需要用到的js类库文件,比如jQuery,去官网下载名为jquery-1.10.2.min.js文件,放到我们的项目里。当项目又需要bootstrap的时候,我们会重复刚才的工作,去bootstrap官网下载对应的类库。如果bootstrap所依赖的jQuery并不是1.10.2,而是2.0.3时,我们会再重新下载一个对应版本的jQuery替换原来的。

包管理是个复杂的问题,我们要知道谁依赖谁,还要明确哪个版本依赖哪个版本。这些对于开发人员来说,负担过重了。bower作为一个js依赖管理的工具,提供一种理想包管理方式,借助了npm的一些思想,为我们提供一个舒服的开发环境。

你要还不动起手来试试bower,那你一定不会知道,前端开发是件多么享受的事。

目录

  1. bower介绍
  2. bower安装
  3. bower命令
  4. bower使用
  5. 用bower提交自己类库

1. bower介绍

Bower 是 twitter 推出的一款包管理工具,基于nodejs的模块化思想,把功能分散到各个模块中,让模块和模块之间存在联系,通过 Bower 来管理模块间的这种联系。

包管理工具一般有以下的功能:

  • 注册机制:每个包需要确定一个唯一的 ID 使得搜索和下载的时候能够正确匹配,所以包管理工具需要维护注册信息,可以依赖其他平台。
  • 文件存储:确定文件存放的位置,下载的时候可以找到,当然这个地址在网络上是可访问的。
  • 上传下载:这是工具的主要功能,能提高包使用的便利性。比如想用 jquery 只需要 install 一下就可以了,不用到处找下载。上传并不是必备的,根据文件存储的位置而定,但需要有一定的机制保障。
  • 依赖分析:这也是包管理工具主要解决的问题之一,既然包之间是有联系的,那么下载的时候就需要处理他们之间的依赖。下载一个包的时候也需要下载依赖的包。

功能介绍,摘自文章:http://chuo.me/2013/02/twitter-bower.html

2. bower安装

bower插件是通过npm, Node.js包管理器安装和管理的.

我的系统环境

  • win7 64bit
  • Nodejs:v0.10.5
  • Npm:1.2.19
~ D:\workspace\javascript>node -v
v0.10.5

~ D:\workspace\javascript>npm -v
1.2.19

在系统中,我们已经安装好了Nodejs和npm。win7安装nodejs请参考文章:Nodejs开发框架Express3.0开发手记–从零开始

安装bower
全局安装bower


~ D:\workspace\javascript>npm install bower -g

新建一个express3的项目nodejs-bower


~ D:\workspace\javascript>express -e nodejs-bower
~ D:\workspace\javascript>cd nodejs-bower && npm install

3. bower命令

bower安装后,我们就可以用bower这个命令了。

~ D:\workspace\javascript\nodejs-bower>bower
Usage:
    bower  [] []
Commands:
    cache                   Manage bower cache
    help                    Display help information about Bower
    home                    Opens a package homepage into your favorite browser
    info                    Info of a particular package
    init                    Interactively create a bower.json file
    install                 Install a package locally
    link                    Symlink a package folder
    list                    List local packages
    lookup                  Look up a package URL by name
    prune                   Removes local extraneous packages
    register                Register a package
    search                  Search for a package by name
    update                  Update a local package
    uninstall               Remove a local package
Options:
    -f, --force             Makes various commands more forceful
    -j, --json              Output consumable JSON
    -l, --log-level         What level of logs to report
    -o, --offline           Do not hit the network
    -q, --quiet             Only output important information
    -s, --silent            Do not output anything, besides errors
    -V, --verbose           Makes output more verbose
    --allow-root            Allows running commands as root
See 'bower help ' for more information on a specific command.

Commands,列出了bower支持的各种命令。

  • cache:bower缓存管理
  • help:显示Bower命令的帮助信息
  • home:通过浏览器打开一个包的github发布页
  • info:查看包的信息
  • init:创建bower.json文件
  • install:安装包到项目
  • link:在本地bower库建立一个项目链接
  • list:列出项目已安装的包
  • lookup:根据包名查询包的URL
  • prune:删除项目无关的包
  • register:注册一个包
  • search:搜索包
  • update:更新项目的包
  • uninstall:删除项目的包

4. bower使用

1). 安装jQuery到项目nodejs-bower


~ D:\workspace\javascript\nodejs-bower>bower install jquery
bower jquery#*              not-cached git://github.com/components/jquery.git#*
bower jquery#*                 resolve git://github.com/components/jquery.git#*
bower jquery#*                download https://github.com/components/jquery/archive/2.0.3.tar.gz
bower jquery#*                 extract archive.tar.gz
bower jquery#*                resolved git://github.com/components/jquery.git#2.0.3
bower jquery#~2.0.3            install jquery#2.0.3

jquery#2.0.3 bower_components\jquery

通过执行命令,我们可以看到jQuery的最新版本被下载,并安装到项目的bower_components\jquery目录

查看bower_components/jquery目录,发现了3个文件。


~ D:\workspace\javascript\nodejs-bower>ls bower_components/jquery -a
.  ..  .bower.json  component.json  jquery.js

同样地,我们的项目还需要d3的类库


~ D:\workspace\javascript\nodejs-bower>bower install d3
bower d3#*                  not-cached git://github.com/mbostock/d3.git#*
bower d3#*                     resolve git://github.com/mbostock/d3.git#*
bower d3#*                    download https://github.com/mbostock/d3/archive/v3.2.8.tar.gz
bower d3#*                     extract archive.tar.gz
bower d3#*                    resolved git://github.com/mbostock/d3.git#3.2.8
bower d3#~3.2.8                install d3#3.2.8

d3#3.2.8 bower_components\d3

非常方便,下载并安装完成!

2). 查看项目中已导入的类库


~ D:\workspace\javascript\nodejs-bower>bower list
bower check-new     Checking for new versions of the project dependencies..
nodejs-bower#0.0.0 D:\workspace\javascript\nodejs-bower
├── d3#3.2.8
└── jquery#2.0.3

3). 安装bootstrap库,并查看依赖情况


~ D:\workspace\javascript\nodejs-bower>bower install bootstrap
bower bootstrap#*               cached git://github.com/twbs/bootstrap.git#3.0.0-rc1
bower bootstrap#*             validate 3.0.0-rc1 against git://github.com/twbs/bootstrap.git#*
bower jquery#>= 1.9.0           cached git://github.com/components/jquery.git#2.0.3
bower jquery#>= 1.9.0         validate 2.0.3 against git://github.com/components/jquery.git#>= 1.9.0
bower bootstrap#~3.0.0-rc1     install bootstrap#3.0.0-rc1

bootstrap#3.0.0-rc1 bower_components\bootstrap
└── jquery#2.0.3

~ D:\workspace\javascript\nodejs-bower>bower list
bower check-new     Checking for new versions of the project dependencies..
nodejs-bower#0.0.0 D:\workspace\javascript\nodejs-bower
├─┬ bootstrap#3.0.0-rc1 extraneous
│ └── jquery#2.0.3
├── d3#3.2.8
└── jquery#2.0.3

我们发现bootstrap,对jquery是有依赖的。

4). 删除jQuery库,破坏依赖关系


~ D:\workspace\javascript\nodejs-bower>bower uninstall jquery
bower conflict      bootstrap depends on jquery
Continue anyway? (y/n) y
bower uninstall     jquery

~ D:\workspace\javascript\nodejs-bower>bower list
bower check-new     Checking for new versions of the project dependencies..
nodejs-bower#0.0.0 D:\workspace\javascript\nodejs-bower
├─┬ bootstrap#3.0.0-rc1 extraneous
│ └── jquery missing
├── d3#3.2.8
└── jquery missing

5). 安装低版本的jQuery,制造不版本兼容


~ D:\workspace\javascript\nodejs-bower>bower install jquery#1.7.2
bower jquery#~2.0.3             cached git://github.com/components/jquery.git#2.0.3
bower jquery#~2.0.3           validate 2.0.3 against git://github.com/components/jquery.git#~2.0.3
bower jquery#>= 1.9.0           cached git://github.com/components/jquery.git#2.0.3
bower jquery#>= 1.9.0         validate 2.0.3 against git://github.com/components/jquery.git#>= 1.9.0
bower jquery#1.7.2              cached git://github.com/components/jquery.git#1.7.2
bower jquery#1.7.2            validate 1.7.2 against git://github.com/components/jquery.git#1.7.2

Unable to find a suitable version for jquery, please choose one:
    1) jquery#1.7.2 which resolved to 1.7.2
    2) jquery#~2.0.3 which resolved to 2.0.3 and has nodejs-bower as dependants
    3) jquery#>= 1.9.0 which resolved to 2.0.3 and has bootstrap#3.0.0-rc1 as dependants

Prefix the choice with ! to persist it to bower.json

Choice: 1
bower jquery#1.7.2             install jquery#1.7.2

jquery#1.7.2 bower_components\jquery

~ D:\workspace\javascript\nodejs-bower>bower list
bower check-new     Checking for new versions of the project dependencies..
nodejs-bower#0.0.0 D:\workspace\javascript\nodejs-bower
├─┬ bootstrap#3.0.0-rc1 extraneous
│ └── jquery#1.7.2 incompatible with >= 1.9.0 (2.0.3 available)
├── d3#3.2.8
└── jquery#1.7.2 incompatible with ~2.0.3 (2.0.3 available)

我们可以清楚的看到bower,很明确的告诉了我们,jquery和bootstrap是不兼容的,强大之处大家应该有所体会。

6).升级jQuery,让版本兼容


~ D:\workspace\javascript\nodejs-bower>bower update jquery
bower jquery#~2.0.3             cached git://github.com/components/jquery.git#2.0.3
bower jquery#~2.0.3           validate 2.0.3 against git://github.com/components/jquery.git#~2.0.3
bower jquery#>= 1.9.0           cached git://github.com/components/jquery.git#2.0.3
bower jquery#>= 1.9.0         validate 2.0.3 against git://github.com/components/jquery.git#>= 1.9.0
bower jquery#~2.0.3            install jquery#2.0.3

jquery#2.0.3 bower_components\jquery

~ D:\workspace\javascript\nodejs-bower>bower list
bower check-new     Checking for new versions of the project dependencies..
nodejs-bower#0.0.0 D:\workspace\javascript\nodejs-bower
├─┬ bootstrap#3.0.0-rc1 extraneous
│ └── jquery#2.0.3
├── d3#3.2.8
└── jquery#2.0.3

多么智能,一键搞定,这才是高效的开发。

7). 查看本地bower已经缓存的类库


~ D:\workspace\javascript\nodejs-bower>bower cache list
bootstrap=git://github.com/twbs/bootstrap.git#3.0.0-rc1
d3=git://github.com/mbostock/d3.git#3.2.8
jquery=git://github.com/components/jquery.git#1.7.2
jquery=git://github.com/components/jquery.git#2.0.3

8). 查看D3库信息


~ D:\workspace\javascript\nodejs-bower>bower info d3
d3

  Versions:
    - 3.2.8
    - 3.2.7
    - 3.2.6
    - 3.2.5
    - 3.2.4
    - 3.2.3
    ...

9). 查看dojo库的url


~ D:\workspace\javascript\nodejs-bower>bower lookup dojo
dojo git://github.com/dojo/dojo.git

10). 用浏览器打开dojo的发布主页


~ D:\workspace\javascript\nodejs-bower>bower home dojo
bower dojo#*                not-cached git://github.com/dojo/dojo.git#*
bower dojo#*                   resolve git://github.com/dojo/dojo.git#*
bower dojo#*                  download https://github.com/dojo/dojo/archive/1.9.1.tar.gz
bower dojo#*                   extract archive.tar.gz
bower dojo#*                  resolved git://github.com/dojo/dojo.git#1.9.1

浏览器自动打开:https://github.com/dojo/dojo

11). 查询包含dojo的类库


~ D:\workspace\javascript\nodejs-bower>bower search dojo
Search results:

    dojo git://github.com/dojo/dojo.git
    dojox git://github.com/dojo/dojox.git
    dojo-util git://github.com/dojo/util.git
    dojo-bootstrap git://github.com/samvdb/Dojo-Bootstrap

真是方便实用的技术。

5. 用bower提交自己类库

1). 生成bower.json配置文件


~ D:\workspace\javascript\nodejs-bower>bower init
bower existing      The existing bower.json file will be used and filled in
[?] name: nodejs-bower
[?] version: 0.0.0
[?] main file:
[?] set currently installed components as dependencies? No
[?] add commonly ignored files to ignore list? Yes

查看生成的文件bower.json


{
  "name": "nodejs-bower",
  "version": "0.0.0",
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ],
  "dependencies": {
    "d3": "git://github.com/mbostock/d3.git#~3.2.8",
    "jquery": "git://github.com/components/jquery.git#~2.0.3"
  }
}

2). 在github创建一个资源库:nodejs-bower
3). 本地工程绑定github


~ D:\workspace\javascript\nodejs-bower>git init
Initialized empty Git repository in D:/workspace/javascript/nodejs-bower/.git/

~ D:\workspace\javascript\nodejs-bower>git add .
~ D:\workspace\javascript\nodejs-bower>git commit -m "first commit"
# On branch master
#
# Initial commit
#
# Untracked files:
#   (use "git add ..." to include in what will be committed)
#
#       app.js
#       bower.json
#       bower_components/
#       node_modules/
#       package.json
#       public/
#       routes/
#       views/
nothing added to commit but untracked files present (use "git add" to track)

~ D:\workspace\javascript\nodejs-bower>git remote add origin https://github.com/bsspirit/nodejs-bower

~ D:\workspace\javascript\nodejs-bower>git push -u origin master
Counting objects: 565, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (516/516), done.
Writing objects: 100% (565/565), 803.08 KiB, done.
Total 565 (delta 26), reused 0 (delta 0)
To https://github.com/bsspirit/nodejs-bower
 * [new branch]      master -> master
Branch master set up to track remote branch master from origin.

4). 注册到bower官方类库


~ D:\workspace\javascript\nodejs-bower>bower register nodejs-bower git@github.com:bsspirit/nodejs-bower.git
bower                          convert Converted git@github.com:bsspirit/nodejs-bower.git to git://github.com/bsspirit/n
odejs-bower.git
bower nodejs-bower#*           resolve git://github.com/bsspirit/nodejs-bower.git#*
bower nodejs-bower#*          checkout master
bower nodejs-bower#*          resolved git://github.com/bsspirit/nodejs-bower.git#af3ceaac07
Registering a package will make it visible and installable via the registry (https://bower.herokuapp.com), continue? (y/
n)                    y
bower nodejs-bower            register git://github.com/bsspirit/nodejs-bower.git

Package nodejs-bower registered successfully!
All valid semver tags on git://github.com/bsspirit/nodejs-bower.git will be available as versions.
To publish a new version, you just need release a valid semver tag.

Run bower info nodejs-bower to list the package versions.

5). 查询我们自己的包


D:\workspace\javascript\nodejs-bower>bower search nodejs-bower
Search results:

    nodejs-bower git://github.com/bsspirit/nodejs-bower.git

6). 安装我们自己的包


D:\workspace\javascript\nodejs-bower>bower install nodejs-bower
bower nodejs-bower#*            cached git://github.com/bsspirit/nodejs-bower.git#af3ceaac07
bower nodejs-bower#*          validate af3ceaac07 against git://github.com/bsspirit/nodejs-bower.git#*
bower nodejs-bower#*           install nodejs-bower#af3ceaac07

nodejs-bower#af3ceaac07 bower_components\nodejs-bower
├── d3#3.2.8
└── jquery#2.0.3

其实模块化,版本依赖,开发类库,发布类库,安装类库,都是一条命令!还能再简单一点么!快把项目模块化,然后分享给大家吧!!未来是属于开发者的。

转载请注明出处:
http://blog.fens.me/nodejs-bower-intro/

打赏作者