转:seajs的spm使用摸索
~~~spm是基于nodejs的,打开nodejs命令行工具,npm install spm -g 进行spm的安装,过程很漫长 github上的官网不能访问
seajs自带的spm打包工具相关文档略少,在粗读了一点源代码之后,我摸索出了spm使用上的一些要点,记录为此文
压缩JS文件
只需要执行这个命令即可
spm build xxx.js
这时候你将得到一个压缩过的__build/xxx.js文件
合并JS文件
如果希望将JS文件中require的其他模块都合并到这个文件中,我们可以加上--combine参数
另外记得这时候必须传递--app_url参数,用于生成module的id,如
spm build xxx.js --combine --app_url http://x.com
你将与上面一样得到一个__build/xxx.js文件,但是这个js中require的模块也都合并在这个文件中了
合并JS文件的规则
一般说来,前端优化时,并非链接数越少越好,对于通用JS类库,由于在多个页面中都会被引用,单独加载可以利用到浏览器缓存
spm在合并时,也考虑到了这种情况,因此它遵循这样一个规则,即只合并require的“相对标识”的模块,而不合并require的“顶级标识”的模块
对“相对标识”和“顶级标识”不了解的参见http://seajs.com/docs/zh-cn/module-identifier.html
为什么是这样一条规则呢?因为seajs的作者推荐使用这样一条规则来require模块:
“推荐使用 require('xxx') 这种方式引用通用类库,使用 require('./xx') 或 require('../path/to/yy') 引用业务模块”
所以,spm在合并时,不会合并通用类库的模块,而判断是否是通用类库的依据就是“相对标识”与“顶级标识”,因此这也要求我们在书写代码时,需要遵守以上的规则
强制合并通用类库
某些特殊情况下,我们希望将通用类库也合并进来,当然最简单的办法就是在代码中使用“相对标识”来require通用类库,不过这个办法实在太蠢
而且spm也有相应的处理方案,我们需要添加--combine_all参数,但是这时候我们还必须传递--base_path参数,指定通用类库所在的文件夹,也就是seajs的base路径
命令参考如下
spm build xxx.js --combine_all --app_url http://x.com --base_path ./lib/
输出文件路径
默认情况下,spm会把文件输出到当前文件同级的__build子文件夹下,在以上几点的例子里面已经看到了
spm也支持用--out_path参数自定义路径,而且如果有同名文件的话会自动覆盖,这点在部署时候做自动化替换很有用
命令参考如下
spm build xxx.js --combine --app_url http://x.com --out_path .
以上命令会将当前的xxx.js替换为合并后的
app_path参数
以上的讨论,都是假设JS文件位于“根”下面,也就是说
假设js在文件系统的目录为D:\project\xxx.js,而未来部署后,访问路径为http://x.com/xxx.js
那么进入D:\project目录,执行spm build xxx.js --combine --app_url http://x.com命令,这时候build出的文件是没有问题的
下面考虑一下复杂的情况:
假设js在文件系统中位于D:\project\javascript\xxx.js,而部署后,访问路径为http://x.com/javascript/xxx.js
那么如果我们进入D:\project\javascript目录,执行上述同样命令,这时候build出的文件是有问题的,哪里有问题呢?打开build出的文件一看就知道了
一般这时候文件中define的id语句是这样的
define("http://x.com/xxx.js", //省略
明显这是有问题,我们期望编译出的id应该是http://x.com/javascript/xxx.js,假设路径再深一点,如果存在两个同名而目录不同的js,就会存在define id重复了
那么如何解决呢?我发现spm还提供一个--app_path参数,尝试执行以下命令,将项目的“根”路径做为--app_path参数
cd D:\project
spm build javascript\xxx.js --combine --app_url http://x.com --app_path D:\project --out_path .
这时候因为out_path为. 所以xxx.js已经被替换掉了,打开发现define id正确无误,是http://x.com/javascript/xxx.js
这是因为当传递了--app_path参数时,spm会计算要合并的js文件的路径与这个路径的相对路径,举例来说,就是计算出D:\project\javascript\xxx.js与D:\project的相对路径,也就是javascript\xxx.js,然后将这个路径再与--app_url参数连接,作为define的id
注意:但是这里有个问题,如果不指定--out_path时,spm会出错,因为这时候--out_path默认为D:\project\javascript_build\javascript,而似乎spm只能新建_build文件夹,对于下级文件夹不会再新建,所以会报错
使用build-config.js
如果不希望在敲命令时候传那么多乱七八糟的参数,可以将这些参数写在build-config.js里面,如下
module.exports = { "base_path": "../", "app_url": "http://x.com", "app_path": "http://www.cnblogs.com/" };
当你在某个目录下执行spm build命令时,spm会自动寻找当前目录下有没有build-config.js文件,如果有则将内容解析为参数
当然如果你不喜欢这个名字,你还可以在执行spm命令时,用--config指定build配置文件
loader_config参数
如果你在某个js文件中,使用了seajs.config做了alias的配置,则打包时,需要传递--loader_config参数,将文件传给spm