2014-12-20 46 views
2

項目結構requirejs回調不確定

root 
    wwwroot <-- files under this location are static files public to the site 
     css 
     lib 
      bootstrap/js/bootstrap.js 
      jquery/js/jquery.js 
      knockout/knockout.js 
      requires/require.js 
     scripts 
      modules    ┌───────────────┐ 
       global.js  <--│ Built modules │ 
       dropdown.js  └───────────────┘ 
    modules 
     global.js     ┌────────────────┐ 
     dropdown    <--│ Source modules │ 
      dropdown.js   └────────────────┘ 
    gruntfile.js 

global.cs內容(預編譯的版本在〜/模塊/ global.js)

require.config({ 
    baseUrl: "scripts/modules", 
    paths: { 
     jquery: "../../lib/jquery/js/jquery", 
     bootstrap: "../../lib/bootstrap/js/bootstrap", 
     knockout: "../../lib/knockout/knockout" 
    }, 
    shims: { 
     bootstrap: { 
      deps: ['jquery'] 
     } 
    }, 
}); 

define(function (require) { 
    var $ = require('jquery'); 
    var ko = require('knockout'); 
    var bootstrap = require('bootstrap'); 
}); 

dropdown.js內容 (〜/ modules/dropdown.js預建版)

define(function() { 
    console.log('dropdown initialized'); 
    return 'foo'; 
}); 

HTML頁面

包含在加載頁面的<head>這個腳本標籤需要配置:

<script src="~/lib/requirejs/require.js" data-main="scripts/modules/global"></script> 

在HTML頁面的主體,我有以下幾點:

<script> 
    require(['global'], function() { 
     require(['dropdown'], function (dropdown) { 
      console.log(dropdown); 
     }); 
    }); 
</script> 

Issue

dropdown回調是undefined而不是我從定義的模塊返回的預期「foo」字符串。

事實上,控制檯不包含「下拉初始化」的日誌項目。這讓我相信模塊沒有被調用?然而,很奇怪dropdown.js作爲加載到頁面中的腳本存在於F12調試器中。因此,要求確實調用了加載它,但沒有運行定義的內容?

值得注意提到

  • 我使用r.js優化和建設。 global.js和dropdown.js都經過處理。
  • 由r.js處理分配給下拉模塊的名稱是「modules/dropdown/dropdown.js」。我不確定我是否應該以某種方式使用它,或者如果我正確地將模塊稱爲dropdown並依靠我的baseUrl配置具有正確的路徑。

編輯#1

我已經添加了r.js建立與每評議請求咕嚕使用的配置。結合起來,我更新了文件結構以包含整個項目結構,而不僅僅是運行時公共wwwroot結構。

r.js過程將彙總來自源位置~/modules~/wwwroot/scripts/modules中編譯的global.js +其他模塊的內置形式。

function getRequireJsConfiguration() { 
    var baseUrl = './'; 
    var paths = { 
     jquery: "wwwroot/lib/jquery/js/jquery", 
     bootstrap: "wwwroot/lib/bootstrap/js/bootstrap", 
     knockout: "wwwroot/lib/knockout/knockout" 
    }; 
    var shims = { 
     bootstrap: { 
      deps: ['jquery'] 
     } 
    }; 
    var optimize = 'none'; 

    var configuration = {}; 

    var jsFilePaths = grunt.file.expand('modules/**/*.js'); 
    jsFilePaths.forEach(function (jsFilePath) { 
     var fileName = jsFilePath.split('/').pop(); 

     if (configuration[fileName]) { 
      throw 'Duplicate module name conflict: ' + fileName; 
     } 

     configuration[fileName] = { 
      options: { 
       baseUrl: './', 
       name: jsFilePath, 
       out: 'wwwroot/scripts/modules/' + fileName, 
       paths: paths, 
       shims: shims, 
       optimize: optimize, 
       exclude: ['jquery', 'knockout', 'bootstrap'] 
      } 
     }; 
    }); 

    configuration['global'] = { 
     options: { 
      baseUrl: './', 
      name: 'modules/global.js', 
      out: 'wwwroot/scripts/modules/global.js', 
      paths: paths, 
      shims: shims, 
      optimize: optimize, 
     } 
    }; 

    return configuration; 
} 

