1. 程式人生 > >RequireJS進階-模塊的優化及配置的詳解

RequireJS進階-模塊的優化及配置的詳解

packages blank profile nbu ive 開頭 necessary 下載地址 iter

概述

關於RequireJS已經有很多文章介紹過了。這個工具可以將你的JavaScript代碼輕易的分割成苦幹個模塊(module)並且保持你的代碼模塊化與易維護性。這樣,你將獲得一些具有互相依賴關系的JavaScript文件。僅僅需要在你的HTML文檔中引用一個基於RequireJS的腳本文件,所有必須的文件都將會被自動引用到這個頁面上.

但是,在生產環境中將所有的JavaScript文件分離,這是一個不好的做法。這會導致很多次請求(requests),即使這個些文件都很小,也會浪費很多時間。 可以通過合並這些腳本文件,以減少請求的次數達到節省加載時間的目的。
另一種節省加載時間的技巧是縮小這些被加載文件的大小,相對小一些的文件會傳輸的更快一些。這個過程叫作最小化 (minification) ,它是通過小心的改變腳本文件的代碼結構並且不改變代碼的形為(behavior)和功能(functionality)來實現的。例如這些:去除不必要的空格,縮短(mangling,或都壓縮)變量(variables)名與函數(methods,或者叫方法)名,等等。這種合並並壓縮文件的過程叫做代碼優化( optimization)。這種方法除了用於優化(optimization)JavaScript文件,同樣適用於CSS文件的優化。

RequireJS有兩個主要方法(method): define()和require()。這兩個方法基本上擁有相同的定義(declaration) 並且它們都知道如何加載的依賴關系,然後執行一個回調函數(callback function)。與require()不同的是, define()用來存儲代碼作為一個已命名的模塊。 因此define()的回調函數需要有一個返回值作為這個模塊定義。這些類似被定義的模塊叫作AMD (Asynchronous Module Definition,異步模塊定義)。

下面通過一個示例講解如何優化RequireJS項目。(這段話來自下面的參考連接)

所需環境

Node.js、r.js、RequireJS、以及示例程序,示例程序的下載地址為:http://www.webdeveasy.com/code/optimize-requirejs-projects/todo-mvc.zip

配置參數介紹

涉及的操作請可以參考上面的示例,本文的主要目的主要是通過示例來講解配置參數的使用。

appDir

appDir: ‘./‘

應用程序的頂級目錄,如果這個選項被開啟的話,那麽你的腳本文件是這個目錄路徑下的一個子目錄。這個是個可選項。如果沒有設置的話,則通過baseUrl這個參數下的錨點來查找文件(?)。如果設置了該選項的話,那麽這個路徑下的所有文件都會被復制到dir

指定的輸出目錄,並且baseUrl這個目錄的路徑是相對於該路徑。

baseUrl

baseUrl: ‘./js‘

默認情況下,所以的模塊都相對於這個路徑存在(有人稱為腳本的跟路徑),如果baseUrl沒有明確指定的話,那麽所有的模塊路徑都相對與build構建文件的路徑。如果appDir已設置,那麽baseUrl 的路徑是相對與appDir

mainConfigFile

mainConfigFile: ‘../some/path/to/main.js‘

RequireJS的主配置文件。這裏要區分配置文件和入口文件的區別,示例中的main.js即包含配置文件同時又是文件的入口文件。

paths

  1. paths: {
  2. "foo.bar": "../scripts/foo/bar",
  3. "baz": "../another/path/baz"
  4. },

參見: RequireJS進階:配置文件的學習

map

map: {},

參見: RequireJS進階:配置文件的學習

packages

packages: [],

參見: RequireJS進階:配置文件的學習

dir

dir: "../some/path"

文件輸出的頂級目錄。如果沒有指定的話,默認會創建一個“build”目錄在build文件的路徑中。所有相對路徑是相對於構建文件。

keepBuildDir

keepBuildDir: true

在 RequireJS 2.0.2 中,輸出目錄的所有資源會在 build 前被刪除。值為 true 時 rebuild 更快,但某些特殊情景下可能會出現無法預料的異常

shim

shim: {},

參見: RequireJS進階:配置文件的學習

wrapShim

wrapShim: false,

禁止非模塊包裹define函數。

locale

locale: "en-us",

國際化配置設置。

optimize

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

skipDirOptimize: false,

當設置為true時,優化器將會跳過非構建中被約束的JS文件。

generateSourceMaps

generateSourceMaps: false,

是否生成SourceMaps文件,什麽是SourceMaps,參考SourceMaps

normalizeDirDefines

normalizeDirDefines: "skip",

