私は現在、かなり大きな Angular JS アプリケーションのパフォーマンスを向上させようとしています。これは、javascript ファイルの 1 つの大きなチャンクから、遅延ロードされる可能性のある 3 ~ 4 つの小さなチャンクに移行することによって実現しています。
次の npm パッケージとバージョンを使用しています。
grunt-contrib-requirejs: 1.0.0
grunt: 0.4.5
requirejs: 2.3.0
最初は、すべての必要な JavaScript ファイルを取得し、requirejs オプティマイザーを使用してそれらすべてを 1 つのファイルに含める 1 つの面倒なタスクがありました。そのmain.js
ため、特定のすべてのパッケージのすべてのパスとシムが定義された 1 つのメイン構成ファイルがありました (私は必要に応じてサンプル構成などを投稿できます)。
ここでのアイデアは、この 1 つの大きなファイルを持つことから移行し、アプリケーションを 3 つから 4 つの小さな JavaScript ファイルにモジュール化して、ロード時間を短縮することです (4 つの小さなファイルを並行してロードする方が、1 つの大きなファイルをロードするよりも高速であるため)。
そのために、grunt-requirejs の modules オプションと bundles オプションを使用して、すべてのモジュールとその内容を定義します。
プロジェクトの構造は次のとおりです。
/src/
./Gruntfile.js
./scripts/
./app.js
./vendor.js
./app_mini.js
./features/
./test.service.js
/dist/
grunt タスクは次のように定義されます。
requirejs: {
bundle: {
options: {
baseUrl: '/src',
mainConfigFile: '/src/scripts/app.js',
bundlesConfigOutFile: 'scripts/app.js',
findNestedDependencies: true,
dir: '/dist',
modules: [
{
name: 'scripts/vendor',
exclude: [],
override: {
{
paths: {
'angular': 'bower/angular/angular',
'jquery': 'bower/jquery/dist/jquery'
},
bundles: {
}
},
}
},
{
name: 'scripts/app',
exclude: ['scripts/vendor'],
override: {
{
paths: {
'vendor': 'scripts/vendor',
'app_mini': 'scripts/app_mini',
'testservice': 'scripts/features/test.service'
},
bundles: {
'vendor': ['angular', 'jquery']
}
}
}
]
}
}
}
requirejs:bundle 実行後の dist フォルダーは次のようになります。
/dist/
./scripts/
./app.js
./vendor.js
したがって、app_mini
とtestservice
は に含まれapp.js
、angular
とjquery
は に含まれvendor.js
ます。
src フォルダー内の私app.js
のものは、多かれ少なかれ次のようになります。
define('app',
[
'angular',
'app_mini',
'testservice'
],
function(
angular,
app_mini,
testservice) {}
);
require([
'angular',
'app_mini',
'testservice'
], function (
angular,
app_mini,
testservice
) {
// entry to app
}, function(err) {
console.log('error loading module: ' + err.requireModules);
};
長いファイルの内容で申し訳ありませんが、それなしで問題を説明することは不可能です:) したがって、問題は、オプティマイザーとアプリ自体の Requirejs 構成全体を配置するための中心的な場所が必要なことです。ただし、明らかに、オプティマイザのパスは gruntfile パスに対して相対的であり、実行中のアプリのパスは対応するファイルに対して相対的です。
バンドル構成は requirejs によって自動的に生成されるため (bundlesConfigOutFile のため)、そこで使用される名前については、モジュール オプションから取得されるため、実際には多くのことを行うことはできません。
生成されて app.js に含まれるバンドル構成は次のようになります。
require.config({
bundles: {
'scripts/vendor': [
'angular',
'jquery'
],
'scripts/app': [
'testservice',
'app_mini',
'app'
]
}
});
まず、RequireJs が vendor.js をパスでロードしたいという問題がありました。scripts/scripts/vendor.js
それを修正するために、私は abaseUrl = '/'
をrequire.config
ofに含めましたapp
しかし、今、私は問題を抱えていますtestservice
.injectapp_mini
とangular
.
dist フォルダー内の最適化された app.js は次のようになります。おそらく問題を見つけることができます。
(function(){
define(
'testservice',[
'angular',
'app_mini'
], function(
angular,
app_mini
) {
'use strict';
app_mini.factory('testservice', TestService);
function TestService() {
var service = {
test: test
};
return service;
};
var test = function() {
console.log("testservice::test()");
};
});
define('app_mini',
[
'angular',
'testservice'
],
function (
angular,
testservice
) {
'use strict';
var module = angular.module(‘some.project’, []);
module.run(AppRun);
AppRun.$inject = [
'$rootScope',
'testservice'
];
function AppRun($rootScope, testservice) {
console.log(“yay, it works”);
testservice.test();
}
return module;
}
);
require.config({
bundles: {
'scripts/vendor.bundle': [
'angular',
'jquery'
],
'scripts/app.bundle': [
'testservice',
'app_mini',
'app'
]
}
});
require.config({
baseUrl: '/'
});
define(‘app’,
[
'angular',
'app_mini',
'testservice'
], function(
angular,
app_mini,
testservice
){});
require([
'angular',
'app_mini',
'testservice'
], function (
angular,
app_mini,
testservice
) {
angular.element().ready(function () {
var $html = angular.element(document.getElementsByTagName('html')[0]);
angular.bootstrap($html, [app_mini['name']]);
});
}, function (err) {
'use strict';
console.log('Error loading requirejs-module: ' + err.requireModules);
});
define("scripts/app.bundle", function(){});
})();