写点什么

Dojo Build 系统介绍

2011 年 9 月 02 日

1. 简介

Build 系统是产品正式发布的最后一道工序,其效率和质量直接决定着最终产品的效率和质量。虽然在传统应用中,Build 系统已经相当成熟,但在 Web 领域,依然是八仙过海,各显神通,甚至不经 Build 就直接上线的也比比皆是。Web 系统的零散性、复杂性,也决定了对其进行 Build 是一件复杂的事情。但通过 Dojo,我们认识到了一款开源的 Web 应用 Build 系统:bdBuild,也见识了其强大的功能。它是一个独立的通用 Build 系统,完全用 JavaScript 写成,可以运行于 NodeJS 或者 Rhino 等 JavaScript 引擎,理论上可以对任何 Web 应用进行 Build。下面就将介绍 Dojo 中是如何用 bdBuild 系统来实现 Web 应用的 Build 的。以此为起点,你也可以利用 bdBuild 实现自己的 Web 应用 Build 系统,对非 Dojo 的应用来进行打包。

2. bdBuild 系统简介

bdBuild 是一套开源的前端应用 Build 引擎,完全用 JavaScript 写成,可运行于 Node.js ,Rhino 等 JavaScript 引擎。其强大的功能和灵活可扩展的架构使得其能够应用于任何 Web 应用的打包。Build 在传统应用中可以翻译为构建,而在 Web 中,也许翻译成打包更加适合。一个合格的 Web Build 系统至少应该能够完成以下几件事情:

  1. 排除开发时文件,比如备份文件,代码中的调试信息,单元测试文件,等等。
  2. 将页面需要的多个资源文件打包成一个文件,并进行压缩,通常是针对 JavaScript 和 CSS 文件。这个过程包括了自动处理资源文件之间的依赖关系,能够按顺序进行打包。
  3. 拷贝资源文件到目标位置。

基本上来说,这些工作的最终目的都是为了提高性能,Http 协议的特性决定了多次请求取得多个小文件的效率远低于一次请求一个大文件。所以 Web Build 的首要目标就是合并小文件形成一个大文件。为了实现这些通用功能,bdBuild 系统将 Build 的过程分为以下几个步骤:

  1. 发现资源(discovery)。即找到最终产品所需要的所有资源,不仅包括 JavaScript 文件,还包括图片,CSS 等等。bdBuild 实现了默认的资源发现引擎,你也可以通过创建自己的资源发现引擎来告诉系统如何寻找需要的资源。
  2. 转换资源(transform)。即对每个资源进行相应的处理,这个处理是一个有序可扩展的步骤。例如,读取文本,压缩 JavaScript 代码,就是 2 个不同的转换步骤,前面所有转换步骤的结果是作为下一个步骤的输入,这样实现了对资源的多重加工。你可以通过配置文件来加入自己的资源处理步骤。
  3. 控制打包(build control)。这通过一个配置文件,来精确控制每个资源转换的顺序和依赖关系。bdBuild 还在其中引入了 Gate 的概念,将打包过程分为不同的阶段。

虽然当前 bdBuild 系统仍然处于 alpha 测试阶段,但是 Dojo 已经对其进行完善和封装,形成了自己的 Build 系统,在已经发布的 Dojo 1.7 beta 版本中,我们已经可以使用它来进行 Web 应用的打包。

3. Dojo Build 系统简介

要使用 Dojo 的 Build 系统,首先需要下载源码版的 Release 包,在 util/build 下就是 build 相关的工具:

Dojo 对 bdBuild 系统进行了相当程度的封装,使得针对 Dojo 的打包变的更加容易,通过引入层(layer)的概念,可以很方便的指定哪些模块应该被压缩到同一个 JavaScript 文件。同时,Dojo Build 系统还会自动把其它文件拷贝到目标文件夹,每个 JavaScript 文件或者 CSS 文件都会同时被压缩。下面的代码说明了 layer 的作用:

复制代码
<script type="text/javascript" src="/dojoroot/dojo/dojo.js"></script>
<script type="text/javascript" src="/dojoroot/dijit/dijit.js"></script>
<script type="text/javascript" src="/js /mylayer.js"></script>

这是在页面中引入 JavaScript 的一段典型代码,其中 dojo.js, dijit.js 和 mylayer.js 就是在 build 系统中配置的 3 个 layer,它们都包含了所有各自需要的代码。通过 layer 的方式,能够把页面需要的多个 JavaScript 文件打包成一个,加快了页面的载入速度。layer 是在 Build 的配置文件 profile 中指定的,如下面的介绍。