2.1.11中:如果dir被聲明且不為”none”,並且skipDirOptimize 為false,通常所有的JS文件都會被壓縮,這個值自動設置為”all”。為了讓JS文件能夠在壓縮過正確執行,優化器會加一層define()調用並且會插入一個依賴數組。當然,這樣會有一點點慢如果有很多文件或者有大文件的時候。所以,設置該參數為”skip”這個過程就不會執行,如果optimize設置為”none”也一樣。如果你想手動設置值的話:

  • 優化後:如果你打算壓縮沒在modules聲明的JS文件,在優化器執行過後,你應該設置這個值為”all”

  • 優化中:但在動態加載過後,你想做一個會文件優化,但不打算在動態加載這些文件可以設置成”skip”

最後:所有生成的文件(無論在不在modules裏聲明過)自動標準化

uglify

  1. uglify: {
  2. toplevel: true,
  3. ascii_only: true,
  4. beautify: true,
  5. max_line_length: 1000,
  6. //How to pass uglifyjs defined symbols for AST symbol replacement,
  7. //see "defines" options for ast_mangle in the uglifys docs.
  8. defines: {
  9. DEBUG: [‘name‘, ‘false‘]
  10. },
  11. //Custom value supported by r.js but done differently
  12. //in uglifyjs directly:
  13. //Skip the processor.ast_mangle() part of the uglify call (r.js 2.0.5+)
  14. no_mangle: true
  15. },

使用UglifyJS進行代碼壓縮,具體參數配置可見UglifyJS

uglify2

  1. uglify2: {
  2. //Example of a specialized config. If you are fine
  3. //with the default options, no need to specify
  4. //any of these properties.
  5. output: {
  6. beautify: true
  7. },
  8. compress: {
  9. sequences: false,
  10. global_defs: {
  11. DEBUG: false
  12. }
  13. },
  14. warnings: true,
  15. mangle: false
  16. },

使用UglifyJS2進行代碼壓縮, 具體參數配置可見UglifyJS2

closure

  1. closure: {
  2. CompilerOptions: {},
  3. CompilationLevel: ‘SIMPLE_OPTIMIZATIONS‘,
  4. loggingLevel: ‘WARNING‘
  5. },

如果用Closure Compiler優化,這個參數可以用來配置Closure Compiler,詳細請看Closure Compiler的文檔

optimizeCss

optimizeCss: "standard.keepLines.keepWhitespace",

是否優化CSS文件,以那種方式優化。

  • "standard": @import inlining and removal of comments, unnecessary whitespace and line returns.Removing line returns may have problems in IE, depending on the type of CSS.
  • "standard.keepLines": like "standard" but keeps line returns.
  • "none": skip CSS optimizations.
  • "standard.keepComments": keeps the file comments, but removes linereturns. (r.js 1.0.8+)
  • "standard.keepComments.keepLines": keeps the file comments and linereturns. (r.js 1.0.8+)
  • "standard.keepWhitespace": like "standard" but keeps unnecessary whitespace.

cssImportIgnore

 cssImportIgnore: null,

是否忽略 CSS 資源文件中的 @import 指令

cssIn

cssIn: "path/to/main.css",

一般用於命令行,可將多個 CSS 資源文件打包成單個 CSS 文件

out

out: "path/to/css-optimized.css",

一般用於命令行,可將多個 CSS 資源文件打包成單個 CSS 文件

cssPrefix

cssPrefix: "",

如果”out”和”cssIn”不是同一目錄,並且在cssIn文件裏面有url()相對目錄的,用這個去設置URL前置。僅僅在優化後URL不正確的情況下使用。

inlineText

inlineText: true,

處理所有的文本資源依賴項,從而避免為加載資源而產生的大量單獨xhr請求

useStrict

useStrict: false,

是否開啟嚴格模式, 由於很多瀏覽器不支持 ES5 的嚴格模式,故此配置默認值為 false

pragmas

  1. pragmas: {
  2. fooExclude: true
  3. },

指定生成編譯指示。如果源文件包含類似如下註釋:>>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

  1. pragmasOnSave: {
  2. //Just an example
  3. excludeCoffeeScript: true
  4. },

和”pragmas”一樣,但只能在文件保存的優化階段應用一次。”pragmas”可以同時在依賴映射和文件保存優化階段應用。有些”pragmas”可能不會在依賴映射時被執行,例如在CoffeeScript的loader插件中,只想CoffeeScript做依賴映射,但是一旦這個文件被保存為一個javascript文件,CoffeeScript compiler就沒用了。那樣的話,pragmasOnSave就會用於在保存期排除編譯代碼。

has

  1. has: {
  2. ‘function-bind‘: true,
  3. ‘string-trim‘: false
  4. },

