Ini adalah artikel lanjutan dari Aplikasi seluler hibrid: berbagi logika antara aplikasi Angular2 dan Ionic2. Pada tahun 2016, ini adalah upaya pertama kami untuk berbagi logika bisnis berbasis Ngrx antara aplikasi Angular2 dan aplikasi seluler Ionic2, tetapi menggunakan npm link “hack” yang cukup tidak stabil, dengan tiga proyek TypeScript npm yang terpisah.

Dengan CLI terbaru Angular8 dan Ionic4, kini ada cara yang lebih elegan untuk mencapai hal ini, berkat struktur proyek mono-repo.

Tujuannya tetap sama:

  • meringkas semua logika bisnis (berdasarkan @ngrx/store) dalam modul inti, dan
  • menjaga tata letak tampilan tertentu, markup, dan logika navigasi dalam proyek aplikasi seluler dan web.

Catatan: @ngrx/store adalah manajemen status yang didukung RxJS yang terinspirasi oleh aplikasi Redux untuk Angular. Saat ini merupakan cara paling populer untuk menyusun logika bisnis yang kompleks di aplikasi Angular.

Aplikasi demo dan repo Github

Berikut adalah repo bukti konsep kami:



Repo menggunakan struktur mono-repo Nx Workspace (dengan integrasi Ionic khusus yang dirinci nanti):

  • /, root proyek berdasarkan Angular (versi 8.1.2) dan @ngrx/store (versi 8.1.0), dikelola oleh Angular CLI
  • /libs/core,modul bersama dengan logika status, reduksi, dan tindakan,
  • /apps/web, aplikasi web
  • /apps/mobile, aplikasi seluler, berdasarkan Ionic (versi 4.7.1), dikelola oleh Ionic CLI

Untuk demonya, kami menggunakan kode contoh counter (tindakan dan reduksi) dari @ngrx/store.

Modul inti menyediakan:

  • Antarmuka CounterState, model counter state
  • peredam counterReducer, manajemen status counter berdasarkan tindakan yang dikirim,
  • Tindakan balasan Menambah, mengurangi, dan mengatur ulang

Di aplikasi seluler atau web, kami menggunakan aset tersebut untuk membangun model status aplikasi.

import {CounterState} from ‘@ngrx-demo/core’;
export interface AppState {
  counter: CounterState,
  // Add other states here
}

Dan, berikan tindakan, layanan, dan reduksi selama bootstrap aplikasi.

import {ActionReducerMap} from '@ngrx/store';
import {counterReducer} from '@ngrx-demo/core';
import {AppState} from './app.state';
const reducers: ActionReducerMap<AppState> = {
    counter: counterReducer
};
@NgModule({
  imports: [
    BrowserModule,
    StoreModule.forRoot(reducers)
  ]
  bootstrap: [
    AppComponent
  ],
  declarations: [
    AppComponent
  ],
  
})
export class AppModule { }

Sekarang kita dapat menggunakan aset tersebut di komponen tampilan mana pun pada aplikasi.

// HTML component template
<h2>
  {{counter$ | async}}
</h2>
<p>
  <button (click)=”increment()”> +1 </button>
  <button (click)=”decrement()”> -1 </button>
</p>
<p>
  <button (click)=”reset()”> Reset </button>
</p>

Dengan komponen yang sesuai:

// Typescript angular component
import {CounterActions} from '@ngrx-demo/core';
import {AppState} from './app.state';
@Component({
  templateUrl: 'some.component.html'
})
export class SomeComponent {
  counter$: Observable<number>;
  constructor(private store: Store<AppState>) {
    this.counter$ = this.store.select(s => s.counter.total);
  }
  decrement() {
    this.store.dispatch(new CounterActions.DecrementAction());
  }
  increment() {
    this.store.dispatch(new CounterActions.IncrementAction());
  }
  reset() {
    this.store.dispatch(new CounterActions.ResetAction());
  }
}

Semua logika bisnis dikemas sepenuhnya dalam modul bersama. Misalnya, kita dapat menambahkan @ngrx/effects ke dalam campuran, untuk menangani panggilan asinkron API.

Tampilan hanya “mengetahui” tentang tindakan yang tersedia untuk dikirim dan model status yang dapat digunakannya.

Integrasi aplikasi ionik ke dalam Nx Workspace

Secara default, Nx Workspaces tidak mendukung aplikasi Ionic. Karena Ionic menggunakan CLI dan dependensinya sendiri untuk membuat, menguji, dan menjalankan aplikasi, /app/mobile memiliki /app/mobile/package.json sendiri (yang independen dari ruang kerja utama /package.json), sehingga menjadi /app/mobile/node_modules miliknya sendiri.

Konfigurasi khusus ionik

Di package.json, Ionic menyediakan beberapa hook untuk menyesuaikan konfigurasi default. Kami menggunakan opsi konfigurasi ionic_watch dan ionic_webpack serta 2 file konfigurasi khusus yang disimpan di /app/mobile/config.

// app/mobile/package.json
{
  ...
  "description": “An Ionic project”,
  "config": {
    "ionic_watch": "./config/watch.config.js",
    "ionic_webpack": "./config/webpack.config.js"
   },
  ...
}

Resolusi modul skrip ketikan

