RequireJS 优化器
- 要求§ 1
- 下载§ 2
- 示例设置§ 3
- 基础知识§ 4
- 优化一个 JavaScript 文件§ 5
- 用于快速开发的浅层排除§ 6
- empty: 用于网络/CDN 资源的路径§ 7
- 优化一个 CSS 文件§ 8
- 优化整个项目§ 9
- 优化多页面项目§ 10
- Turbo 选项§ 11
- 与 has.js 集成§ 12
- 源代码地图§ 13
- 所有配置选项§ 14
- 部署技术§ 15
- 常见陷阱§ 16
RequireJS 有一个优化工具,可以执行以下操作
- 将相关的脚本合并到构建层中,并通过 UglifyJS(默认)或 Closure Compiler(使用 Java 时的选项)对其进行压缩。
- 通过内联 @import 引用的 CSS 文件和删除注释来优化 CSS。
优化器是 适用于 Node 和 Nashorn 的 r.js 适配器的一部分,它被设计为在完成开发并准备为用户部署代码后,作为构建或打包步骤的一部分运行。
优化器只会合并那些在传递给顶级 require 和 define 调用或 简化的 CommonJS 包装中的 require('name') 字符串字面量调用的字符串字面量数组中指定的模块。因此,它不会找到通过变量名加载的模块
var mods = someCondition ? ['a', 'b'] : ['c', 'd'];
require(mods);
但如果像这样指定,'a' 和 'b' 将会被包含
require(['a', 'b']);
或者
define(['a', 'b'], function (a, b) {});
这种行为允许在优化后动态加载模块。您始终可以使用 **include** 选项显式添加未通过优化器的静态分析找到的模块。
要求 § 1
可以使用 Node、带有 Rhino 或 Nashorn 的 Java 或在浏览器中运行优化器。每个选项的要求
- **Node:**(首选)Node 0.4.0 或更高版本。
- **Java:**Java 1.6 或更高版本。
- **浏览器:**从 2.1.2 版本开始,优化器可以在具有 数组扩展的 Web 浏览器中运行。虽然优化器选项与下面显示的相同,但它是通过 JavaScript 而不是命令行选项调用的。它也只适用于生成优化的单个文件,而不适用于目录优化。请参阅浏览器示例。此选项实际上仅适用于提供基于 Web 的库自定义构建。
对于命令行使用,Node 是首选的执行环境。优化器在 Node 中运行**速度更快**。
此页面中的所有示例命令都假定使用 Node,并在 Linux/OS X 命令行上运行。有关如何在 Java 中运行它的信息,请参阅r.js 自述文件。
下载§ 2
1) 您可以在下载页面上下载该工具。
2) 如果您将 Node 与 NPM 一起使用,则可以将 r.js 作为 NPM 中“requirejs”包的一部分全局安装
> npm install -g requirejs
> r.js -o app.build.js
如果在 Windows 上,您可能需要键入 r.js.cmd
而不是 r.js
。或者,您可以使用DOSKEY
DOSKEY r.js=r.js.cmd $*
如果您想将 requirejs 作为 npm 包本地安装在项目中,而不是全局安装
> npm install requirejs
通过此本地安装,您可以通过运行项目 node_modules/.bin
目录中的 r.js
或 r.js.cmd
文件来运行优化器。
通过本地安装,您还可以通过 node 程序中的函数调用来使用优化器。
本页面的其余部分假设 r.js 只是从下载页面手动下载的。这通常是使用优化器的最清晰、最便携的方式。
示例设置§ 3
本页面中的示例假设您已将 r.js 下载并保存到与项目目录同级的目录中。作为 r.js 一部分的优化器可以位于您想要的任何位置,但您可能需要在这些示例中相应地调整路径。
示例设置
- 应用程序目录
- main.html
- css
- common.css
- main.css
- scripts
- require.js
- main.js
- one.js
- two.js
- three.js
- r.js(来自下载页面的 r.js 优化器)
main.html 具有 require.js 的脚本标签,并通过 require 调用加载 main.js,如下所示
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
<link rel="stylesheet" type="text/css" href="css/main.css">
<script data-main="scripts/main" src="scripts/require.js"></script>
</head>
<body>
<h1>My App</h1>
</body>
</html>
main.js 通过 require 调用加载 one.js、two.js 和 three.js
require(["one", "two", "three"], function (one, two, three) {
});
main.css 具有如下内容
@import url("common.css");
.app {
background: transparent url(../../img/app.png);
}
基础知识 § 4
命令行参数可以与构建配置文件属性互换
您可以在命令行上指定选项
node r.js -o baseUrl=. paths.jquery=some/other/jquery name=main out=main-built.js
或在构建配置文件中。在 **build.js** 中,可以像这样指定相同的命令行参数
({
baseUrl: ".",
paths: {
jquery: "some/other/jquery"
},
name: "main",
out: "main-built.js"
})
然后只需将构建配置文件的文件名传递给优化器
node r.js -o build.js
命令行参数优先于构建配置文件设置,您可以将它们混合在一起
node r.js -o build.js optimize=none
命令行参数语法有**限制**。点被视为对象属性分隔符,以允许将 paths.jquery=lib/jquery
之类的内容转换为优化器中的以下内容
paths: {
jquery: 'lib/jquery'
}
但这意味着您无法将“core/jquery.tabs”的路径属性的值设置为某个值。这将不起作用:paths.core/jquery.tabs=empty:
,因为它会导致以下错误结构
paths: {
'core/jquery': {
tabs: 'empty:'
}
}
如果需要设置像“core/jquery.tabs”这样的路径,请使用 build.js 文件,其中构建选项指定为 JavaScript 对象,而不是使用命令行参数。
有关所有选项的列表,请参阅所有配置选项。
相对路径解析规则:
通常,如果它是路径,则它相对于用于保存构建选项的 build.js 文件,或者如果仅使用命令行参数,则相对于当前工作目录。是文件路径的属性示例:**appDir**、**dir**、**mainConfigFile**、**out**、**wrap.startFile**、**wrap.endFile**。
对于 **baseUrl**,它相对于 **appDir**。如果没有 appDir,则 baseUrl 相对于 build.js 文件,或者如果仅使用命令行参数,则相对于当前工作目录。
对于 **paths** 和 **packages**,它们相对于 **baseUrl**,就像它们对于 require.js 一样。
对于作为模块 ID 的属性,它们应该是模块 ID,而不是文件路径。示例包括 **name**、**include**、**exclude**、**excludeShallow**、**deps**。
默认情况下,优化器**不会读取**在运行时加载到浏览器中的主 JS 模块中的配置设置
这是因为构建的配置设置可能会有很大差异,并且具有多个优化目标。因此,需要为优化器指定一组单独的配置选项。
在 1.0.5+ 版本的优化器中,可以使用 **mainConfigFile** 选项来指定运行时配置的位置。如果使用主 JS 文件的路径指定,则将在该文件中找到的第一个 requirejs({}), requirejs.config({}), require({}), or require.config({})
被解析出来,并用作传递给优化器的配置选项的一部分
mainConfigFile: 'path/to/main.js'
配置的优先级:命令行、构建配置文件、mainConfigFile。换句话说,mainConfigFile 配置的优先级最低。
优化一个 JavaScript 文件 § 5
使用上面的示例设置,如果您只想优化 main.js,则可以使用此命令,从 **appdirectory/scripts** 目录中
node ../../r.js -o name=main out=main-built.js baseUrl=.
这将创建一个名为 **appdirectory/scripts/main-built.js** 的文件,其中将包含 main.js、one.js、two.js 和 three.js 的内容。
通常,您**不应**使用原始项目源代码保存优化后的文件。通常,您会将它们保存到项目的副本中,但为了使此示例更容易,它与源代码一起保存。将 **out=** 选项更改为您喜欢的任何目录,该目录包含源代码的副本。然后,您可以将 main-built.js 文件名更改为 main.js,以便 HTML 页面将加载文件的优化版本。
如果要将 require.js 与 main.js 源代码一起包含,则可以使用以下命令
node ../../r.js -o baseUrl=. paths.requireLib=../../require name=main include=requireLib out=main-built.js
由于“require”是保留的依赖项名称,因此您创建了一个“requireLib”依赖项并将其映射到 require.js 文件。
完成优化后,您可以将脚本标签更改为引用“main-built.js”而不是“require.js”,并且您的优化项目只需要发出一个脚本请求。
如果要包装构建的文件,以便可以在没有 AMD 加载器(如 RequireJS)的页面中使用它,请参阅优化常见问题解答。
用于快速开发的浅层排除§ 6
您可以使用单个 JavaScript 文件优化方法来加快您的开发体验。通过将项目中的所有模块(除了您当前正在开发的模块)优化到一个文件中,您可以在浏览器中快速重新加载项目,但仍然可以选择在模块中进行细粒度调试。
您可以使用 excludeShallow 选项来做到这一点。使用上面的示例设置,假设您当前正在构建或调试 two.js。您可以使用以下优化命令
node ../../r.js -o name=main excludeShallow=two out=main-built.js baseUrl=.
如果您不希望对 main-build.js 文件进行压缩,请在上述命令中传递 optimize=none。
然后通过将“main”的路径配置为“main-built”,将 HTML 页面配置为加载 main-built.js 文件而不是 main.js
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
<link rel="stylesheet" type="text/css" href="css/main.css">
<script src="scripts/require.js"></script>
<script>
require.config({
paths: {
//Comment out this line to go back to loading
//the non-optimized main.js source file.
"main": "main-built"
}
});
require(["main"]);
</script>
</head>
<body>
<h1>My App</h1>
</body>
</html>
现在,当加载此页面时,对“main”的 require() 将加载 main-built.js 文件。由于 excludeShallow 告诉它只排除 two.js,因此 two.js 仍将作为单独的文件加载,允许您在浏览器的调试器中将其视为单独的文件,以便您可以设置断点并更好地跟踪其个别更改。
empty:网络/CDN 资源的路径§ 7
您可能有一个脚本想要从内容交付网络 (CDN)或不同域上的任何其他服务器加载。
优化器无法加载网络资源,因此如果您希望将其包含在构建中,请确保创建一个路径配置以将文件映射到模块名称。然后,为了运行优化器,请下载 CDN 脚本并将路径配置传递给优化器,该配置将模块名称映射到本地文件路径。
但是,您更有可能不希望在构建中包含该资源。如果脚本没有任何依赖项,或者您不想包含其依赖项或将以其他方式包含它们,则可以使用路径配置中的特殊 'empty:' 方案 在优化时跳过该文件。
在您的 main.js 文件中,创建一个路径配置,为脚本指定一个模块名称。即使脚本没有通过调用 define() 来定义模块,也可以这样做。路径配置仅用于将短模块/脚本 ID 映射到 URL。这允许您为优化使用不同的路径配置。在 main.js 中
requirejs.config({
paths: {
'jquery': 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min'
}
});
require(['jquery'], function ($) {
});
然后,在运行优化器时,对路径配置使用 'empty:'
node ../../r.js -o name=main out=main-built.js baseUrl=. paths.jquery=empty:
或者,在构建配置文件中
({
baseUrl: ".",
name: "main",
out: "main-built.js",
paths: {
jquery: "empty:"
}
})
优化一个 CSS 文件§ 8
使用上面的示例设置,如果您只想优化 main.css,则可以使用此命令,从 appdirectory/css 目录中
node ../../r.js -o cssIn=main.css out=main-built.css
这将创建一个名为 appdirectory/css/main-build.css 的文件,该文件将包含 main.css 的内容,正确调整 url() 路径,并删除注释。
有关避免在原始源代码树中保存优化文件的更多信息,请参阅优化一个 JavaScript 文件的注释。这里这样做只是为了使示例更简单。
注意:url() 路径修复将始终修复相对于 cssIn 构建选项路径的路径,而不是 out 构建选项。优化整个项目§ 9
优化器可以通过使用构建配置文件来优化项目中的所有 CSS 和 JS 文件。
创建一个构建配置文件,将其命名为 app.build.js,并将其放在 scripts 目录中。app.build.js 文件可以放在任何位置,但请确保在下面的示例中相应地调整路径 - 所有路径都将相对于 app.build.js 所在的位置。示例 app.build.js
({
appDir: "../",
baseUrl: "scripts",
dir: "../../appdirectory-build",
modules: [
{
name: "main"
}
]
})
此构建配置文件告诉 RequireJS 将 appdirectory 的所有内容复制到名为 appdirectory-build 的同级目录,并在 appdirectory-build 目录中应用所有优化。强烈建议您使用与源目录不同的输出目录 - 否则,当优化器覆盖您的源代码时,可能会发生不好的事情。
RequireJS 将使用 baseUrl 来解析任何模块名称的路径。baseUrl 应该是相对于 appDir 的。
在 modules 数组中,指定要优化的模块名称,在本例中为“main”。“main”将映射到您项目中的 appdirectory/scripts/main.js。然后,构建系统将跟踪 main.js 的依赖项,并将它们注入到 appdirectory-build/scripts/main.js 文件中。
它还将优化它在 appdirectory-build 中找到的任何 CSS 文件。
要运行构建,请从 appdirectory/scripts 目录中运行以下命令
node ../../r.js -o app.build.js
构建完成后,您可以使用 appdirectory-build 作为您的优化项目,准备部署。
优化多页项目§ 10
requirejs/example-multipage 是一个多页项目示例,但共享一个通用配置和一个通用优化构建层。
Turbo 选项§ 11
优化器的默认设置是执行最安全、最健壮的操作集,以避免构建后出现意外。但是,根据您的项目设置,您可能希望关闭其中一些功能以加快构建速度
- 最大的时间消耗是压缩。如果您只是将构建作为开发工作流程的一部分,请将 optimize 设置为
"none"
。 - 如果正在进行整个项目优化,但只想压缩 modules 选项中指定的构建层,而不是构建输出目录中的其余 JS 文件,则可以将 skipDirOptimize 设置为
true
。 - 通常,每次运行整个项目优化都会删除 dir 指定的输出构建目录以保持清洁。某些构建选项(如 onBuildWrite)将以对相同文件执行两次操作很危险的方式修改输出目录。但是,如果您正在执行没有除构建层压缩之外的额外文件转换的简单构建,则可以将 keepBuildDir 设置为
true
以在运行之间保留构建目录。然后,只会复制在构建运行之间已更改的文件。
从版本 2.1.2 开始,如果 optimize 设置为 "none"
,优化器将默认采用一些速度捷径。但是,如果您对 optimize 使用 "none"
并且您计划在优化器运行后压缩构建文件,则应将 normalizeDirDefines 设置为 "all"
,以便正确规范化 define() 调用以承受压缩。如果您正在通过 optimize 选项进行压缩,则无需担心设置此选项。
与 has.js 集成§ 12
has.js 是一个很棒的工具,可以为您的项目添加简单的功能检测。优化器对优化 has.js 测试的代码路径有一些支持。
如果您的代码使用如下测试
if (has("someThing")) {
//use native someThing
} else {
//do some workaround
}
您可以在构建配置中定义一个 has 对象,其中包含一些 has() 测试的 true 或 false 值,优化器会将 has() 测试替换为 true 或 false 值。
如果您的构建配置文件如下所示
({
baseUrl: ".",
name: "hasTestModule",
out: "builds/hasTestModule.js",
has: {
someThing: true
}
})
然后优化器会将上面的代码示例转换为
if (true) {
//use native someThing
} else {
//do some workaround
}
然后,如果您在 r.js 0.26.0 或更高版本中使用默认的“uglify”优化设置,或者 optimize 设置为“closure”(在Java 下运行时),压缩器将优化掉死代码分支!因此,您可以对代码进行自定义构建,针对一组 has() 测试进行优化。
源映射§ 13
版本 2.1.6 及更高版本对源映射提供实验性支持。它适用于将压缩的捆绑代码映射到未压缩的单独模块,并且仅当 optimize 设置为 "uglify2"
时才有效。optimize 设置为 "closure"
仅允许将压缩的捆绑代码映射到未压缩的捆绑代码(closure 仅在使用 Rhino 在 Java 下运行时可用)。未压缩的文件将在开发工具中显示为“.src.js”文件扩展名。
要启用源映射生成,请将 generateSourceMaps 设置为 true
。由于压缩器需要完全控制压缩文件以生成源映射,因此应将 preserveLicenseComments 显式设置为 false
。有一种方法可以在压缩源中获取一些许可证注释。
优化器支持sourceURL(通过将 useSourceUrl 设置为 true
),用于将组合模块作为单个文件进行调试。但是,这仅适用于未压缩的代码。源映射将压缩文件转换为未压缩版本。将 useSourceUrl 与 generateSourceMaps 一起使用是没有意义的,因为 useSourceUrl 需要将源值作为字符串,这会阻止与 generateSourceMaps 结合使用的有用压缩。
所有配置选项§ 14
requirejs/build 目录中有一个example.build.js文件,其中详细说明了所有允许的优化器配置选项。
常见陷阱§ 16
如果您在使用以下示例时遇到问题,以下是一些可能导致问题的常见陷阱
不要为 JavaScript 指定源区域内的输出目录
例如,如果您的 baseUrl 是“js”并且您的构建输出进入“js/build”,则每次优化运行时可能会出现生成额外嵌套文件的问题。此指南仅适用于非单文件优化的优化。
避免使用 baseUrl 之外的优化名称
例如,如果您的 baseUrl 是“js”,并且您的优化目标是
name: '../main'
优化可能会覆盖输出目录之外的文件或将文件放置在输出目录之外。对于这些情况,请创建一个 paths 配置以将该文件映射到本地名称,例如
paths: {
main: '../main'
}
然后使用名称
name: 'main'
作为优化目标。
注意 shim 配置的构建限制。 特别是,您不能从 CDN 加载 shimmed 库的依赖项。有关更多信息,请参阅shim 配置部分。