Angular 2 z Webpackiem dla mnie to wciąż wielka zmora. Na każdej stronie jest masa poradników, tutoriali ale niestety tak wiele z nich wymaga już troszkę większej wiedzy od osób (node, npm, …). A w tym momencie nie dość, że ja tej wiedzy nie posiadam, to jeszcze próbuję to złączyć z Electronem! Zapraszam do lektury i przejscia ze mną tej przygody.
“Szybki” start z Angularem 2
Na szczęście to jest najprostsza ścieżka. A przynajmniej tak mi się w tym momencie wydaje. Pamiętajcie, że piszę bloga zgodnie z zasadą live blogging. Czyli to co Wam opisuję jednocześnie robię :). Dlatego jeśli będą komplikacje po drodze - to dopiero na koniec tego posta zapewne będzie na repo najaktualniejszy i działający kod. Po pierwsze do dependencies w pliku packages.json dorzucam angulara:
"@angular/common": "^2.4.9",
"@angular/compiler": "^2.4.9",
"@angular/core": "^2.4.9",
"@angular/forms": "^2.4.9",
"@angular/http": "^2.4.9",
"@angular/platform-browser": "^2.4.9",
"@angular/platform-browser-dynamic": "^2.4.9",
"@angular/router": "^3.4.9",
a potem znana już nam metoda w command line:
npm install
Ha!. Zainstalowane. I to było to co najprostsze :) Było szybko? Było. Problem, że to jedynie instalacja. :( Ale cóż. Czas przejść dalej.
Moduł aplikacji
Na początek postępuję z instrukcją przygotowania środowiska wg strony angulara2. Jedynym wyjątkiem jest to, że robimy to pod Webpacka. Ale wszystko zróbmy krok po kroku.
Po pierwsze jak w ostatnim wpisie wspomniałem po zalogowaniu/przejsciu ekranu logowania przenosimy się do nowego okna. Te okno buduję w tym momencie w inny sposób niż ekran logowania. Ale to też dlatego, że chcę to zrobić w pełni poprawnie (a przynajmniej tak myślę). Najpierw bootstrap aplikacji:
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
Jak widzicie zaimportowaliśmy tutaj też nowy moduł (app.module). Nazwa modułu związana jest aktualnie z nazwą pliku, który nazywa się app.module.ts a jego zawartość to:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Tutaj ponownie widzimy, że dodaję jako deklarację AppComponent i jest on jednocześnie komponentem rozruchowym (właściwość bootstrap). A oto jak wygląda komponent:
import { Component } from '@angular/core';
@Component({
selector: 'app',
template: `<h1>Hello </h1>`
})
export class AppComponent {
name = 'World';
}
No cóż. Szału nie ma :) Póki co to komponent jest całkiem czysty i nie zawiera żadnych wodotrysków. Teraz wystarczy go wykorzystać w pliku index.html:
<app>Loading awesome MassCo app...</app>
Powyższy TAG dodajemy do body. Ten tekst ładujący dodajemy głównie po to aby podczas rozruchu aplikacji wyświetlił się jakiś tekst. Aczkolwiek aplikacja teraz jest tak lekka i mała, że po prostu nie zauważymy tego tekstu.
Konfiguracja webpacka
W tym momencie aby to wszystko jeszcze zadziałało trzeba tylko skonfigurować webpacka. Lekko zmodyfikowałem wartości we właściwości entry:
entry: {
'login': './login/login',
'login-vendor': './login/vendor',
'app-polyfills': './app/polyfills',
'app-vendor': './app/vendor',
'app': './app/app',
}
A takze wartości plugins (usunięte elementy):
plugins: [
new CommonsChunkPlugin({ name: 'common', filename: 'common.js' })
]
W sumie nic nadzwyczajnego. Co do pierwszej zmiany. Wynikała ona z tego, ze chciałem powydzielać importy zewnętrzych modułów poza konfigurację webpacka. Polyfills i vendor to dwa plii (polyfills.ts i vendor.ts), których zawartość odpowiednio to:
import 'zone.js/dist/zone';
import 'reflect-metadata';
if (process.env.ENV === 'production') {
// Production
} else {
// Development and test
Error['stackTraceLimit'] = Infinity;
require('zone.js/dist/long-stack-trace-zone');
}
// RxJS
import 'rxjs';
// Angular
import '@angular/platform-browser';
import '@angular/platform-browser-dynamic';
import '@angular/core';
import '@angular/common';
import '@angular/http';
import '@angular/router';
Natomiast co do drugiej zmiany. Sam jej nie rozumiem jeszcze, dlatego nie wytłumaczę teraz :(. Może ktoś mógłby mi podpowiedzieć w ogóle co ona oznacza? Będę wdzięczny :)
watch, start … zwiększenie produktywności
Nie wiem, czy już o tym pisałem ale zawsze warto powtórzyć. Do pliku packages.json dodałem ostatnio wpis w części związanej ze skryptami:
"watch": "webpack --watch --progress --profile --colors --display-error-details --display-cached"
Dzięki takiemu zabiegowi mozemy teraz uruchomić webpacka w trybie watch, czyli natychmiastowy rebuild po wykryciu zmian w plikach (nie wszystkich - angularowych). ALE. okazuje się, że nie mozemy wtedy uruchomić electrona z jednej konsoli bo webpack wciąż nasłuchuje. Oczywiście są dwie opcje. Można łączyć komendy i zrobić dwie operacja na raz. A druga opcja to uruchomić dwie konsole. A tam gdzie dwoje się bije trzeci korzysta.
Jeśli korzystacie z Visual Studio Code tak jak ja to jest trzecia opcja. Terminal. Uruchamiamy ją za pomocą skrótu Ctrl+`. Plusem jest to, że uruchamia się ona odrazu w kontekście projektu, w którym piszemy. Druga fajna opcja to możliwość uruchmiania kilku terminali (Ctrl+Shift+`). I to jest właśnie najciekawsze. Bo możemy w jednym z nich uruchomić webpacka w trybie watch, w drugim uruchomić electrona i cieszyć się szybszymi zmianami. Po każdym zapisie i przebuildowaniu przez webpacka jedyne co musimy to w okienku aplikacji wykonać skrót Ctrl+R. I mozemy cieszyć się szybkimi zmianami. To jest też wielka zaleta samego pisania aplikacji desktopowych w tej technologii.