編輯#2

以爲它會是一個好主意,包括requirejs包的版本我使用的是:

requirejs: 2.1.15 
grunt-contrib-requirejs: 0.4.4 

感謝。

+0

請將您的'r.js'構建配置添加到您的問題中。 – Louis

+0

我已經根據你的請求添加了這個,並且更新了文件結構以包含相關的項目結構(這樣你就可以瞭解r.js的輸入和輸出)。謝謝。 –

回答

1

雖然我已經解決了我的問題與提示wyantb提供的答案,因爲我已經改變了我的方式,以單個文件CONCAT由於它所帶來的簡單性。我仍然希望公佈如何解決這個問題的具體細節,以便其他任何人發生。

在grunt構建配置選項中,我添加了onBuildWrite字段來轉換內容,所以我分配的模塊ID與我如何懶惰地加載它們一致。

onBuildWrite: function (moduleName, path, contents) { 
    return contents.replace(/modules\/global.js/, 'global'); 
} 

此代碼專門用於global.js文件。我爲其他模塊文件(在foreach循環中)實現了類似的onBuildWrite。轉換將從r.js分配的模塊名稱中刪除路徑和擴展名。

下面是之前和之後的一些例子:

Before        After 
/modules/global.js     global 
/modules/dropdown/dropdown.js   dropdown 
/modules/loginButton/loginButton.js loginButton 

因此,當我從我原來的問題加載使用HTML腳本模塊,requirejs解析和發現匹配。

-1

要麼需要由路徑或在global.cs

require(['./global'], function() { 
    require(['./dropdown'], function (dropdown) { 
     console.log(dropdown); 
    }); 
}); 
+0

沒有運氣。行爲保持不變。 –

+0

您是否嘗試過在globle.cs路徑中定義全局和下拉列表?像'dropdown:「./dropdown」'。由於在構建項目之後,require環境中的文件模塊名稱將爲'scripts/modules/dropdown' – elaijuh

+0

我想避免將每個模塊的路徑添加到global.js(require配置),因爲我不想緊緊地將這些超出baseUrl路徑。任何時候我添加或刪除一個模塊,我不想記得添加/刪除一個路徑。但是,也許有一點我不理解你的建議。如果是這樣的話,請讓我知道。 –

1

通過r.js處理分配給下拉模塊的名稱爲 「模塊/下拉/ dropdown.js」 定義globaldropdown。我不確定是否應該以某種方式使用它,或者如果我正確地將模塊稱爲下拉菜單並依賴具有正確路徑的baseUrl配置。

從某種意義上說,是的,你應該使用完整的路徑。這就是要求提到的模塊id - 「modules/dropdown/dropdown」(如果上述輸出中的.js是真實的,我建議在「name」配置中剝離該擴展名.js由RequireJS假定,在你的模塊id中不需要那個字符串)。當給定ID時,使用basePath將一些未知ID轉換爲文件路徑(例如'bootstrap'id - >(應用路徑配置) - >'../../lib/bootstrap/js/bootstrap' - > (應用基URL) - >'scripts/modules /../../ lib/bootstrap/js/bootstrap')。

真的,只是允許r.js將所有內容連接成一個文件 是首選的方式。您可以使用include選項將global.js未引用的模塊也包含在優化包中(https://github.com/jrburke/r.js/blob/master/build/example.build.js#L438

至於您的具體問題:您的懶惰require(['dropdown'])調用會誤導您。通過將請求的模塊ID與basePath相結合,RequireJS提供了您想要的URL - scripts/modules/dropdown - 它定義了一個模塊ID爲scripts/module/dropdown的模塊 - 但由於您請求模塊ID爲dropdown,所以您什麼也得不到。 (我想你會得到一個RuntimeError而不是未定義的,但我想這就是事情的方式)。無論如何,你需要解決ID /路徑不匹配問題。

+0

謝謝。我將其標記爲有用,但不是答案,因爲它沒有提供如何解決問題的具體信息(代碼)。我已經發布瞭解決特定問題的代碼(請參閱我的答案)。 –

+0

有道理。我沒有給出具體的答案,因爲這幾乎是一個意見問題,如果我們足夠了解AMD/RJS。很高興我能幫上忙! – wyantb