Profile 的概念

通常一个完整的系统会不只有一个 layer,而且对于同一页面,也有可能需要多个 layer。所以,Dojo 定义了 profile 这个概念,来描述整个打包的配置和参数。。在 dojoroot/util/buildscripts/profiles/ 下可以看找到系统自带的一些 profile 文件,它们用于打包标准的 dojo.js 和 dijit.js 等等。一个典型的 profile 文件示例如下:

复制代码
dependencies = {
layers: [
{
name: "dojo/dojo.js",
dependencies: [
"dijit._Widget",
"dijit._Templated",
"dojo.fx",
"dojo.NodeList-fx"
]
}
],
prefixes: [
[ "dijit", "../dijit" ],
[ "dojox", "../dojox" ],
[ "myNamespace", "~/src/myNamespace" ]
]
}

文件中定义了一个全局对象 dependencies。包含 2 个必须属性:layers 和 prefixes。在 layers 数组中,可以定义多个 layer。每个 layer 的 name 属性表明了输出的文件,是一个相对于 releaseDir(后面介绍如何指定)的相对路径。dependencies 数组包含了这个 layer 需要的模块。Build 系统会去递归寻找所有依赖的模块并将它们全部打包进来。

另一个属性是 prefixes 数组,其中定义的是模块映射关系,它告诉系统到哪里去寻找一个 Dojo 模块。其作用和应用代码中使用的 dojo.registerModulePath 是一样的。Prefixes 中的每个元素也是一个数组,包含两个元素,前面是模块前缀,比如 “dijit”,后面一个是相对于 util/ 路径的相对路径,比如“…/dijit”。

有了这个 profile,我们就可以来进行打包了。在 Dojo 中,是通过 util/build/build.js 来完成的。因为 Build 系统自身的代码都是 JavaScript,因此需要一个 JavaScript 运行环境,现在同时支持的是 NodeJS 和 Rhino。前者通常需要 Linux 或者 Cygwin 环境,后者则需要 Java 环境的支持。NodeJS 比 Rhino 运行速度快的多,条件允许的话,大家尽可能用 NodeJS 来进行 build。下面的代码演示了如何开始一个 build:

使用 NodeJS:

复制代码
node dojoroot/dojo/dojo.js load=build [options] 

使用 Java:

复制代码
java -Xms256m -Xmx256m -jar path/to/util/shrinksafe/js.jar path/to/dojo/dojo.js baseUrl=path/to/dojo load=build [options]

可以看到,build.js 文件接受多个参数(options),完整的参数列表可以通过指定—help 参数来获取,比如 releaseDir 指定了要输出 build 结果的文件夹。Action 指定了要执行的操作序列,例如 action=clean,check,release。当然还有一个最关键的参数:profile,它指定了打包的配置文件,从而控制整个打包的过程。例如:

复制代码
Node dojoroot/dojo/dojo.js load=build profile=/home/dojo/my.profile.js action=check,release

这里的 profile 可以是如下多种类型:

  • 如果是 html 文件,则分析其中的 dojo.require,从而自动生成一个包含所有模块的 profile
  • 如果是标准 profile 文件,则直接处理
  • 如果是文件夹,则扫描其中的所有以 profile.js 结尾的文件,分别进行打包。

命令行的完整参数如下面的表格所示:

参数 描述 --build 指定进行 build control 的脚本。 --profile 指定 profile 文件。 --action 指定要执行哪些操作,比如 check, clean, release。 --releaseDir 输出 build 结果的文件夹。 --version 指定版本号。### Layer 的定义

一个 profile 中可以有多个 layer。Layer 的配置参数除了上面介绍的 name 和 dependencies 之外,还有一个属性非常有用,那就是:layerDependencies。它指定了所依赖的 layer,所有出现在指定 layer 中的模块,都不会被包含在当前模块中。例如,假设有 2 个页面 P1 和 P2,他们所共用的代码被打包进 layerA,各自特殊的则被打包进 layerB 和 layerC。那么在描述 layerB 和 layerC 时就可以指定他们的 layerDependencies 为 layerA,从而 layerA 中的代码只会被用户 load 一次,提高了加载速度。而所有的 layer 都回隐含的依赖于标准的 dojo.js layer。所以在 dojo.js 中出现的代码是不会出现在其它的 layer 中的。

除此之外,layer 还支持以下可选属性:

