高能预警,前方山路十八弯html
在上一篇文章里简单的讨论了一下模块化Js, 先来回顾一下目前模块化的两大规范:jquery
CommonJs 同步加载模块规范gulp
AMD/CMD 异步加载模块规范app
其中CMD规范的产出是国内目前十分火爆的SeaJs, 这篇文章主要是解释几个使用SeaJs会碰到的重要概念异步
具名模块模块化
匿名模块函数
路径即ID原则grunt
SeaJs定义匿名模块通常采用以下的方式:工具
define(function(require,exports,module){xx})
SeaJs定义除了定义匿名模块,还能够定义具名模块ui
//define(BlockID,[Deps],function(require,exports,module){}) define(‘A’,[],function(require,exports,module){xx})
其中能够
第一个参数 定义该模块的名字(即ID),用来惟一标识该模块
第二个参数 把该模块依赖的模块从函数体里提到参数中,用来标识该模块还依赖了哪些模块
第三个参数 模块主体
诚然,咱们能够把全部模块都以匿名的形式书写。但这样有个很大的缺点,就是模块化会致使Js文件特别多,这样无形中会加大了http请求的数
咱们在知道,在文件比较小的时候, 文件的大小并不显著影响http的下载速度, 可是若是把这个文件拆成两个文件下载,增长的一次http开销确是很大的
因此,不少状况下咱们须要把零碎的Js模块进行合并成一个文件。可是这么多模块合并在一个文件里,全是匿名的话,系统如何区别哪一个是哪一个模块呢? 所以,咱们须要对这些模块给不一样的ID进行标识。 因而这些带了ID的模块,就叫作具名模块
上面解释了什么是具名模块,为何须要用具名模块,咱们如今就来给具名模块命名
SeaJs遵循的是路径即ID命名规则,意思就是具名模块的ID名是路径的一部分. 而沿着最终拼接出来的路径,确定能够找获得这个具名模块
听起来很绕,但这个规则很是很是很是重要.做者也是在理解SeaJs路径的过程当中踩坑无数,这里就来重点讲一下
首先来看SeaJs的路径的书写种类,总的来讲,能够分为3种.
相对路径(以相对路径符开头,好比../js/
), 路径以本页面为起点
直接路径(以直接目录开头,好比js/
), 路径以baseUrl为起点
根路径(以根路径开头, 好比/app/js/
) 路径以项目根目录为起点
这里拿入口文件index.html举例:
<!--例1--> <script> seajs.config({ base: "../js/", alias:{"JQ":"lib/jquery"} }) seajs.use("src/index.js") </script>
base
参数是以当前页面(index.html)为参照,设定基础相对路径baseUrl.
在本例中base
设定采用相对路径的形式, 那么baseUrl = (index.html的位置) + (../js/)
alias
可以给具名模块(例子中该匿名模块ID为lib/jquery)取别名(JQ),取别名的好处在于能够把具名模块自己很是冗长的路径命名变得很短很小清新,通常是针对页面须要引用的库文件.
在本例中JQ 后的路径是采用直接路径的形式, 那么JQ的路径= (baseUrl) + (lib/jquery) = (index.html的位置)+ (../js/) + (lib/jquery/
)
sea.use
用来指定SeaJS加载器的入口, 经过在入口js再加载七七八八页面所需的JS模块达到按需加载的目的
在本例中,sea.use的路径是采用直接路径的形式, 那么入口文件index.js的路径 = (baseUrl) + (src/index.js) = (index的位置) + (../js/) + (src/index.js)
若是换一种形式写:
<!--例2--> <script> seajs.config({ base: "../js/", alias:{"JQ":"../js/lib/jquery"} }) seajs.use("../js/src/index.js") </script>
base设定采用相对路径的形式, 那么baseUrl = (index.html的位置) + (../js/)
alias JQ 后的路径是采用相对路径的形式, 那么JQ的路径= (index.html的位置) + (../js/lib/jquery)
sea.use的路径是采用相对路径的形式, 那么入口文件index.js的路径= (index.html的位置) + (../js/src/index.js)
如今拿例1来讲:
<!--例1--> <script> seajs.config({ base: "../js/", alias:{"JQ":"lib/jquery"} }) seajs.use("src/index.js") </script>
既然alias中具名模块叫lib/jquery, 那么你的jquery经过define定义的模块ID必定是lib/jquery
define(‘lib/jquery’,[],function(require,exports,module){xx})
又因为alias
中具名模块(lib/jquery)
的采用了直接路径的方式, 根据路径即ID的原则,你应该能够顺着 (baseUrl) + (lib/jquery)
找到该具名模块的位置,若是找不到,确定会报错
如今拿例2来讲:
<!--例2--> <script> seajs.config({ base: "../js/", alias:{"JQ":"../js/lib/jquery"} }) seajs.use("../js/src/index.js") </script>
既然alias中具名模块叫../js/lib/jquery, 那么你的jquery经过define定义的模块ID必定是../js/lib/jquery
define(‘../js/lib/jquery’,[],function(require,exports,module){xx})
又因为alias
中具名模块(../js/lib/jquery)
的采用了相对路径的方式, 根据路径即ID的原则,你应该能够顺着 index.html当前位置 + (../js/lib/jquery)
找到该具名模块的位置,若是找不到,确定会报错
但实际的使用上,咱们基本不会去写具名模块, 而是所有写匿名模块
而后经过自动化构建工具(好比grunt,gulp,fis3)的插件去自动解决匿名模块具名化的问题,好比grunt就提供了相关插件:
grunt-cmd-transport 将匿名模块转换成具名模块
grunt-cmd-concat 将具名模块合并压缩到一个Js文件里
SeaJs大法好,Grunt大法好 但在使用这些工具的之时,并非简单抄一两个demo就完事. 不少状况下你要根据本身工程的特性来调整目录结构,而模块所在的路径
,和模块的ID
, 和最后JS合并压缩
的过程息息相关. 因此必须理解它们的规则,运用起来才能更加驾轻就熟