用grunt构建seajs项目的总结

来源:互联网 发布:自学c语言看什么书 编辑:程序博客网 时间:2024/06/05 10:49

最近半个月,将seajs构建方式从spm-build改为grunt + grunt-cmd-xxx,踩坑无数,今天终于基本大功告成,在此总结一下:

首先,这个帖子写得不错,介绍了为什么seajs构建这么麻烦:为什么seajs构建这么麻烦

其实最关键的一个问题,就是用grunt-cmd-transport来提取依赖的时候,会将间接依赖也写入deps[],于是会造成大量无效的http请求(404),关键的参数有2个,一个是transport task的paths参数,第二个是concat task的include参数

关键参数

paths:表示transport时,到哪里找依赖的模块,如果找到就写入deps[]。如果没有找到则报错,但是可以用--force参数强制继续,不会写入deps[]

include:表示concat时,合并哪些文件。有3个可选值,self,relative(默认),all

self基本是没用的;relative只会合并相对标识的依赖;all会合并所有依赖:标准构建

require("./menu");// 设置include:relative时会合并require("uiframework/static/package");// 设置include:all时会合并

目录结构

源码目录结构大致是这样的:


在src下有N个模块,每个模块都有很多.js,规定以package.js作为此模块的出口。如果外部模块需要依赖该模块,就用:

require("xxx/static/package");

第一版

将transport的paths配置为src,concat的include配置为relative

合并后得到的package.js文件类似这样:


可以看到,deps[]数组里把间接依赖也全部写进来了,正常应该只有uiframework/static/package。像红框里的这些文件,在合并后已经不存在了(开发阶段才有),但是seajs还是会发起无效的HTTP请求

第二版

为了解决这个问题,把concat的include配置为all

这样会把这些文件也全部合并进来,倒是不会再发起无效的http请求了,但是这样有2个问题

1,合并后的package.js文件超大,而且大量重复。因为每个模块都有package.js(模块出口),其中有大量重复的内容

2,每个模块都有menu.js,代码中是:

require("./menu");

但是合并以后,每个package.js都有多个menu,比如employee/static/menu,hair/static/menu,这样seajs就不知道应该使用哪个menu,造成加载失败。所以这种规避404的办法行不通

第三版

观察用spm build合并出来的文件:


可以看到deps[]是正确的,只依赖每个外部模块的出口(当然还有模块内部的所有js),这样就很完美,不会发起无效的HTTP请求,而且也不需要合并多余的文件进来

spm-build内部使用的也是grunt-cmd-transport和grunt-cmd-concat,所以没道理spm-build能构建成功,自己写grunt就不行。一怒之下看了spm-build的源码,发现它配置的include也是relative,而paths配置是错的


这里配置的paths我的目录结构里根本就没有,所以等于是没有配置paths参数,于是在我的Gruntfile里也把paths去掉,运行grunt报错,使用--force强制继续,最后就得到了跟spm-build一模一样的构建结果。区别是spm-build要求是标准目录结构,而且需要到每个模块下执行一遍;用grunt则可以自定义目录结构,而且可以一键构建

总结

1、paths不要配置,用--force强制执行

2、include配置为relative

3、开发中规定每个模块只有一个出口,这样

require("module_name/static/package");
这行代码,无论在开发态还是部署态都是OK的,算是取了个巧

4、开发态和部署态的相对目录结构要保持一致,这是为了满足seajs的约定(模块ID即路径)