Я предполагаю, что у вас есть проект Angular (версии 2 или 4), созданный с помощью Angular CLI 1.0 или выше.

Посмотреть полный проект вы можете здесь - https://github.com/sani-banani/angular4-starter

Причины перехода с Angular CLI на Webpack:

  1. Более настраиваемый (загрузчики, плагины,…).
  2. И больше гибкости для различных конфигураций (локальная, разработка, производство).

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, есть функция «извлечения», которая позволяет извлекать файл конфигурации веб-пакета и манипулировать им по своему усмотрению.

  1. Запустите ng eject, чтобы интерфейс командной строки Angular сгенерировал файл webpack.config.js.
  2. Запустите npm install, чтобы новые зависимости, сгенерированные CLI, были удовлетворены

Итак, у нас есть "ejected": truein .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
}