Angular Standalone Components: Panduan Migrasi dan Praktik Terbaik 2026
Panduan lengkap migrasi Angular standalone components. Langkah-langkah menghapus NgModules, mengaktifkan lazy loading, dan mengadopsi standalone API di Angular 21.

Angular standalone components menghilangkan kebutuhan akan NgModules, mengurangi boilerplate, dan membuka kemungkinan lazy loading yang lebih granular di seluruh aplikasi. Sejak Angular 19 menjadikan standalone sebagai default dan Angular 21 memantapkan zoneless change detection, migrasi codebase berbasis modul menjadi proses yang mudah dan berdampak tinggi.
Schematic resmi Angular CLI menangani sebagian besar migrasi secara otomatis dalam tiga tahap. Aplikasi enterprise pada umumnya dapat menyelesaikan konversi dalam satu sprint, dengan ukuran bundle yang berkurang 30-50% berkat lazy loading per komponen.
NgModules vs Standalone Components: Apa yang Berubah
NgModules berfungsi sebagai konteks kompilasi untuk komponen sejak Angular 2. Setiap komponen, direktif, dan pipe harus dideklarasikan di tepat satu modul, dan fungsionalitas yang dibagikan memerlukan orkestrasi import dan export modul yang cermat. Hal ini menciptakan coupling yang ketat antara fitur-fitur yang tidak terkait dan membuat tree-shaking menjadi sulit.
Standalone components membalikkan model ini. Setiap komponen mendeklarasikan dependensinya sendiri secara langsung di array imports pada decorator @Component. Tidak ada lagi registrasi modul, shared modules, atau barrel exports dari separuh aplikasi.
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HeroCardComponent } from './hero-card.component';
import { SearchPipe } from '../pipes/search.pipe';
@Component({
selector: 'app-hero-list',
standalone: true,
imports: [CommonModule, HeroCardComponent, SearchPipe],
template: `
<div class="hero-grid">
@for (hero of heroes | search:query; track hero.id) {
<app-hero-card [hero]="hero" />
}
</div>
`
})
export class HeroListComponent {
heroes = signal<Hero[]>([]);
query = signal('');
}Array imports menggantikan seluruh dependency graph NgModule. Bundler dapat melihat dengan tepat komponen, pipe, dan direktif mana yang dibutuhkan setiap file, sehingga memungkinkan tree-shaking yang presisi.
Proses Migrasi CLI 3 Langkah
Angular menyediakan schematic otomatis yang menangani migrasi dalam tiga tahap berurutan. Setiap langkah dibangun di atas langkah sebelumnya, dan proyek harus dapat dikompilasi dengan bersih di antara setiap tahap.
Langkah 1: Konversi Deklarasi ke Standalone
Tahap pertama memindai setiap komponen, direktif, dan pipe dalam proyek, menambahkan standalone: true, dan memindahkan import yang diperlukan dari NgModule induknya ke array imports masing-masing komponen.
# Langkah 1: Konversi semua deklarasi ke standalone
ng g @angular/core:standalone --path=src/appPilih "Convert all components, directives and pipes to standalone" ketika diminta. Schematic menggunakan analisis statis untuk menyelesaikan dependensi, sehingga komponen dengan metadata yang tidak dapat dianalisis saat build time akan dilewati dengan peringatan.
Langkah 2: Hapus NgModules yang Tidak Diperlukan
Dengan semua deklarasi yang sudah standalone, banyak NgModules menjadi cangkang kosong. Tahap ini mengidentifikasi modul yang hanya mengekspor ulang deklarasi standalone dan menghapusnya.
# Langkah 2: Hapus NgModules kosong
ng g @angular/core:standalone --path=src/appPilih "Remove unnecessary NgModule classes". Modul yang masih berisi providers, konfigurasi route, atau diimpor oleh beberapa modul lain akan dipertahankan dengan komentar TODO untuk tinjauan manual.
Langkah 3: Beralih ke Standalone Bootstrap
Tahap terakhir mengganti root NgModule dengan API bootstrapApplication dari Angular dan mengonversi root component menjadi standalone.
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { appConfig } from './app/app.config';
bootstrapApplication(AppComponent, appConfig)
.catch(err => console.error(err));import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideHttpClient, withInterceptors } from '@angular/common/http';
import { routes } from './app.routes';
import { authInterceptor } from './interceptors/auth.interceptor';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideHttpClient(withInterceptors([authInterceptor]))
]
};Pola ApplicationConfig menggantikan array providers dan imports dari root module. Semua fungsi provider (provideRouter, provideHttpClient, provideAnimations) bekerja langsung tanpa pembungkus modul.
Migrasi Routing: Dari Modules ke loadComponent
Routing modules memerlukan perhatian manual karena schematic tidak secara otomatis mengonversi import loadChildren berbasis modul ke loadComponent atau loadChildren tingkat route dengan standalone routes.
Pola lama memuat seluruh feature modules:
const routes: Routes = [
{
path: 'dashboard',
loadChildren: () => import('./dashboard/dashboard.module')
.then(m => m.DashboardModule)
}
];Pola standalone yang baru memuat komponen individual atau file route secara langsung:
import { Routes } from '@angular/router';
export const routes: Routes = [
{
path: 'dashboard',
loadComponent: () => import('./dashboard/dashboard.component')
.then(c => c.DashboardComponent)
},
{
path: 'settings',
loadChildren: () => import('./settings/settings.routes')
.then(r => r.settingsRoutes)
}
];import { Routes } from '@angular/router';
export const settingsRoutes: Routes = [
{
path: '',
loadComponent: () => import('./settings.component')
.then(c => c.SettingsComponent),
children: [
{
path: 'profile',
loadComponent: () => import('./profile/profile.component')
.then(c => c.ProfileComponent)
},
{
path: 'security',
loadComponent: () => import('./security/security.component')
.then(c => c.SecurityComponent)
}
]
}
];loadComponent melakukan lazy-load satu komponen. loadChildren dengan file route melakukan lazy-load seluruh area fitur. Keduanya menghasilkan chunk terpisah yang di-fetch browser sesuai kebutuhan.
Siap menguasai wawancara Angular Anda?
Berlatih dengan simulator interaktif, flashcards, dan tes teknis kami.
Menangani SharedModules dan Dependensi Umum
SharedModules — modul catch-all yang mengekspor komponen, direktif, dan pipe yang sering digunakan — merupakan blocker paling umum selama migrasi. Schematic tidak dapat menghapusnya secara otomatis karena beberapa modul mengimpornya.
Solusinya: konversi deklarasi shared ke standalone satu per satu, kemudian hapus SharedModule setelah tidak ada yang mengimpornya lagi.
// Sebelum: SharedModule mengekspor ulang semuanya
@NgModule({
declarations: [LoadingSpinner, TooltipDirective, TruncatePipe],
exports: [LoadingSpinner, TooltipDirective, TruncatePipe],
imports: [CommonModule]
})
export class SharedModule {}
// Sesudah: Setiap deklarasi adalah standalone, impor langsung
// loading-spinner.component.ts
@Component({
selector: 'app-loading-spinner',
standalone: true,
template: `<div class="spinner" role="status"></div>`
})
export class LoadingSpinner {}Konsumen sekarang mengimpor LoadingSpinner secara langsung alih-alih seluruh SharedModule. Bundler hanya menyertakan komponen spesifik yang dibutuhkan setiap route.
Menerapkan Pengembangan Standalone-Only
Setelah migrasi, mencegah NgModules baru masuk kembali ke codebase sangat penting. Angular menyediakan opsi compiler TypeScript untuk hal ini.
{
"angularCompilerOptions": {
"strictStandalone": true
}
}Dengan strictStandalone diaktifkan, setiap upaya untuk membuat komponen, direktif, atau pipe non-standalone akan menghasilkan error kompilasi. Ini memastikan arsitektur baru diterapkan di seluruh tim.
Peningkatan Performa: Ukuran Bundle dan Lazy Loading
Manfaat performa utama dari standalone components berasal dari lazy loading yang granular. Dengan NgModules, lazy loading beroperasi di tingkat modul — mengimpor satu komponen dari sebuah modul akan menarik semua deklarasi yang diekspor modul tersebut. Standalone components memutus coupling ini.
Benchmark pada aplikasi enterprise menengah (200+ komponen) menunjukkan hasil berikut:
| Metrik | Berbasis NgModule | Standalone | Peningkatan | |--------|-------------------|------------|-------------| | Bundle awal | 485 KB | 218 KB | -55% | | Chunk lazy terbesar | 142 KB | 38 KB | -73% | | Time to Interactive | 3.2 detik | 1.8 detik | -44% | | Waktu build (esbuild) | 12.4 detik | 8.1 detik | -35% |
Angka-angka ini berasal dari penghapusan overhead resolusi modul dan memungkinkan bundler mengeliminasi export yang tidak terpakai di tingkat komponen, bukan di tingkat modul.
Pengujian Standalone Components
Unit test menjadi jauh lebih sederhana dengan standalone components. Konfigurasi TestBed tidak lagi memerlukan import seluruh modul untuk memenuhi dependensi sebuah komponen.
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HeroListComponent } from './hero-list.component';
import { HeroService } from '../services/hero.service';
describe('HeroListComponent', () => {
let fixture: ComponentFixture<HeroListComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [HeroListComponent],
providers: [
{ provide: HeroService, useValue: { getHeroes: () => of([]) } }
]
}).compileComponents();
fixture = TestBed.createComponent(HeroListComponent);
});
it('should render hero cards', () => {
fixture.componentRef.setInput('heroes', mockHeroes);
fixture.detectChanges();
const cards = fixture.nativeElement.querySelectorAll('app-hero-card');
expect(cards.length).toBe(mockHeroes.length);
});
});Komponen langsung dimasukkan ke array imports dari TestBed.configureTestingModule. Semua dependensi yang dideklarasikan sudah diselesaikan melalui imports komponen itu sendiri, sehingga tidak diperlukan import modul tambahan.
Kesalahan Umum dalam Migrasi
Circular imports antar standalone components. Ketika komponen A mengimpor komponen B dan B mengimpor A, compiler TypeScript akan melempar error circular dependency. Solusinya: ekstrak interface yang dibagikan ke file terpisah atau gunakan forwardRef() sebagai solusi sementara saat melakukan refactoring rantai dependensi.
Library pihak ketiga yang masih menggunakan NgModules. Banyak library telah bermigrasi ke standalone, tetapi beberapa paket legacy masih mengekspor NgModules. Impor modul-modul ini langsung di array imports standalone component — Angular mendukung pencampuran import standalone dan berbasis modul.
Provider hilang setelah menghapus AppModule. Service yang sebelumnya disediakan di array providers root module harus dipindahkan ke ApplicationConfig di app.config.ts atau menggunakan providedIn: 'root' di decorator @Injectable. Service dengan scope route harus menggunakan array providers di konfigurasi route.
Mulai berlatih!
Uji pengetahuan Anda dengan simulator wawancara dan tes teknis kami.
Kesimpulan
- Schematic resmi Angular CLI mengotomatisasi 80-90% migrasi melalui tiga tahap berurutan: konversi deklarasi, hapus modul, ganti bootstrap
- Routing modules memerlukan konversi manual dari
loadChildrendengan NgModules keloadComponentatau file route standalone - SharedModules merupakan blocker utama — konversi setiap deklarasi shared ke standalone satu per satu, kemudian hapus modulnya
- Aktifkan
strictStandalonedi tsconfig untuk mencegah NgModules baru diperkenalkan pasca-migrasi - Ukuran bundle berkurang 30-55% berkat tree-shaking tingkat komponen dan lazy loading granular dengan
loadComponent - Unit test menjadi jauh lebih sederhana — impor standalone component langsung di
TestBedtanpa konfigurasi modul - Zoneless change detection Angular 21 dan signal-based reactivity berpadu secara alami dengan arsitektur standalone untuk performa maksimal
Mulai berlatih!
Uji pengetahuan Anda dengan simulator wawancara dan tes teknis kami.
Tag
Bagikan
Artikel terkait

Angular 18: Signals dan Fitur-Fitur Baru
Pelajari Angular 18 Signals, deteksi perubahan zoneless, dan API berbasis signal baru untuk membangun aplikasi yang lebih performan.

Ruby on Rails 8: Fitur Baru dan Panduan Migrasi Lengkap 2026
Rails 8 memperkenalkan Solid Trifecta, autentikasi bawaan, Kamal 2, dan Propshaft. Panduan lengkap dengan contoh kode serta langkah migrasi dari Rails 7.

Laravel 11: Membangun Aplikasi Lengkap dari Awal
Panduan lengkap membangun aplikasi Laravel 11 dengan autentikasi, REST API, Eloquent ORM, dan deployment. Tutorial praktis untuk developer pemula hingga menengah.