Maison > interface Web > js tutoriel > le corps du texte

Webpack implémente le chargement paresseux d'AngularJS_AngularJS

WBOY
Libérer: 2016-05-16 15:12:22
original
1656 Les gens l'ont consulté

À mesure que votre application monopage grandit, son temps de téléchargement augmente également. Cela n’apportera pas grand-chose à l’expérience utilisateur (indice : mais l’expérience utilisateur est la raison pour laquelle nous développons des applications à page unique). Plus de code signifie des fichiers plus gros, et jusqu'à ce que la compression du code ne réponde plus à vos besoins, la seule chose que vous pouvez faire pour vos utilisateurs est d'arrêter de leur demander de télécharger l'intégralité de l'application en une seule fois. C’est là que le chargement paresseux s’avère utile. Au lieu de télécharger tous les fichiers en même temps, l'utilisateur est autorisé à télécharger uniquement les fichiers dont il a besoin actuellement.

Alors. Comment faire en sorte que votre application soit paresseuse à chargement ? Il est essentiellement divisé en deux choses. Divisez votre module en petits morceaux et implémentez un mécanisme permettant à ces morceaux d'être chargés à la demande. Cela ressemble à beaucoup de travail, n'est-ce pas ? Pas si vous utilisez Webpack. Il prend en charge les fonctionnalités de fractionnement de code prêtes à l'emploi. Dans cet article, je suppose que vous connaissez Webpack, mais si ce n'est pas le cas, voici une introduction. Pour faire court, nous utiliserons également AngularUI Router et ocLazyLoad.

Le code est disponible sur GitHub. Vous pouvez le débourser à tout moment.

Configuration du Webpack

Rien de spécial, vraiment. Vous pouvez en fait simplement copier et coller à partir de la documentation, la seule différence est l'utilisation de ng-annotate pour garder notre code propre, et de babel pour utiliser une partie de la magie ECMAScript 2015. Si vous êtes intéressé par ES6, vous pouvez consulter ce post précédent . Bien que ces éléments soient tous excellents, aucun d’entre eux n’est nécessaire pour implémenter le chargement différé.

// webpack.config.js
var config = {
entry: {
app: ['./src/core/bootstrap.js'],
},
output: {
path: __dirname + '/build/',
filename: 'bundle.js',
},
resolve: {
root: __dirname + '/src/',
},
module: {
noParse: [],
loaders: [
{ test: /\.js$/, exclude: /node_modules/,
loader: 'ng-annotate!babel' },
{ test: /\.html$/, loader: 'raw' },
]
}
};
module.exports = config;
Copier après la connexion

Postuler

Le module d'application est le fichier principal, qui doit être inclus dans bundle.js, qui doit être téléchargé sur chaque page. Comme vous pouvez le voir, nous ne chargeons rien de compliqué à part des dépendances globales. Contrairement au chargement du contrôleur, nous chargeons uniquement la configuration du routage.

// app.js
'use strict';
export default require('angular')
.module('lazyApp', [
require('angular-ui-router'),
require('oclazyload'),
require('./pages/home/home.routing').name,
require('./pages/messages/messages.routing').name,
]);
Copier après la connexion

Configuration du routage

Tous les chargements différés sont implémentés dans la configuration de l'itinéraire. Comme je l'ai dit, nous utilisons AngularUI Router car nous devons implémenter des vues imbriquées. Nous avons plusieurs cas d'utilisation. Nous pouvons charger le module entier (y compris les contrôleurs d'état enfants) ou charger un contrôleur par état (indépendamment des dépendances sur les états parents).

Charger l'intégralité du module

Lorsque l'utilisateur entre le chemin /home, le navigateur téléchargera le module home. Il comprend deux contrôleurs, pour les deux états home et home.about. Nous pouvons implémenter un chargement paresseux via l'attribut solve dans l'objet de configuration d'état. Grâce à la méthode require.ensure de Webpack, nous pouvons créer le module home comme premier bloc de code. Cela s'appelle 1.bundle.js . Sans $ocLazyLoad.load , nous constaterons que nous obtenons une erreur Argument 'HomeController' is not a function, got undefined , car dans la conception d'Angular, il n'est pas possible de charger des fichiers après le démarrage de l'application. Mais $ocLazyLoad.load nous permet d'enregistrer un module au démarrage puis de l'utiliser après son chargement.

// home.routing.js
'use strict';
function homeRouting($urlRouterProvider, $stateProvider) {
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url: '/home',
template: require('./views/home.html'),
controller: 'HomeController as vm',
resolve: {
loadHomeController: ($q, $ocLazyLoad) => {
return $q((resolve) => {
require.ensure([], () => {
// load whole module
let module = require('./home');
$ocLazyLoad.load({name: 'home'});
resolve(module.controller);
});
});
}
}
}).state('home.about', {
url: '/about',
template: require('./views/home.about.html'),
controller: 'HomeAboutController as vm',
});
}
export default angular
.module('home.routing', [])
.config(homeRouting);
Copier après la connexion

Les contrôleurs sont traités comme des dépendances de module.

// home.js
'use strict';
export default angular
.module('home', [
require('./controllers/home.controller').name,
require('./controllers/home.about.controller').name
]);
Copier après la connexion