使用”has”允許trimming代碼樹。基於js的特征檢測:https://github.com/phiggins42/has.js。代碼樹修飾僅僅在使用UglifyJS或Closure Compiler壓縮時發生。更多請見:http://requirejs.org/docs/optimization.html

hasOnSave

  1. hasOnSave: {
  2. ‘function-bind‘: true,
  3. ‘string-trim‘: false
  4. },

和pragmasOnSave類似。

namespace

namespace: ‘foo‘,

命名空間,完整實例可以參考 http://requirejs.org/docs/faq-advanced.html

skipPragmas

skipPragmas: false,

跳過執行pragmas

skipModuleInsertion

skipModuleInsertion: false,

如果是false,文件就不會用define()來定義模塊而是用一個define()占位符插入其中。另外,require.pause/resume調用也會被插入。設置為”true”來避免。這個參數用在你不是用require()來創建項目或者寫js文件,但是又想使用RquireJS的優化工具來合並模塊是非常有用的。

stubModules

stubModules: [‘text‘, ‘bar‘],

將模塊排除在優化文件之外。

optimizeAllPluginResources

optimizeAllPluginResources: false,

如果不是一個文件的優化,描述輸出目錄的所有.js文件的插件依賴,如果這個插件支持優化成為一個單獨的文件,就優化它。可能是一個比較慢的優化過程。僅僅在有些插件用了像XMLHttpRequest不支持跨域,並且生成的代碼會被放在另一個域名。

findNestedDependencies

findNestedDependencies: false,

尋找require()裏面的require或define調用的依賴。默認為false是因為這些資源應該被認為是動態加載或者實時調用的。當然,有些優化場景也需要將它們合並在一起。

removeCombined

removeCombined: false

如果設置為true,在輸出目錄將會刪除掉已經合並了的文件

modules

  1. modules: [
  2. //Just specifying a module name means that module will be converted into
  3. //a built file that contains all of its dependencies. If that module or any
  4. //of its dependencies includes i18n bundles, they may not be included in the
  5. //built file unless the locale: section is set above.
  6. {
  7. name: "foo/bar/bop",
  8. //create: true can be used to create the module layer at the given
  9. //name, if it does not already exist in the source location. If
  10. //there is a module at the source location with this name, then
  11. //create: true is superfluous.
  12. create: true,
  13. //For build profiles that contain more than one modules entry,
  14. //allow overrides for the properties that set for the whole build,
  15. //for example a different set of pragmas for this module.
  16. //The override‘s value is an object that can
  17. //contain any of the other build options in this file.
  18. override: {
  19. pragmas: {
  20. fooExclude: true
  21. }
  22. }
  23. },
  24. //This module entry combines all the dependencies of foo/bar/bop and foo/bar/bee
  25. //and any of their dependencies into one file.
  26. {
  27. name: "foo/bar/bop",
  28. include: ["foo/bar/bee"]
  29. },
  30. //This module entry combines all the dependencies of foo/bar/bip into one file,
  31. //but excludes foo/bar/bop and its dependencies from the built file. If you want
  32. //to exclude a module that is also another module being optimized, it is more
  33. //efficient if you define that module optimization entry before using it
  34. //in an exclude array.
  35. {
  36. name: "foo/bar/bip",
  37. exclude: [
  38. "foo/bar/bop"
  39. ]
  40. },
  41. //This module entry shows how to specify a specific module be excluded
  42. //from the built module file. excludeShallow means just exclude that
  43. //specific module, but if that module has nested dependencies that are
  44. //part of the built file, keep them in there. This is useful during
  45. //development when you want to have a fast bundled set of modules, but
  46. //just develop/debug one or two modules at a time.
  47. {
  48. name: "foo/bar/bin",
  49. excludeShallow: [
  50. "foo/bar/bot"
  51. ]
  52. },
  53. //This module entry shows the use insertRequire (first available in 2.0):
  54. {
  55. name: "foo/baz",
  56. insertRequire: ["foo/baz"]
  57. }
  58. ],

列出要優化的模塊。如果有依賴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

insertRequire: [‘foo/bar/bop‘],

如果目標模塊在頂層級只調用了define沒有調用require(),並且輸出文件在data-main中使用,如果頂層沒有require,就不會有任何模塊被加載。定義insertRequire在文件尾部來執行其它模塊,更多參見:https://github.com/jrburke/almond

name

name: "foo/bar/bop",

include

include: ["foo/bar/bee"],

insertRequire

insertRequire: [‘foo/bar/bop‘],

out

out: "path/to/optimized-file.js",

