Я предполагаю, что у вас есть проект Angular (версии 2 или 4), созданный с помощью Angular CLI 1.0 или выше.
Посмотреть полный проект вы можете здесь - https://github.com/sani-banani/angular4-starter
Причины перехода с Angular CLI на Webpack:
- Более настраиваемый (загрузчики, плагины,…).
- И больше гибкости для различных конфигураций (локальная, разработка, производство).
0. Предварительные шаги:
0,1. Создание и обслуживание проекта Angular с помощью Angular CLI (версия 1.2.6).
ng new angular4-starter cd angular4-starter ng serve
Дополнительные инструкции Angular CLI находятся здесь.
0.2. Внесите некоторые изменения в CSS и добавьте шрифты и изображения.
ng build -prod
1. Извлеките файл webpack.
Начиная с Angular CLI v1.0, есть функция «извлечения», которая позволяет извлекать файл конфигурации веб-пакета и манипулировать им по своему усмотрению.
- Запустите
ng eject
, чтобы интерфейс командной строки Angular сгенерировал файл webpack.config.js. - Запустите
npm install
, чтобы новые зависимости, сгенерированные CLI, были удовлетворены
Итак, у нас есть "ejected": true
in .angular-cli.json, новый файл - webpack.config.js и измененные скрипты запуска в package.json.
2. Преобразуйте результат некрасивого конфига webpack
Выполните рефакторинг уродливой конфигурации и сделайте конфигурации для локальных, разработки и производства с помощью WebpackMerge.
Если мы добавим "ejected": false
в .angular-cli.json, мы также можем использовать команду ng.
Что мы видим? У нас есть более мелкие активы с веб-пакетом, чем с командой ng build -prod
.
3. Другие производственные решения:
3.1. Сервер Node JS
Если мы используем сжатие с помощью node js, у нас будет больше ресурсов меньшего размера:
server.js
const compression = require('compression'); const express = require('express'); const app = express(); app.set('port', (process.env.PORT || 8081)); // Gzip app.use(compression()); // Run the app by serving the static files // in the dist directory app.use('/', express.static(__dirname + '/dist')); // Start the app by listening on the default port app.listen(app.get('port'), function() { console.log('Angular4 Starter App listening on port ' + app.get('port')); });
3.2. Ленивый модуль
Причины: для лучшей загрузки https://github.com/mgechev/angular-performance-checklist#lazy-loading-of-resources
Файловая структура модуля администрирования представлена ниже.
администрирование-routing.module.ts
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { AdministrationComponent } from './administration.component'; import { UserListComponent } from './user-list/user-list.component'; import { UserInfoComponent } from './user-info/user-info.component'; const routes: Routes = [ { path: '', component: AdministrationComponent }, children: [ { path: 'user-list/:page', component: UserListComponent }, { path: 'user-list', redirectTo: 'user-list/0' }, { path: 'user-info/:id', component: UserInfoComponent }, { path: '', redirectTo: 'user-list/0' }, ] } ]; @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) export class AdministrationRoutingModule { }
app-routing.module.ts
{ path: 'administration', loadChildren: './+administration/administration.module#AdministrationModule' },
3.2. Общий модуль для AppModule и LazyModule
Модуль с общими сервисами и компонентами:
import { NgModule } from '@angular/core'; import { CommonModule } from "@angular/common"; import { FormsModule } from '@angular/forms'; import { MyDatePickerModule } from 'mydatepicker'; import { SelectModule } from 'angular2-select'; import { Tab, Tabs } from '../tabs/tabs'; import { Countries } from './dictionary/countries'; @NgModule({ imports: [ CommonModule, FormsModule, MyDatePickerModule, SelectModule, ], exports: [ CommonModule, FormsModule, MyDatePickerModule, SelectModule, Tab, Tabs ], declarations: [ Tab, Tabs ], providers: [ Countries ], }) export class SharedModule {}
app.module.ts
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppRoutingModule } from './app-routing.module'; import { HttpModule } from '@angular/http'; import { LightboxModule } from 'angular2-lightbox'; import { SharedModule } from './shared/shared.module'; import { BackendService } from './shared/service/backend.service'; import { ApiService } from './shared/service/api.service'; import { AppComponent } from './app.component'; import { PageNotFoundComponent } from './page-not-found/page-not-found.component'; import { RegistrationComponent } from './registration/registration.component'; import { HomeComponent } from './home/home.component'; import { SuccessComponent } from './success/success.component'; import { FilesComponent } from './files/files.component'; import { BreadcrumbComponent } from './breadcrumb/breadcrumb.component'; import { ParticipantsComponent } from './participants/participants.component'; import { VisaComponent } from './visa/visa.component'; import { ProgramComponent } from './program/program.component'; import { FoodComponent } from './food/food.component'; import { PlaceComponent } from './place/place.component'; import { ContactsComponent } from './contacts/contacts.component'; import { DirectionsComponent } from './directions/directions.component'; import { CultureComponent } from './culture/culture.component'; import { UnderConstructionComponent } from './under-construction/under-construction.component'; @NgModule({ declarations: [ AppComponent, PageNotFoundComponent, RegistrationComponent, HomeComponent, SuccessComponent, FilesComponent, BreadcrumbComponent, ParticipantsComponent, VisaComponent, ProgramComponent, FoodComponent, PlaceComponent, ContactsComponent, DirectionsComponent, CultureComponent, UnderConstructionComponent ], imports: [ AppRoutingModule, BrowserModule, HttpModule, LightboxModule, SharedModule, ], providers: [ ApiService, BackendService ], bootstrap: [ AppComponent ] }) export class AppModule { }
administrator.module.ts
import { NgModule } from '@angular/core'; import { SharedModule } from '../shared/shared.module'; import { AdministrationRoutingModule } from './administration-routing.module'; import { AdministrationComponent } from './administration.component'; import { UserListComponent } from './user-list/user-list.component'; import { UserInfoComponent } from './user-info/user-info.component'; @NgModule({ imports: [ AdministrationRoutingModule, SharedModule, ], exports: [], declarations: [ AdministrationComponent, UserInfoComponent, UserListComponent, ], providers: [], }) export class AdministrationModule { }
3.3. Поддержка статики и Node.js
1) Используйте маршрутизацию hash-urls (#) как для статического, так и для серверного режима.
@NgModule({ imports: [ RouterModule.forRoot(routes, { useHash: true }) ], exports: [ RouterModule ] })
2) Используйте ‹base href =” ./ ”›
3.4. Прокси
Избежать проблем cors при локальной разработке просто. Давайте посмотрим на примеры ниже для angular-cli и webpack.
1) Angular CLI: создайте proxy.conf.json для проксирования запросов.
{ "/backend": { "target": "http://amazon.com", "secure": false } }
И запускаем его:
ng serve --environment local --proxy-config proxy.conf.json --host 0.0.0.0 --port 8080
2) Webpack: измените конфигурацию webpack.local.js для локальной разработки.
const proxyConf = require('../proxy.conf.json'); devServer: { historyApiFallback: true, stats: 'minimal', proxy: proxyConf }