Agar dapat menggunakan modul bersama dan mendapatkan resolusi modul TypeScript yang benar, kami menggunakan properti pemetaan jalur khusus di /app/mobile/tsconfig.json. Di aplikasi kami, kami menggunakan @ngrx-demo, namun Anda dapat menggunakan @local misalnya.

// app/mobile/tsconfig.json
{
 "compilerOptions": {
 ...
   "baseUrl": ".",
   "paths": {
     "@ngrx-demo/*": ["../../libs/*"]
   }
 ...
}

Dan plugin webpack jalur TSConfig di konfigurasi Webpack khusus kami, sehingga Webpack mengetahui pemetaan jalur khusus tersebut.

// app/mobile/config/webpack.config.js
const TsconfigPathsPlugin = require(‘tsconfig-paths-webpack-plugin’);
const resolveConfig = {
 extensions: [‘.ts’, ‘.js’, ‘.json’],
 modules: [path.resolve(‘node_modules’)],
 plugins: [
   new TsconfigPathsPlugin({})
 ]
};
// Default config update
const webpackConfig = require(‘../node_modules/@ionic/app-scripts/config/webpack.config’); 
webpackConfig.dev.resolve = resolveConfig;
webpackConfig.prod.resolve = resolveConfig;

Isi ulang langsung

Senang rasanya bisa memanfaatkan live reload selama pengembangan: saat menjalankan ionic serve, jika file diperbarui di /libs/*, perubahan akan terdeteksi dan aplikasi seluler secara otomatis dimuat ulang di browser Anda. Kami menggunakan konfigurasi jam tangan khusus untuk itu:

// app/mobile/config/watch.config.js
// Default config update
const watchConfig = require(‘../node_modules/@ionic/app-scripts/config/watch.config’);
watchConfig.srcFiles.paths = [
 ‘{{SRC}}/**/*.(ts|html|s(c|a)ss)’,
 ‘../../libs/**/*.(ts|html|s(c|a)ss)’
];

Alat Pengembang Toko Ngrx

Dan yang terakhir, selama pengembangan, Alat Pengembang Ngrx Store adalah suatu keharusan untuk men-debug aplikasi Anda, tetapi harus dinonaktifkan di lingkungan produksi. Kami menggunakan pemetaan jalur @app/env khusus untuk itu (untuk meniru variabel lingkungan di aplikasi Angular), berkat https://github.com/gshigeto/ionic-environment-variables.

// app/mobile/tsconfig.json
{
 "compilerOptions": {
 ...
    "baseUrl": ".",
    "paths": {
      "@app/env": ["src/environments/environment"],
      "@ngrx-demo/*": ["../../libs/*"] 
    }
 ...
}

Dengan pemetaan alias di konfigurasi Webpack khusus kami.

// app/mobile/config/webpack/config.json
...
webpackConfig.dev.resolve.alias = {
 "@app/env": path.resolve('../src/environments/environment.ts')
};
webpackConfig.prod.resolve.alias = {
 "@app/env": path.resolve('../src/environments/environment.prod.ts')
};

Kemudian, kita cukup mengimpor variabel lingkungan di aplikasi Ionic kita!

import {StoreModule} from '@ngrx/store';
import {StoreDevtoolsModule} from '@ngrx/store-devtools';
...
import {environment} from '@app/env';
@NgModule({
  ...
  imports: [
    BrowserModule,
    IonicModule.forRoot(AppComponent),
    DemoCoreModule,
    StoreModule.forRoot(reducers),
    EffectsModule.forRoot([]),
    !environment.production ? StoreDevtoolsModule.instrument({maxAge: 25}) : []
  ],
  ...
})
export class AppModule { }

Keunggulan ruang kerja dan mono-repo

Itu dia! Seperti yang Anda lihat, struktur proyek baru ini jauh lebih bersih daripada solusi awal tahun 2016.

Ini mendapat manfaat dari semua keuntungan yang dijelaskan dalam dokumentasi Nx, Mengapa Ruang Kerja (kecuali untuk manajemen ketergantungan terpadu karena aplikasi Ionic memerlukan ketergantungannya sendiri):

Versi terpadu

Segala sesuatu di komitmen saat ini bekerja bersama

Label atau cabang dapat menangkap hal yang sama

Mempromosikan berbagi kode dan penggunaan kembali

Mudah untuk membagi kode menjadi modul lib

Mudah untuk menggunakan/menerapkan kode tersebut dan perubahan terbarunya

Manfaat pemfaktoran ulang

Editor kode dan IDE sadar akan “ruang kerja”.

Dapat memiliki satu komit untuk refactor yang mencakup aplikasi di domain

Pengalaman pengembang yang konsisten

Memastikan semua kode dependen yang diperlukan tersedia

Jika Anda memiliki pertanyaan atau saran untuk meningkatkan aplikasi demo, jangan ragu untuk mengirimkan masalah atau permintaan penarikan!

Catatan:kami sedang membuka lowongan! Apakah Anda pengembang fullstack atau front-end keren yang ingin bekerja di Angular, Java, atau Groovy? Anda harus menghubungi saya untuk bergabung dengan tim impian kami di Paris!

Jika Anda menyukai artikel ini, silakan tekan tombol ❤ untuk merekomendasikannya. Hal ini akan memudahkan pengguna Medium lainnya untuk menemukan hal ini.