如果只優化一個模塊(和它的依賴項),而且是生成一個單文件,你可以在行內定義模塊的選項,以代替modules參數的定義方式,”exclude”, “excludeShallow”, “include”和”insertRquire”都可以以兄弟屬性的方式定義。

deps

deps: ["foo/bar/bee"],

“include”的替換方案。一般用requirejs.config()來定義並用mainConfigFile引入。

out

  1. out: function (text, sourceMapText) {
  2. //Do what you want with the optimized text here.
  3. //Starting in 2.1.10, if generateSourceMaps was set to true
  4. //and optimize: ‘uglify2‘ was used, then the second argument
  5. //to this function, sourceMapText, will be the text of the source map.
  6. },

在2.0,”out”可以是一個函數, 對單個JS文件優化可以調用requirejs.optimize(), 用out函數表示優化過後的內容不會被寫到磁盤,而是傳遞給out函數

out

out: “stdout”

在2.0.12+, 設置”out”為”stdout”, 優化輸出會寫到STDOUT,這對於r.js整合其它命令行工具很有用。為了避免額外的輸出”logLevel: 4”應該被使用。

wrap

  1. wrap: {
  2. start: "(function() {",
  3. end: "}());"
  4. },

wrap任何東西在start和end之間,用於define/require不是全局的情況下,在end裏可以暴露全局對象在文件中。

wrap

wrap: true,

wrap的另一種方式,默認是(function() { + content + }())

wrap

  1. wrap: {
  2. startFile: "parts/start.frag",
  3. endFile: "parts/end.frag"
  4. },

用文件來wrap

wrap

  1. wrap: {
  2. startFile: ["parts/startOne.frag", "parts/startTwo.frag"],
  3. endFile: ["parts/endOne.frag", "parts/endTwo.frag"]
  4. },

多個文件的wrap

fileExclusionRegExp

fileExclusionRegExp: /^./,
跳過任何以.開頭的目錄和文件,比如.files, .htaccess等

preserveLicenseComments

preserveLicenseComments: true,

默認註釋有授權在裏面。當然,在大項目生成時,文件比較多,註釋也比較多,這樣可以把所有註釋寫在文件的頂部。

logLevel

logLevel: 0

設置logLevel。

TRACE: 0,

INFO: 1

WARN: 2

ERROR: 3

SILENT: 4

throwWhen

  1. throwWhen: {
  2. optimize: true
  3. }

在2.1.3,有些情況下當錯誤發生時不會拋出異常並停止優化,你可能想讓優化器在某些錯誤發生時停止,就可以使用這個參數

onBuildRead

  1. onBuildRead: function (moduleName, path, contents) {
  2. //Always return a value.
  3. //This is just a contrived example.
  4. return contents.replace(/foo/g, ‘bar‘);
  5. },

當每個文件被讀取的時候調用這個方法來改變文件內容

onBuildWrite

  1. onBuildWrite: function (moduleName, path, contents) {
  2. //Always return a value.
  3. //This is just a contrived example.
  4. return contents.replace(/bar/g, ‘foo‘);
  5. },

允許在寫入目標文件前執行方法改變內容

onModuleBundleComplete

  1. onModuleBundleComplete: function (data) {
  2. /*
  3. data.name: the bundle name.
  4. data.path: the bundle path relative to the output directory.
  5. data.included: an array of items included in the build bundle.
  6. If a file path, it is relative to the output directory. Loader
  7. plugin IDs are also included in this array, but depending
  8. on the plugin, may or may not have something inlined in the
  9. module bundle.
  10. */
  11. },

每個JS模塊集完成後執行。 模塊集是指一個modules數組項。

rawText

  1. rawText: {
  2. ‘some/id‘: ‘define(["another/id"], function () {});‘
  3. },

在2.1.3,種子raw text是模塊ID的列表。這些文本內容用於代替模塊的文件IO調用。用於模塊ID是基於用戶動態輸入的情況,在網頁生成工具中常用。

cjsTranslate

cjsTranslate: true,

在2.0.2中。如果為true, 優化器會添加define(require, exports, module) {});包裹每一個沒有調用define()的文件。

useSourceUrl

useSourceUrl: true,

在2.0.2,有點實驗性質。每一個模塊集最後都會添加一段//# sourceUrl的註釋。

waitSeconds

waitSeconds: 7

參見: RequireJS進階:配置文件的學習

skipSemiColonInsertion

skipSemiColonInsertion: false

在2.1.9,通常r.js插入一個分號在文件末尾,如果沒有的話。

keepAmdefine

keepAmdefine: false

在2.1.10, 如果是true,就不會刪除amdefine,詳情見:https://github.com/jrburke/amdefine

allowSourceOverwrites

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

RequireJS進階-模塊的優化及配置的詳解