Webpack и LazyLoad модули Angular
После выхода на свет версии Angular RC5 у роутера появилась возможность lazy подгрузки. Что позволяет загружать части приложения по востребованию, тоесть модули подгружаются после перехода по определенным маршрутам. Что существенно сокращает время загрузки и более равномерно распределяет время отклика.
Для этого нужно, всего лишь, задать поле loadChildren
у роута, и далее Angular будет сам извлекать модуль, по этому пути, и загружать в конфигурацию роутера.
//app.routing.ts
@NgModule({
declarations: [ AppComponent, HomeComponent ],
bootstrap: [ AppComponent ],
imports: [
RouterModule.forRoot([
{ path: 'home', component: HomeComponent },
{ path: 'lazy', loadChildren: './my-lazy-module#LazyModule' }
])
})
export class RoutingModule {}
Не забывайте указывать название импортируемого модуля, после хештега.
И все это конечно хорошо до тех пор, пока мы не начнем собирать webpack’ом. После попытки загрузить страничку появятся бесконечные ошибки о том, что не удалось загрузить тот или иной модуль.
Для того, чтобы webpack инжектил модули установим пакет angular2-router-loader
и добавим в webpack конфиг
//webpack.common.js
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var helpers = require('./helpers');
module.exports = {
module: {
loaders: [
{
test: /\.ts$/,
loaders: ['angular2-router-loader?loader=require']
}
....
}
Параметр loader указывает на то, какой загрузчик будет использоваться для разделения кода (system/require). В нашем случае это require.
Он заменит наш путь до модуля на следующий код:
//app.routing.js
{
path: 'lazy',
loadChildren: () => new Promise(function (resolve) {
(require as any).ensure([], function (require: any) {
resolve(require('./lazy/lazy.module')['LazyModule']);
});
})
}
При помощи require.ensure
webpack собирает эти модули по отдельным файлам называемые chunk’ами.
Если же и после этих действий ошибки не пропали, то обратите внимание на пути к модулям, они должны быть относительными.
Также стоит обратить еще на одну важную вещь. К примеру, если компилируем gulp’ом и собираем при помощи SystmJs для dev, а на продакшн собираем webpack’ом, то велика вероятность получить некорректно собранный код и получать те же самые ошибки. Дело в том, что webpack может использовать уже собранные .js файлы (которые могут быть не трансформированы для его целей). Выход из этой ситуации прост - почистить директорию с .ts исходниками от .js.
К примеру gulp таской:
//gulpfile.js
gulp.task('clean-src', function() {
return del([
paths.tsOutput + '/**/*.js',
paths.tsOutput + '/**/*.js.map',
'app.js',
'vendor.js',
'polyfills.js',
'*.chunk.js']);
});
P.S.
Кроме того, ошибки об отсутствующих файлах могут быть не только для модулей, а также для темплейтов и стилей. Для их загрузки, опять же, необходимо указывать относительные пути, и, в конфигурации webpack, добавить в поле loaders ‘awesome-typescript-loader’ и ‘angular2-template-loader’ (перед этим следует установить пакеты)