关于RequireJS已经有不少文章介绍过了。这个工具能够将你的JavaScript代码轻易的分割成苦干个模块(module)而且保持你的代码模块化与易维护性。这样,你将得到一些具备互相依赖关系的JavaScript文件。仅仅须要在你的HTML文档中引用一个基于RequireJS的脚本文件,全部必须的文件都将会被自动引用到这个页面上.javascript
可是,在生产环境中将全部的JavaScript文件分离,这是一个很差的作法。这会致使不少次请求(requests),即便这个些文件都很小,也会浪费不少时间。 能够经过合并这些脚本文件,以减小请求的次数达到节省加载时间的目的。
另外一种节省加载时间的技巧是缩小这些被加载文件的大小,相对小一些的文件会传输的更快一些。这个过程叫做最小化 (minification) ,它是经过当心的改变脚本文件的代码结构而且不改变代码的形为(behavior)和功能(functionality)来实现的。例如这些:去除没必要要的空格,缩短(mangling,或都压缩)变量(variables)名与函数(methods,或者叫方法)名,等等。这种合并并压缩文件的过程叫作代码优化( optimization)。这种方法除了用于优化(optimization)JavaScript文件,一样适用于CSS文件的优化。css
RequireJS有两个主要方法(method): define()和require()。这两个方法基本上拥有相同的定义(declaration) 而且它们都知道如何加载的依赖关系,而后执行一个回调函数(callback function)。与require()不一样的是, define()用来存储代码做为一个已命名的模块。 所以define()的回调函数须要有一个返回值做为这个模块定义。这些相似被定义的模块叫做AMD (Asynchronous Module Definition,异步模块定义)。html
下面经过一个示例讲解如何优化RequireJS项目。(这段话来自下面的参考链接)java
Node.js、r.js、RequireJS、以及示例程序,示例程序的下载地址为:http://www.webdeveasy.com/code/optimize-requirejs-projects/todo-mvc.zipnode
涉及的操做请能够参考上面的示例,本文的主要目的主要是经过示例来说解配置参数的使用。git
appDir: './'
应用程序的顶级目录,若是这个选项被开启的话,那么你的脚本文件是这个目录路径下的一个子目录。这个是个可选项。若是没有设置的话,则经过baseUrl这个参数下的锚点来查找文件(?)。若是设置了该选项的话,那么这个路径下的全部文件都会被复制到dir指定的输出目录,而且baseUrl这个目录的路径是相对于该路径。github
baseUrl: './js'
默认状况下,因此的模块都相对于这个路径存在(有人称为脚本的跟路径),若是baseUrl没有明确指定的话,那么全部的模块路径都相对与build构建文件的路径。若是appDir已设置,那么baseUrl 的路径是相对与appDir。web
mainConfigFile: '../some/path/to/main.js'
RequireJS的主配置文件。这里要区分配置文件和入口文件的区别,示例中的main.js即包含配置文件同时又是文件的入口文件。segmentfault
paths: { "foo.bar": "../scripts/foo/bar", "baz": "../another/path/baz" },
参见: RequireJS进阶:配置文件的学习跨域
map: {},
packages: [],
dir: "../some/path"
文件输出的顶级目录。若是没有指定的话,默认会建立一个“build”目录在build文件的路径中。全部相对路径是相对于构建文件。
keepBuildDir: true
在 RequireJS 2.0.2 中,输出目录的全部资源会在 build 前被删除。值为 true 时 rebuild 更快,但某些特殊情景下可能会出现没法预料的异常
shim: {},
wrapShim: false,
禁止非模块包裹define函数。
locale: "en-us",
国际化配置设置。
optimize: "uglify",
优化脚本文件的方式。值只能取下面的任何值中的一个。
"uglify": (default) uses UglifyJS to minify the code.
"uglify2": in version 2.1.2+. Uses UglifyJS2.
"closure": uses Google's Closure Compiler in simple optimizationmode to minify the code. Only available if running the optimizer using Java.
"closure.keepLines": Same as closure option, but keeps line returns in the minified files.
"none": no minification will be done.
skipDirOptimize: false,
当设置为true时,优化器将会跳过非构建中被约束的JS文件。
generateSourceMaps: false,
是否生成SourceMaps文件,什么是SourceMaps,参考SourceMaps
normalizeDirDefines: "skip",
2.1.11中:若是dir被声明且不为”none”,而且skipDirOptimize 为false,一般全部的JS文件都会被压缩,这个值自动设置为”all”。为了让JS文件可以在压缩过正确执行,优化器会加一层define()调用而且会插入一个依赖数组。固然,这样会有一点点慢若是有不少文件或者有大文件的时候。因此,设置该参数为”skip”这个过程就不会执行,若是optimize设置为”none”也同样。若是你想手动设置值的话:
优化后:若是你打算压缩没在modules声明的JS文件,在优化器执行事后,你应该设置这个值为”all”
优化中:但在动态加载事后,你想作一个会文件优化,但不打算在动态加载这些文件能够设置成”skip”
最后:全部生成的文件(不管在不在modules里声明过)自动标准化
uglify: { toplevel: true, ascii_only: true, beautify: true, max_line_length: 1000, //How to pass uglifyjs defined symbols for AST symbol replacement, //see "defines" options for ast_mangle in the uglifys docs. defines: { DEBUG: ['name', 'false'] }, //Custom value supported by r.js but done differently //in uglifyjs directly: //Skip the processor.ast_mangle() part of the uglify call (r.js 2.0.5+) no_mangle: true },
使用UglifyJS进行代码压缩,具体参数配置可见UglifyJS
uglify2: { //Example of a specialized config. If you are fine //with the default options, no need to specify //any of these properties. output: { beautify: true }, compress: { sequences: false, global_defs: { DEBUG: false } }, warnings: true, mangle: false },
使用UglifyJS2进行代码压缩, 具体参数配置可见UglifyJS2
closure: { CompilerOptions: {}, CompilationLevel: 'SIMPLE_OPTIMIZATIONS', loggingLevel: 'WARNING' },
若是用Closure Compiler优化,这个参数能够用来配置Closure Compiler,详细请看Closure Compiler的文档
optimizeCss: "standard.keepLines.keepWhitespace",
是否优化CSS文件,以那种方式优化。
cssImportIgnore: null,
是否忽略 CSS 资源文件中的 @import 指令
cssIn: "path/to/main.css",
通常用于命令行,可将多个 CSS 资源文件打包成单个 CSS 文件
out: "path/to/css-optimized.css",
通常用于命令行,可将多个 CSS 资源文件打包成单个 CSS 文件
cssPrefix: "",
若是”out”和”cssIn”不是同一目录,而且在cssIn文件里面有url()相对目录的,用这个去设置URL前置。仅仅在优化后URL不正确的状况下使用。
inlineText: true,
处理全部的文本资源依赖项,从而避免为加载资源而产生的大量单独xhr请求
useStrict: false,
是否开启严格模式, 因为不少浏览器不支持 ES5 的严格模式,故此配置默认值为 false
pragmas: { fooExclude: true },
指定生成编译指示。若是源文件包含相似以下注释:>>excludeStart(“fooExlude”,pragmas.fooExclude); >>excludeEnd(“fooExclude”);那么以//>>开头的注释就是编译指示。excludeStart/excludeEnd和includeStart/includeEnd起做用,在includeStart或excludeStart中的编译指示值将参与计算来判断Start和End以前的编译指示是include仍是exclude。若是你能够选择用”has”或编译指示,建议用”has”代替。 编译指示比较难于阅读,可是它在对代码移除上比较灵活。基于”has”的代码必须遵照JavaScript规则。编译指示还能够在未压缩的代码中删除代码,而”has”只能经过UglifyJS或者Closure Compiler来作。
pragmasOnSave: { //Just an example excludeCoffeeScript: true },
和”pragmas”同样,但只能在文件保存的优化阶段应用一次。”pragmas”能够同时在依赖映射和文件保存优化阶段应用。有些”pragmas”可能不会在依赖映射时被执行,例如在CoffeeScript的loader插件中,只想CoffeeScript作依赖映射,可是一旦这个文件被保存为一个javascript文件,CoffeeScript compiler就没用了。那样的话,pragmasOnSave就会用于在保存期排除编译代码。
has: { 'function-bind': true, 'string-trim': false },
使用”has”容许trimming代码树。基于js的特征检测:https://github.com/phiggins42/has.js。代码树修饰仅仅在使用UglifyJS或Closure Compiler压缩时发生。更多请见:http://requirejs.org/docs/optimization.html#hasjs
hasOnSave: { 'function-bind': true, 'string-trim': false },
和pragmasOnSave相似。
namespace: 'foo',
命名空间,完整实例能够参考 http://requirejs.org/docs/faq-advanced.html#rename
skipPragmas: false,
跳过执行pragmas
skipModuleInsertion: false,
若是是false,文件就不会用define()来定义模块而是用一个define()占位符插入其中。另外,require.pause/resume调用也会被插入。设置为”true”来避免。这个参数用在你不是用require()来建立项目或者写js文件,可是又想使用RquireJS的优化工具来合并模块是很是有用的。
stubModules: ['text', 'bar'],
将模块排除在优化文件以外。
optimizeAllPluginResources: false,
若是不是一个文件的优化,描述输出目录的全部.js文件的插件依赖,若是这个插件支持优化成为一个单独的文件,就优化它。多是一个比较慢的优化过程。仅仅在有些插件用了像XMLHttpRequest不支持跨域,而且生成的代码会被放在另外一个域名。
findNestedDependencies: false,
寻找require()里面的require或define调用的依赖。默认为false是由于这些资源应该被认为是动态加载或者实时调用的。固然,有些优化场景也须要将它们合并在一块儿。
removeCombined: false
若是设置为true,在输出目录将会删除掉已经合并了的文件
modules: [ //Just specifying a module name means that module will be converted into //a built file that contains all of its dependencies. If that module or any //of its dependencies includes i18n bundles, they may not be included in the //built file unless the locale: section is set above. { name: "foo/bar/bop", //create: true can be used to create the module layer at the given //name, if it does not already exist in the source location. If //there is a module at the source location with this name, then //create: true is superfluous. create: true, //For build profiles that contain more than one modules entry, //allow overrides for the properties that set for the whole build, //for example a different set of pragmas for this module. //The override's value is an object that can //contain any of the other build options in this file. override: { pragmas: { fooExclude: true } } }, //This module entry combines all the dependencies of foo/bar/bop and foo/bar/bee //and any of their dependencies into one file. { name: "foo/bar/bop", include: ["foo/bar/bee"] }, //This module entry combines all the dependencies of foo/bar/bip into one file, //but excludes foo/bar/bop and its dependencies from the built file. If you want //to exclude a module that is also another module being optimized, it is more //efficient if you define that module optimization entry before using it //in an exclude array. { name: "foo/bar/bip", exclude: [ "foo/bar/bop" ] }, //This module entry shows how to specify a specific module be excluded //from the built module file. excludeShallow means just exclude that //specific module, but if that module has nested dependencies that are //part of the built file, keep them in there. This is useful during //development when you want to have a fast bundled set of modules, but //just develop/debug one or two modules at a time. { name: "foo/bar/bin", excludeShallow: [ "foo/bar/bot" ] }, //This module entry shows the use insertRequire (first available in 2.0): { name: "foo/baz", insertRequire: ["foo/baz"] } ],
列出要优化的模块。若是有依赖i18n的,只有root层会被包含进来除非locale:块在上面被声明过。
①仅定义模块会被转换成一个生成目标文件的名字,包含全部依赖项。i18n依赖同上,
create:true可用来生成在源文件目录不存在的给定模块名。若是源文件目录已经存在一个相同名称的模块,create参数就没用了;
override:能够重写全局的pragmas
②这个模块声明编译foo/bar/bop的全部依赖和foo/bar/bee及其全部依赖
③编译全部foo/bar/bip的依赖到一个文件,可是排除foo/bar/bop和它的全部依赖文件,若是想把另外一个模块单独优化,这是一个很好用的方法
④excludeShallow只排除掉这个模块,可是若是输出模块的依赖和它有相同就保留不排除。
⑤这个模块声明表示用insertRequire(在2.0中新加入)
insertRequire: ['foo/bar/bop'],
若是目标模块在顶层级只调用了define没有调用require(),而且输出文件在data-main中使用,若是顶层没有require,就不会有任何模块被加载。定义insertRequire在文件尾部来执行其它模块,更多参见:https://github.com/jrburke/almond
name: "foo/bar/bop",
include: ["foo/bar/bee"],
insertRequire: ['foo/bar/bop'],
out: "path/to/optimized-file.js",
若是只优化一个模块(和它的依赖项),并且是生成一个单文件,你能够在行内定义模块的选项,以代替modules参数的定义方式,”exclude”, “excludeShallow”, “include”和”insertRquire”均可以以兄弟属性的方式定义。
deps: ["foo/bar/bee"],
“include”的替换方案。通常用requirejs.config()来定义并用mainConfigFile引入。
out: function (text, sourceMapText) { //Do what you want with the optimized text here. //Starting in 2.1.10, if generateSourceMaps was set to true //and optimize: 'uglify2' was used, then the second argument //to this function, sourceMapText, will be the text of the source map. },
在2.0,”out”能够是一个函数, 对单个JS文件优化能够调用requirejs.optimize(), 用out函数表示优化事后的内容不会被写到磁盘,而是传递给out函数
out: “stdout”
在2.0.12+, 设置”out”为”stdout”, 优化输出会写到STDOUT,这对于r.js整合其它命令行工具颇有用。为了不额外的输出”logLevel: 4”应该被使用。
wrap: { start: "(function() {", end: "}());" },
wrap任何东西在start和end之间,用于define/require不是全局的状况下,在end里能够暴露全局对象在文件中。
wrap: true,
wrap的另外一种方式,默认是(function() { + content + }())
wrap: { startFile: "parts/start.frag", endFile: "parts/end.frag" },
用文件来wrap
wrap: { startFile: ["parts/startOne.frag", "parts/startTwo.frag"], endFile: ["parts/endOne.frag", "parts/endTwo.frag"] },
多个文件的wrap
fileExclusionRegExp: /^./,
跳过任何以.开头的目录和文件,好比.files, .htaccess等
preserveLicenseComments: true,
默认注释有受权在里面。固然,在大项目生成时,文件比较多,注释也比较多,这样能够把全部注释写在文件的顶部。
logLevel: 0
设置logLevel。
TRACE: 0,
INFO: 1
WARN: 2
ERROR: 3
SILENT: 4
throwWhen: { optimize: true }
在2.1.3,有些状况下当错误发生时不会抛出异常并中止优化,你可能想让优化器在某些错误发生时中止,就可使用这个参数
onBuildRead: function (moduleName, path, contents) { //Always return a value. //This is just a contrived example. return contents.replace(/foo/g, 'bar'); },
当每一个文件被读取的时候调用这个方法来改变文件内容
onBuildWrite: function (moduleName, path, contents) { //Always return a value. //This is just a contrived example. return contents.replace(/bar/g, 'foo'); },
容许在写入目标文件前执行方法改变内容
onModuleBundleComplete: function (data) { /* data.name: the bundle name. data.path: the bundle path relative to the output directory. data.included: an array of items included in the build bundle. If a file path, it is relative to the output directory. Loader plugin IDs are also included in this array, but depending on the plugin, may or may not have something inlined in the module bundle. */ },
每一个JS模块集完成后执行。 模块集是指一个modules数组项。
rawText: { 'some/id': 'define(["another/id"], function () {});' },
在2.1.3,种子raw text是模块ID的列表。这些文本内容用于代替模块的文件IO调用。用于模块ID是基于用户动态输入的状况,在网页生成工具中经常使用。
cjsTranslate: true,
在2.0.2中。若是为true, 优化器会添加define(require, exports, module) {});包裹每个没有调用define()的文件。
useSourceUrl: true,
在2.0.2,有点实验性质。每个模块集最后都会添加一段//# sourceUrl的注释。
waitSeconds: 7
skipSemiColonInsertion: false
在2.1.9,一般r.js插入一个分号在文件末尾,若是没有的话。
keepAmdefine: false
在2.1.10, 若是是true,就不会删除amdefine,详情见:https://github.com/jrburke/amdefine
allowSourceOverwrites: false
在2.1.11中, 做为修复BUG的一部分https://github.com/jrburke/r.js/issues/444。设置为true就容许源代码进行重写覆盖。固然,为了安全起见,请正确配置,好比你可能想设置”keepBuildDir”为true。
参考连接:http://jiongks.sinaapp.com/blog/build-any-web-project-with-requirejs-optimizer/
英文文档(r.js):https://github.com/jrburke/r.js/blob/master/build/example.build.js
参考连接:http://www.oschina.net/translate/optimize-requirejs-projects
参考连接:http://www.cnblogs.com/haoliang/p/3656475.html
参考连接:http://www.yfznw.com/node/22
PS:若是涉及侵权或者文章有错误,请及时通知。