每一个js文件头部都应该用goog.provide和goog.require来声明自己提供的类和需要依赖的类。
goog.provide()工作原理:
根据'.'来分割字符串,然后创建对象,实际上级和下级的命名空间的关系就是对象和属性的关系比如:
goog.provide("demo.Example");
实际上执行了一下操作:
var demo = goog.global.demo || (goog.global.demo = {});//如果不存在demo就创建一个。
if(!demo.Example) demo.Example = {};//如果不存在demo.Example,则创建一个。
在实际项目中一般都会定义一个root命名空间,比如“知乎”所有的类都是在ZH命名空间下的。这样做的好处就是避免名称冲突。
如果没有使用closure,也可以用同样的原理来管理命名空间。比如:var root={},然后把所有的函数和类都挂在root的属性上:
root.say = function(){}.
这比另一种用名称前缀的方式(root_say)要好得多。
goog.require():
goog.require:实际上是把依赖的对象所在的js文件通过
document.write("<script src="xxx.js"></script>")的方式写入到html中。所以goog.require()一个类后,就可以使用这个类了。
其依赖于deps.js中提供的表来确定一个类的文件位置以及这个类是不是依赖其他类。
deps.js里面每一行都对应一个文件,并记录了此文件提供的类和依赖的类,形式如下:
goog.addDependency("../../../dependency_test/example.js", ['demo', 'demo.Example'], ['goog.dom', 'demo.Example2']);
addDependency函数的作用是把这三个参数存在goog.dependencies_中。
因此,使用reqiure函数时,其会在goog.dependencies_中找到类对应的文件位置,从而可以通过dom操作将文件载入页面。
calcdeps.py:
已经不推荐使用此文件,推荐用closurebuilder.py
在上一章的demo中:
4 <script src="../closure-library/closure/goog/base.js"></script>
5 <script src="example.js"></script>
必须引入所有自己创建的js文件,而且必须按依赖顺序引入才行,假设一个大的项目有几百个js,这样做显然非常麻烦,而且多次请求会消耗大量资源。
所以library提供了一个calcdeps.py的工具,可以每个文件头部的goog.require和goog.provide计算所有文件的依赖关系,并且可以用它来生成单个包含所有内容的js文件。
1,生成包好所有内容的单个js文件
可以使用calcdeps.py生成单个js文件,然后在html中只引入这个js文件即可
使用方法如下:
closure-library/closure/bin/calcdeps.py -i example.js -p closure-library/ -o script > main.js
其中三个参数
-i 输入文件/文件夹列表
-p closure-library的路径
-o 输出模式,有四种,官方介绍如下:
使用script模式,会把计算所有js文件的依赖顺序,然后把所有js文件的内容按依赖顺序连接起来,然后用管道命令'>'把结果导入all.js,在html中只需要引入这个main.js文件即可。
所以如果有一个大项目,包含几十个js文件,则可以使用calcdeps.py来生成一个唯一的js文件。
closure-library/closure/bin/calcdeps.py -i js/ -p closure-library/ -o script >main.js
//其中js/是所有js文件的存放路径
在测试的时候发现生成的main.js文件最后一行少一个'/'使注释标签未闭合导致语法错误,不知道是为什么,自己手动加上就好了。
calcdes.py还有调用compiler进行压缩的功能,实际发布产品的时候都会压缩main.js。
假设只想使用特定的几个类而没必要导入所有的js文件,而且希望看到js文件原来的样子而不是被压成一个文件,通常是模块测试的时候。
但是又不希望自己手动引用那么多个js文件。
可以使用calcdeps.py来生成一个deps.js依赖表,然后就可以在html中引入这个deps.py,然后 就可以在html中使用goog.require()来加载需要引用的类。
../closure-library/closure/bin/calcdeps.py -o deps --dep ../closure-library/closure/goog/ -p js/ > deps.js
注意:在方法一中是不需要在html页面中使用goog.require的,但是为什么方法二中需要?因为方法1中已经把所有js文件内容都通过script标签加载了,所有的对象都已经加载了,当然不需要require。但是在方法2中,生成的deps.js只是存了一个依赖关系表,并没有加载js,所以需要通过require来加载指定类后才能使用。
closurebuilder.py 和depswriter.py
官方教材:https://developers.google.com/closure/library/docs/closurebuilder
这两个工具分别用在发布模式下和开发模式下
假设是在发布模式下,需要把所有的相关js都合并压缩一个js文件。
如果是开发模式,则需要计算依赖关系引入所有需要的js文件,方便调试。
发布模式:编译压缩自己的项目:
假设自己的js'都放在js/目录下,现在用closurebuilder.py将所有需要的文件编译为一个大的压缩过的文件,命令如下
closure-library/closure/bin/build/closurebuilder.py \
--root=closure-library/ \
--root=myproject/ \
--namespace="myproject.start" \
--output_mode=compiled \
--compiler_jar=compiler.jar \
--compiler_flags="--compilation_level=ADVANCED_OPTIMIZATIONS"
> compiled.js
ClosureBuilder writes the compiler's output to standa
参数说明:
--root : 指定需要扫描的目录,一般包括两个:自己的目录和closure-library的目录
--namespace: 需要使用的命名空间,包括在该命名空间下的代码都会被扫描
--output_mode:输出模式
--compiler_jar : 编译器路径
--compiler_flags: 编译器的参数
最后用一个管道命令将其导入到一个文件中,最后使用时只要引入这一个文件即可
参数说明:
Options:
-h, --help show this help message and exit
-i INPUTS, --input=INPUTS
One or more input files to calculate dependencies for.
The namespaces in this file will be combined with
those given with the -n flag to form the set of
namespaces to find dependencies for.
-n NAMESPACES, --namespace=NAMESPACES
One or more namespaces to calculate dependencies for.
These namespaces will be combined with those given
with the -i flag to form the set of namespaces to find
dependencies for. A Closure namespace is a dot-
delimited path expression declared with a call to
goog.provide() (e.g. "goog.array" or "foo.bar").
--root=ROOTS The paths that should be traversed to build the
dependencies.
-o OUTPUT_MODE, --output_mode=OUTPUT_MODE
The type of output to generate from this script.
Options are "list" for a list of filenames, "script"
for a single script containing the contents of all the
files, or "compiled" to produce compiled output with
the Closure Compiler. Default is "list".
-c COMPILER_JAR, --compiler_jar=COMPILER_JAR
The location of the Closure compiler .jar file.
-f COMPILER_FLAGS, --compiler_flags=COMPILER_FLAGS
Additional flags to pass to the Closure compiler.
--output_file=OUTPUT_FILE
If specified, write output to this path instead of
writing to standard output.
开发模式:计算依赖关系
使用depswriter.py来计算依赖关系
$ closure-library/closure/bin/build/depswriter.py \
--root_with_prefix="myproject ../../myproject" \
> myproject-deps.js
参数说明:
其中--root_with_prefix参数是指定当前需要扫描的目录,并且指定计算出来的引用中每一个文件的前缀。
前缀就是当前myproject相对于goog目录的路径,即在goog目录下如何进入myproject目录。因为使用依赖文件的是goog目录下的base文件,不指定前缀就无法找到myproject目录。
使用的时候需要引入closure库和计算出来的deps.js文件
<scriptsrc="/closure/goog/base.js"></script>
<scriptsrc="/myproject/myproject-deps.js"></script>
只要以上两行代码即可,closure会根据myproject-deps.js中的依赖关系自动加载其他文件