RequireJS 优化器

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开始,优化器可以在具有extras数组的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 $*

如果要以npm软件包的形式在项目中本地安装requirejs,而不是全局安装:

> npm install requirejs

使用此本地安装,您可以通过运行项目目录中的r.js或r.js.cmd文件来运行优化器node_modules/.bin。

在本地安装中,您还可以通过Node程序内部的函数调用来使用优化器。

该页面的其余部分假定r.js只是从下载页面手动下载的。通常,这是使用优化器的最清晰,最便捷的方法。

设置示例§ 3

此页面中的示例将假定您已将r.js下载并保存在项目目录的同级目录中。作为r.js一部分的优化器可以放在您想要的任何位置,但是在这些示例中,您可能需要相应地调整路径。

设置示例:

  • appdirectory
    • 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属性的值设置为一个值。这将不起作用:paths.core/jquery.tabs=empty:,因为它会导致此错误的结构:

paths: {
    'core/jquery': {
        tabs: 'empty:'
    }
}

如果您需要设置类似"core/jquery.tabs"的路径,请使用带有指定为JavaScript对象的构建选项的build.js文件,而不要使用命令行参数。

有关所有选项的列表,请参阅所有配置选项。

相对路径解析规则::

通常,如果它是路径,则相对于用于保存构建选项的build.js文件,或者仅相对于当前工作目录而言,如果仅使用命令行参数。文件路径属性的示例:appDir,dir,mainConfigFile,out,wrap.startFile,wrap.endFile。

对于的baseUrl,它是相对于APPDIR。如果没有appDir,则baseUrl相对于build.js文件,或者如果仅使用命令行参数,则相对于当前工作目录。

对于路径和包,它们是相对的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'

config的优先级:命令行,构建配置文件,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页面将加载文件的优化版本。

如果要在main.js源代码中包含require.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仍将作为独立文件加载,使您可以在浏览器的调试器中将其视为独立文件,因此可以设置断点并更好地跟踪其各个更改。

空:网络/ CDN资源的路径§ 7

您可能具有要从Content Delivery Network(CDN)或其他域上的任何其他服务器加载的脚本。

优化器无法加载网络资源,因此,如果您希望将其包含在构建中,请确保创建路径配置以将文件映射到模块名称。然后,要运行优化器,请下载CDN脚本,然后将路径配置传递给优化器,以将模块名称映射到本地文件路径。

但是,您很可能不想在构建中包括该资源。如果脚本没有任何依赖关系,或者您不想包含其依赖关系或将以其他方式包含它们,则可以在paths配置中使用特殊的"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,并将其放在脚本目录中。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。

在模块数组中,指定要优化的模块名称,例如"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"。
  • 如果要进行整个项目的优化,而只希望最小化模块选项中指定的构建层,而不是最小化构建输出目录中的其余JS文件,则可以将skipDirOptimize设置为true。
  • 通常,整个项目优化的每次运行都会删除dir指定的输出构建目录,以保持整洁。某些构建选项(如onBuildWrite)将以危险的方式修改输出目录,从而对同一文件执行两次。但是,如果您执行的是简单构建,并且除了最小化构建层之外,没有其他文件转换,则可以将keepBuildDir设置为true在两次运行之间保留构建目录。然后,将仅复制在两次构建运行之间已更改的文件。

从2.1.2版开始,如果将optimize设置为,则优化器默认会采用一些速度快捷方式"none"。但是,如果你正在使用"none"的优化和您所规划的优化运行后,来缩小内置文件,那么你应该把一套normalizeDirDefines以"all"使定义()调用正确归承受微小。如果要通过优化选项进行缩小,则无需担心设置此选项。

集成HAS.JS§ 12

has.js是一个很棒的工具,可以为您的项目添加简单的函数检测。有一些优化器支持可优化has.js测试的代码路径。

如果您的代码使用如下测试:


if (has("someThing")) {
    //用土生土长的东西
} else {
    //做些变通办法
}

您可以在构建配置中为某些has()测试使用true或false值定义has对象,并且优化程序将用true或false值替换has()测试。

如果您的构建配置文件如下所示:


({
    baseUrl: ".",
    name: "hasTestModule",
    out: "builds/hasTestModule.js",
    has: {
        someThing: true
    }
})

然后,优化器会将上面的代码示例转换为:


if (true) {
    //用土生土长的东西
} else {
    //做些变通办法
}

然后,如果您在r.js 0.26.0或更高版本中使用默认的优化设置"uglify",或者如果将优化设置设置为"closure"(在Java下运行),则压缩程序将优化无效代码分支!因此,您可以对代码进行自定义构建,这些构建针对一组has()测试进行了优化。

源地图§ 13

2.1.6版或更高版本具有对源映射的实验性支持。仅在将optimize设置为时,它才能将缩小的捆绑代码映射到未缩小的单独模块"uglify2"。最优化设置为"closure"只允许将缩小的捆绑代码映射到最小的捆绑代码(仅当在具有Rhino的Java下运行时,闭包才可用)。未缩小的文件将以".src.js"文件扩展名显示在开发人员工具中。

要启用源地图生成,请将generateSourceMaps设置为true。由于minifier需要有完全控制权缩小的文件生成源图,preserveLicenseComments应明确设定false。不过,有一种方法可以在缩小的源代码中获得一些许可证注释。

优化器支持sourceURL(通过将useSourceUrl设置为true),用于将组合的模块作为单个文件进行调试。但是,这仅适用于未缩小的代码。源映射将缩小的文件转换为非缩小的版本。将useSourceUrl与generateSourceMaps一起使用是没有意义的,因为useSourceUrl需要将源值作为字符串使用,这禁止了与generateSourceMaps一起进行的有用缩小。

所有配置选项§ 14

requirejs/build目录中有一个example.build.js文件,其中详述了所有允许的优化器配置选项。

部署技术§ 15

r.js优化器旨在通过在其之上添加其他代码来提供一些可用于不同部署方案的原语。有关如何以这种方式使用优化器的想法,请参阅部署技术Wiki页面。

常见陷阱§ 16

如果您在使用以下示例时遇到问题,请注意以下常见问题,这可能是问题的根源:

不要将输出目录指定为JavaScript的源区域内

例如,如果您的baseUrl是'js',而您的构建输出进入了'js/build',则每次优化运行时生成的额外的嵌套文件可能会出现问题。本指南仅适用于不是单文件优化的优化。

避免使用baseUrl之外的优化名称

例如,如果您的baseUrl是'js',并且您的优化目标是:

name: '../main'

优化可能会覆盖文件或将文件放置在输出目录之外。对于这些情况,请创建路径配置以将该文件映射到本地名称,例如:

paths: {
    main: '../main'
}

然后使用名称:

name: 'main'

用于优化目标。

请注意垫片配置的构建限制。特别是,您不能从CDN加载填充程序库的依赖项。有关更多信息,请参见垫片配置部分。