在之前的项目中一直用的是seajs,感觉seajs是挺好用的,但是有个问题就是把现有的js框架打包成seajs模块略麻烦,官方文档里面也没有对这一块作详细的介绍,虽然有spm build,但还是觉得不太方便。因此便在新的项目中用了requirejs。
用requirejs其实还有另一个原因就是项目中用到了百度的图表库echarts,根据其官方文档的描述是不建议使用基于CMD规范的seajs来加载的,因为echarts是基于AMD模块化的,虽然网上有人改了可以用seajs加载,但是我最后还是选择用requirejs来加载,同时也是想尝试一下requirejs。
自定义构建echarts
echarts
的构建是用的r.js
,因此我在这里先讲一下。
自定义构建echarts
还必须下载zrender
,下载完成之后,把echarts
的目录和zrender
目录放在同级目录下,然后进入echarts
的build
目录进行自定义build
(需要node.js环境),下面是我的build命令:
1
| node build.js optimize=true exclude=force,scatter,k,radar,chord,gauge,funnel,map output=echarts1.js
|
上面命令的意思是排除exclude
的之后的那些模块,因为我只用到了echarts
的折线图、柱状图和饼状图。
执行完成之后就可以在build目录看到刚才合并的echarts1.js
requirejs模块加载配置
requirejs
引入主模块的方法是通过在script标签里面添加data-main
属性,如我的引入代码:
1
| <script data-main="js/main" src="js/lib/requirejs/require.js"></script>
|
main.js
是程序的入口js文件,然后我们在main.js
里面进行模块的加载配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| requirejs.config({ urlArgs: "v=" + Date.now(), baseUrl: 'js', shim: { 'backbone': { deps: ['underscore', 'jquery'], exports: 'Backbone' }, 'underscore': { exports: '_' }, 'backbone.localStorage': { deps: ['backbone'], exports: 'Backbone' }, 'bootstrap.modal': { deps: ['jquery'], exports: 'jQuery.fn.modal' } }, paths: { jquery: 'lib/jquery/jquery-1.11.1.min', underscore: 'lib/underscore/underscore-min', ... text: 'lib/requirejs/plugins/text', echarts:'lib/echarts/echarts', 'echarts/chart/bar' : 'lib/echarts/echarts', config: 'modules/common/config' } });
require(['backbone', 'modules/app'], function (Backbone, AppRouter) { new AppRouter(); Backbone.history.start(); });
|
requirejs模块定义与加载
requirejs
定义一个模块相当简单,下面是一个简单的例子:
1 2 3 4 5 6 7 8
| define(['backbone'], function(Backbone){ var AppRouter = Backbone.Router.extend({ ... });
return AppRouter; });
|
我们也可以动态加载模块:
1 2 3 4 5 6 7 8 9 10 11 12 13
| define(['backbone'], function(Backbone){ var AppRouter = Backbone.Router.extend({ ... index: function(){ require(['echarts', 'echarts/chart/bar'], function(ec){ ... }); } });
return AppRouter; });
|
如果你已经用习惯了seajs
的模块加载方法的话,你也可以像seajs
里面那样去加载模块:
1 2 3 4 5 6 7
| define(function (require) { var $ = require('jquery');
return function () { ... }; });
|
或者CommonJS
的方式也ok:
1 2 3
| define(function(require, exports, module) { ... });
|
requirejs
提供一个加载文本的插件text.js
,细心的话你可能已经看到我在requirejs.config
里面已经配置了,使用也很简单:
1 2 3 4 5 6
|
define(['backbone','text!../tmpl/index.html'], function(Backbone, html){ });
|
requirejs构建工具r.js
当项目上线的时候,我们可能需要对模块代码进行压缩合并的操作,这时我们就会用到requirejs
的构建工具r.js
。首先我们在项目根目录创建一个build
的文件夹和dist
的文件夹,分别用来存放模块合并相关配置和合并后的代码的文件目录,在build
目录里面存放r.js
,并新建一个压缩合并的配置文件config.js
,下面是config.js
的配置示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| { mainConfigFile : "../js/main.js", baseUrl: '../js', name: "main", out: "../dist/js/main.js", removeCombined: true, findNestedDependencies: true }
|
然后在命令行执行:
执行完成之后便会在dist/js/
目录下面生成一个合并后的main.js
你会发现这个main.js
可能会非常大,而在实际项目中,像通用的一些jquery、backbone等有时候我们可能没有必要把它压缩进来,我们只需要压缩自己写的一些代码,于是我们再次开始配置我们的config.js
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| { mainConfigFile : "../js/main.js", baseUrl: "../js", removeCombined: true, findNestedDependencies: true, dir: "../dist/js", modules: [{ name: "main", exclude: [ "backbone", "underscore", "jquery", "text", ... ] }] }
|
再次运行压缩合并命令将会发现在exclude
数组里面的项不会被合并。
然而我觉得更好的做法是把通用的一些库,如jquery,bacnbone等合并到一个文件里面,我们自己的代码合并到了一个文件,因此,我们重新进行配置。
首先我们新建一个js文件,这个js文件啥也不用做,就是为了引用所有通用的库,这样方便我们进行排除,如下:
1 2 3 4 5 6 7 8 9
| define([ "jquery", "underscore", "backbone", ... "text" ], function() {});
|
然后我们的config.js
变成了这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| { mainConfigFile : "../js/main.js", baseUrl: "../js", removeCombined: true, findNestedDependencies: true, dir: "../dist/js", modules: [ { name: "main", exclude: [ "libs" ] }, { name: "libs" } ] }
|
现在,我们的build
操作终于完美了。
但是,如果我们的js直接通过cdn引用的呢?如果我们直接运行上面的压缩配置,r.js
将会报错。因此,对于从cdn引入的js,我们作如下配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| requirejs.config({ paths: { jquery: ['http://cdn.staticfile.org/jquery/1.11.1/jquery.min.js', 'lib/jquery/jquery-1.11.1.min'], underscore: 'lib/underscore/underscore-min', ... text: 'lib/requirejs/plugins/text', echarts:'lib/echarts/echarts', 'echarts/chart/bar' : 'lib/echarts/echarts', config: 'modules/common/config' } });
{ mainConfigFile : "../js/main.js", baseUrl: "../js", removeCombined: true, findNestedDependencies: true, dir: "../dist/js", modules: [ { name: "main", exclude: [ "libs" ] }, { name: "libs" } ], paths: { jquery: "empty:" } }
|
我们再次运行合并的操作node r.js -o config.js
会发现此时r.js
没有把jquery
合并进来,因为它是通过cdn加载的。
css的压缩合并配置
虽然我的项目中没有用到,但在这里还是说一下吧。
项目中可能引用了多个css文件,如:
1 2
| <link rel="stylesheet" type="text/css" href="css/bootstrap.css"> <link rel="stylesheet" type="text/css" href="css/style.css">
|
如果我们只想引用一个css文件,我们可以这样:
1 2
| @import url('/css/bootstrap.css');
|
然后在压缩合并的时候进行配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| { mainConfigFile : "../js/main.js", appDir: "../", baseUrl: "js", removeCombined: true, findNestedDependencies: true, dir: "../dist", optimizeCss: "standard", modules: [ { name: "main", exclude: [ "libs" ] }, { name: "libs" } ], paths: { jquery: "empty:" }, fileExclusionRegExp: /(^\.|build|dist|sass|config.rb)/, generateSourceMaps: true }
|
appDir
:项目根目录
optimizeCss
:css压缩规则,有四种,分别是:none
、standard
、standard.keeplines
、standard.keepComments
、standard.keepComments.keeplines
。具体意思我就不一一解释了。
generateSourceMaps
:生成map文件,把压缩过的js与未压缩的作映射