copyrightFile 指定一个包含版权信息的文本文件,其内容将被包含在生成的 layer 文件中。 customBase 前面提到所有 layer 会依赖于标准的 dojo.js。这个属性可以改变这个默认行为,改为依赖于一个定制的 dojo.js。可能的场景是,你需要的是一个更小的 dojo.js。比标准的小很多。 keepRequires 一个数组,包含需要在运行是 require 的模块。Dojo 中可以用 dojo.require() 来引入一个 module,在 build 的时候会直接在 layer 中引入这些 module。如果你需要让某些文件需要时再 require,可以在这个参数中指定。 discard 布尔类型。表示当前 layer 是否需要写入一个文件。默认为 false,即一个 layer 当然要被写入一个单独的文件。但在某些情况下,一些 layer 只会作为其它 layer 的依赖而存在,这时此参数可以设置为 true。## 4. 小结

bdBuild 是一个灵活、可扩展的开源 build 系统,使用 JavaScript 写成,并运行于 Node.js, Rhino 等 JavaScript 环境。非常适合前端人员创建自定义的打包过程。Dojo 自带的 build 系统就是基于 bdBuild,本文简要介绍了其原理和用法,虽然对于一般的 Dojo 开发这已经足够,但是如果要深入理解 bdBuild,甚至开发其中的插件,仍然需要更多深入的了解。有兴趣的同学可以参考其文档,继续学习。

参考资料:


感谢张凯峰对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家加入到 InfoQ 中文站用户讨论组中与我们的编辑和其他读者朋友交流。

2011 年 9 月 02 日 00:004550

评论

发布
暂无评论
发现更多内容

全1子串算法求解、单元测试的必要性论述 John 易筋 ARTS 打卡 Week 32

John(易筋)

ARTS 打卡计划 全1子串算法求解 单元测试必要性

数据可视化平台搭建,警务实战平台大数据应用

t13823115967

数据可视化 可视化数据分析搭建 警务实战平台

架构师训练营 - 大作业一

lucian

第 5 周学习总结

Binary

极客大学架构师训练营

关于Dubbo的原理

皮蛋

架构师训练营第2期 第10周总结

月下独酌

极客大学架构师训练营

6. 抹平差异,统一类型转换服务ConversionService

YourBatman

Spring Framework 类型转换 Converter ConversionService

海纳百川无所不容,Win10环境下使用Docker容器式部署前后端分离项目Django+Vue.js

刘悦的技术博客

Python Docker 镜像 容器化 部署

HBC环保卫士系统搭建

Geek_a620db

数据库范式与反范式设计,是一门艺术

架构精进之路

数据库 范式

架构师训练营 第3期 第5周 作业和总结

ihiming

程序员的bug修复宝典

程序员 经验总结 bug修复

面试官:说说操作系统微内核和Dubbo微内核?

yes的练级攻略

dubbo 操作系统 微内核

物联网方面的竞赛有那些?

IoT云工坊

智能合约系统软件开发|智能合约APP开发

开發I852946OIIO

系统开发

vivo 全球商城:订单中心架构设计与实践

vivo互联网技术

分库分表 服务器 架构设计

Week10 作业

evildracula

生产环境全链路压测建设历程 21:某快递 A 股上市公司的生产压测案例之彩蛋 2 中篇

数列科技杨德华

全链路压测 七日更

第十周作业总结

hunk

极客大学架构师训练营

掌趣电竞系统开发搭建

Geek_a620db

指尖上的警务,打造微警务管理服务平台

t13823115967

智慧警务系统开发 微警务

第十周作业

hunk

极客大学架构师训练营

第 5 周作业提交

Binary

极客大学架构师训练营

架构师训练营第2期 第10周作业

月下独酌

极客大学架构师训练营

深入解析SpringMVC核心原理:从手写简易版MVC框架开始(SmartMvc)

Silently9527

Java mvc springmvc

2020年物联网行业有哪些新趋势

IoT云工坊

多币种钱包app系统开发,数字货币交易所系统源码开发

系统开发咨询:I76-883I-5I52 邓森

架构师训练营 - 大作业二

lucian

十、服务分解

Geek_28b526

使用 Serverless 创建一个简单的短网址服务

donghui

flask Serverless Lambda Store

共享单车系统搭建

Geek_a620db

演讲经验交流会|ArchSummit 上海站

演讲经验交流会|ArchSummit 上海站

Dojo Build系统介绍-InfoQ