利用google closure管理javascript模块依赖

    在web浏览器端管理javascript模块依赖,一直以来都采用直接引入script标签的方式,这种方式直观、一目了然。 

项目说明

    项目中有两个页面page1.html、page2.html,其中page1要引入三个模块a、b、c,page2需a、b、d, 这四个模块分别位于a.js、b.js、c.js、d.js中,其依赖为
c-->b(-->表示依赖于,下同),
d-->b,
b-->a

传统解决方式

    从依赖分析,页面引用如下:
page1.html:
<html>
<head>
<script type="text/javascript" src="a.js"></script>
<script type="text/javascript" src="b.js"></script>
<script type="text/javascript" src="c.js"></script>
</head>
<body>...</body>
</html>

page2.html:

<html>
<head>
<script type="text/javascript" src="a.js"></script>
<script type="text/javascript" src="b.js"></script>
<script type="text/javascript" src="d.js"></script>
</head>
<body>...</body>
</html>


麻烦来了    

    项目经过演化、重构之后,从b模块中分出b1和b2模块,分别位于b1.js和b2.js中,而新的依赖为
b1-->a,
b2-->a,
c-->b1,
d-->b2
页面需修改为

page1.html:

<html>
<head>
<script type="text/javascript" src="a.js"></script>
<script type="text/javascript" src="b1.js"></script>
<script type="text/javascript" src="c.js"></script>
</head>
<body>...</body>
</html>
page2.html:
<html>
<head>
<script type="text/javascript" src="a.js"></script>
<script type="text/javascript" src="b2.js"></script>
<script type="text/javascript" src="c.js"></script>
</head>
<body>...</body>
</html>


缺点分析

    这种js模块间的依赖重构影响到页面的标签引用,丧失了部分灵活性,并且需要手动维护,不能保证修改完全正确。

缺点:

  1. js重构与页面重构耦合增加;
  2. 开发效率低下;
  3. 引入多个script标签,增加http请求数量,延迟时间增加,损害用户体验;
  4. 人工维护,可能遗漏需修改页面,容易引入错误;
  5. 考虑到http请求数量问题,不能更细分模块


google closure的解决办法

    google closure分两个阶段,a)开发或debug阶段,b)与发布阶段。

    具体实现:在closure library中,模块的发布与依赖通过base.js中的goog.provide("...")和goog.require("...")实现,
例如,a模块所在的a.js中要发布a模块,在a.js中声明

goog.provide("a");
即可实现,a代表在项目中唯一id,推荐使用package的格式,

b依赖于a,在b.js中声明

goog.provide("b");
goog.require("a");
c依赖于b,在c.js中声明
goog.provide("c");
goog.require("b");
page1.html修改为:
<html>
<head>
<script type="text/javascript" src="closurepath/base.js"></script>
<script type="text/javascript" src="c.js"></script>
</head>
<body>...</body>
</html>
注意在开发阶段,因为各模块js是通过动态插入script标签实现,所以在c.js中代码需要进行一点小改动,将c.js中依赖于其他模块的js代码部分放入window.onload之类监听函数中,避免出现变量undefined错误。

到这里,开发者可能会有疑问,开发阶段动态插入script标签,那么各js文件路径怎么得到?其实在加载运行base.js中,还会插入deps.js,该文件中配置依赖信息,包括js文件路径(相对于base.js), 发布的模块以及依赖的模块。这个文件无需人工维护,在closure library 中有python脚本(caldeps.py)会帮助你维护这些信息,当模块依赖关系有变动时,运行该脚本即可。  

    让我们再回到之前的重构情景中,当b模块重构成b1和b2模块时,只需要调整各js中依赖(再运行caldeps.py脚本更新deps.js),而html无需改动。

    下一步来到发布编译阶段,假如我们将最终合并编译的js文件命名为c.c.min.js,html需要做一点改动
page1.html为:

<html>
<head>
<script type="text/javascript" src="c.c.min.js"></script>
</head>
<body>...</body>
</html>

这里遇到开发阶段与发布阶段引用的js不同问题,该问题比较容易解决,可以使用服务端动态网页技术来解决,例如采用ssi标签,这里不做详细说明,请参考 http://wasd.vsm.com.au/ht_root/doc/env/

google closure的优点

  1. 提供模块依赖,不需人工管理依赖链(各个模块负责自己的依赖);
  2. 减少http请求数量;

转载于:https://my.oschina.net/jinker/blog/99314

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值