Contrôleur de charge uniquement

Ce que nous faisons est le premier pas en avant, puis passons à l’étape suivante. Cette fois, il n’y aura pas de gros modules, juste des contrôleurs rationalisés.

// messages.routing.js
'use strict';
function messagesRouting($stateProvider) {
$stateProvider
.state('messages', {
url: '/messages',
template: require('./views/messages.html'),
controller: 'MessagesController as vm',
resolve: {
loadMessagesController: ($q, $ocLazyLoad) => {
return $q((resolve) => {
require.ensure([], () => {
// load only controller module
let module = require('./controllers/messages.controller');
$ocLazyLoad.load({name: module.name});
resolve(module.controller);
})
});
}
}
}).state('messages.all', {
url: '/all',
template: require('./views/messages.all.html'),
controller: 'MessagesAllController as vm',
resolve: {
loadMessagesAllController: ($q, $ocLazyLoad) => {
return $q((resolve) => {
require.ensure([], () => {
// load only controller module
let module = require('./controllers/messages.all.controller');
$ocLazyLoad.load({name: module.name});
resolve(module.controller);
})
});
}
}
})
Copier après la connexion

Je pense qu'il n'y a rien de spécial ici et que les règles peuvent rester les mêmes.

Chargement des vues

Maintenant, laissons de côté le contrôleur un instant et concentrons-nous sur la vue. Comme vous l'avez peut-être remarqué, nous intégrons la vue dans la configuration du routage. Cela ne serait pas un problème si nous n'avions pas mis toute la configuration de routage dans bundle.js , mais nous devons maintenant le faire. Ce cas ne concerne pas la configuration de la route de chargement paresseux mais les vues, donc lorsque nous utiliserons Webpack pour l'implémenter, ce sera très simple.

// messages.routing.js
...
.state('messages.new', {
url: '/new',
templateProvider: ($q) => {
return $q((resolve) => {
// lazy load the view
require.ensure([], () => resolve(require('./views/messages.new.html')));
});
},
controller: 'MessagesNewController as vm',
resolve: {
loadMessagesNewController: ($q, $ocLazyLoad) => {
return $q((resolve) => {
require.ensure([], () => {
// load only controller module
let module = require('./controllers/messages.new.controller');
$ocLazyLoad.load({name: module.name});
resolve(module.controller);
})
});
}
}
});
}
export default angular
.module('messages.routing', [])
.config(messagesRouting);
Copier après la connexion

Méfiez-vous des dépendances en double

Jetons un coup d'œil au contenu de messages.all.controller et messages.new.controller.

// messages.all.controller.js
'use strict';
class MessagesAllController {
constructor(msgStore) {
this.msgs = msgStore.all();
}
}
export default angular
.module('messages.all.controller', [
require('commons/msg-store').name,
])
.controller('MessagesAllController', MessagesAllController);
// messages.all.controller.js
'use strict';
class MessagesNewController {
constructor(msgStore) {
this.text = '';
this._msgStore = msgStore;
}
create() {
this._msgStore.add(this.text);
this.text = '';
}
}
export default angular
.module('messages.new.controller', [
require('commons/msg-store').name,
])
.controller('MessagesNewController', MessagesNewController);
Copier après la connexion

La source de notre problème est require('commons/msg-store').name . Le service msgStore est nécessaire pour réaliser le partage de messages entre les contrôleurs. Ce service est présent dans les deux forfaits. Il y en a un dans messages.all.controller et un autre dans messages.new.controller. Désormais, il n’y a plus de place à l’optimisation. Comment le résoudre ? Ajoutez simplement msgStore en tant que dépendance du module d'application. Même si ce n’est pas parfait, dans la plupart des cas, cela suffit.

// app.js
'use strict';
export default require('angular')
.module('lazyApp', [
require('angular-ui-router'),
require('oclazyload'),
// msgStore as global dependency
require('commons/msg-store').name,
require('./pages/home/home.routing').name,
require('./pages/messages/messages.routing').name,
]);
Copier après la connexion

单元测试的技巧

把 msgStore 改成是全局依赖并不意味着你应该从控制器中删除它。如果你这样做了,在你编写测试的时候,如果没有模拟这一个依赖,那么它就无法正常工作了。因为在单元测试中,你只会加载这一个控制器而非整个应用模块。

// messages.all.controller.spec.js
'use strict';
describe('MessagesAllController', () => {
var controller,
msgStoreMock;
beforeEach(angular.mock.module(require('./messages.all.controller').name));
beforeEach(inject(($controller) => {
msgStoreMock = require('commons/msg-store/msg-store.service.mock');
spyOn(msgStoreMock, 'all').and.returnValue(['foo', ]);
controller = $controller('MessagesAllController', { msgStore: msgStoreMock });
}));
it('saves msgStore.all() in msgs', () => {
expect(msgStoreMock.all).toHaveBeenCalled();
expect(controller.msgs).toEqual(['foo', ]);
});
});
Copier après la connexion

以上内容是小编给大家分享的Webpack 实现 AngularJS 的延迟加载,希望对大家有所帮助!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!