首先,這不是一個獨特的解決方案的問題。我將解釋我使用RequireJS的方式,它適用於我,並可能適合你:)
二,英語不是我的母語。有關該語言的更正和提示將非常感謝。隨意,球員:)
1)是否需要JS甚至實際爲不是單頁的項目?
這取決於。例如,如果你的項目在頁面之間沒有共享代碼,RequireJS的幫助將是適度的。 RequireJS的主要思想是將應用程序模塊化爲可重用代碼的塊。如果你的應用程序只使用頁面特定的代碼,那麼使用RequireJS可能不是一個好主意。
2)不使用優化器,我的每個主文件都以基本相同的配置選項開始。有沒有辦法避免這種情況?像每個主文件都包含相同的構建配置文件而不必實際構建它?
我看到正在對主文件的配置,或創建一個模塊,將配置RequireJS,然後使用該模塊作爲main.js.第一依賴的唯一途徑但這可能會很棘手。我的應用程序中不使用許多main.js文件;我只使用一個充當裝載程序的應用程序(請參見下文)。
3)r.js是否應該進入httpdocs_siteroot的父目錄?
不一定。你可以把它放在/ media目錄中,因爲你所有的客戶端都在那裏。
4)我的應用程序目錄結構或使用requirejs有什麼明顯的錯誤嗎?
我不會那麼說。另一方面,結構可能有點過於分散。例如,你可以把所有的'第三方東西'放在一個/ vendor目錄中。但這只是糖;你的結構將運作良好,看起來是正確的。我認爲主要問題是多個主文件中的requirejs.config()調用。
我現在有同樣的問題,我結束了以下解決方案:
1)不要用規定的包裝不符合要求的AMD-文件。儘管它起作用,但您可以使用requirejs.config中的「shim」屬性(請參見下文)獲得相同的結果。
2)在多頁面應用程序中,我的解決方案是不要求優化的main.js文件中的頁面特定模塊。相反,我需要從主文件中獲取所有共享代碼(第三方和我自己的代碼),並在每個頁面上加載頁面特定的代碼。主文件最終只是一個加載器,在加載所有共享/ lib文件後啓動特定於頁面的代碼。
這是我用它來建立與requirejs一個多頁應用的樣板
目錄結構:
/src目錄 - 我把所有的客戶端的東西一個src目錄裏面,所以我可以運行該目錄內的優化器(這是您的媒體目錄)。
/src/vendor - 這裏我放置所有第三方文件和插件,包括require.js。
/src/lib - 在這裏,我放置了由整個應用程序或某些頁面共享的所有自己的代碼。換句話說,不是頁面特定的模塊。
/src/page-module-xx - 然後,我爲每個頁面創建一個目錄。這不是一個嚴格的規定。
/src/main.js:這是整個應用程序的唯一主文件。它將:
- 配置RequireJS,包括墊片
- 負載共享庫/模塊
- 負載特定頁面的主模塊
這是一個requirejs.config呼叫的例子:
requirejs.config({
baseUrl: ".",
paths: {
// libraries path
"json": "vendor/json2",
"jquery": "vendor/jquery",
"somejqueryplugion": "vendor/jquery.somejqueryplufin",
"hogan": "vendor/hogan",
// require plugins
"templ": "vendor/require.hogan",
"text": "vendor/require.text"
},
// The shim section allows you to specify
// dependencies between non AMD compliant files.
// For example, "somejqueryplugin" must be loaded after "jquery".
// The 'exports' attribute tells RequireJS what global variable
// it must assign as the module value for each shim.
// For example: By using the configutation below for jquery,
// when you request the "jquery" module, RequireJS will
// give the value of global "$" (this value will be cached, so it is
// ok to modify/delete the global '$' after all plugins are loaded.
shim: {
"jquery": { exports: "$" },
"util": { exports: "_" },
"json": { exports: "JSON" },
"somejqueryplugin": { exports: "$", deps: ["jquery"] }
}
});
然後,配置完成後,我們可以做出第一個require()請求 爲所有這些庫,然後做我們的「頁面主」模塊的請求。
//libs
require([
"templ", //require plugins
"text",
"json", //3rd libraries
"jquery",
"hogan",
"lib/util" // app lib modules
],
function() {
var $ = require("jquery"),
// the start module is defined on the same script tag of data-main.
// example: <script data-main="main.js" data-start="pagemodule/main" src="vendor/require.js"/>
startModuleName = $("script[data-main][data-start]").attr("data-start");
if (startModuleName) {
require([startModuleName], function (startModule) {
$(function(){
var fn = $.isFunction(startModule) ? startModule : startModule.init;
if (fn) { fn(); }
});
});
}
});
正如您在上面require()的主體中看到的那樣,我們期待require.js腳本標記的另一個屬性。 data-start屬性將保存當前頁面的模塊名稱。
因此,在HTML頁面上,我們必須增加這些額外的屬性:
<script data-main="main" data-start="pagemodule/main" src="vendor/require.js"></script>
通過這樣做,我們將結束與優化main.js一個包含「/供應商」和「所有文件/ lib「目錄(共享資源),但不包括頁面特定的腳本/模塊,因爲它們在main.js中沒有作爲依賴關係進行硬編碼。頁面特定模塊將在應用程序的每個頁面上分別加載。
「頁面主」模塊應返回function()
,將由上面的「應用程序主」執行。
define(function(require, exports, module) {
var util = require("lib/util");
return function() {
console.log("initializing page xyz module");
};
});
編輯
下面是例子,你如何使用的建造輪廓,以優化有一個以上的文件中的特定頁面模塊。
例如,假設我們有以下頁面模塊:
/page1/main.js
/page1/dep1.js
/page1/dep2.js
如果我們不優化這個模塊,那麼瀏覽器會發出3個請求,每個腳本都有一個請求。 我們可以通過指示r.js創建一個包幷包含這3個文件來避免這種情況。
在建造輪廓的「模塊」屬性:
...
"modules": [
{
name: "main" // this is our main file
},
{
// create a module for page1/main and include in it
// all its dependencies (dep1, dep2...)
name: "page1/main",
// excluding any dependency that is already included on main module
// i.e. all our shared stuff, like jquery and plugins should not
// be included in this module again.
exclude: ["main"]
}
]
通過這樣做,我們創建了具有所有依賴另一個單頁主文件。但是,由於我們已經有一個主文件可以加載我們所有的共享內容,因此我們不需要再將它們包含在page1/main模塊中。 該配置有點冗長,因爲您必須爲每個頁面模塊執行此操作,而您有多個腳本文件。
我上傳了GitHub中的樣板代碼:https://github.com/mdezem/MultiPageAppBoilerplate。 這是一個正在運行的樣板,只需爲節點安裝node和r.js模塊並執行build.cmd(位於/ build目錄中,否則將失敗,因爲它使用相對路徑)
我希望我已經清楚。讓我知道是否聽起來有點奇怪;)
問候!
我有和簡短的答案,但我需要一些細節:多少頁?每個頁面特定的代碼很少或很多代碼(比如,每個頁面代碼爲10kb)? – devundef 2012-07-29 09:58:11
你使用的是requirejs插件,插件是什麼? – devundef 2012-07-29 10:00:32
通常每個mainjs文件<10kb。我只是將它用於初始化jquery插件之類的東西。將會有很多頁面......我會說20並且在不斷增長。所以可能大約有15個mainjs文件和增長。我使用的插件是jquery插件,並使用define調用包裝以符合AMD標準 – AndyPerlitch 2012-07-29 16:27:44