Masukkan Password
83 Namespace & Modul ES6
Materi ini sedang masuk ke topik yang sangat penting ketika project TypeScript mulai membesar, yaitu bagaimana membagi kode ke banyak file agar kode tetap rapi dan mudah dirawat.
Inti besarnya adalah:
Jangan menaruh semua kode aplikasi di satu file. Pecah menjadi beberapa file yang masing-masing punya tanggung jawab tertentu, lalu hubungkan file-file tersebut menggunakan namespace atau ES6 modules.
Mari kita bahas dari dasar sampai alur kerjanya.
1. Masalah: Semua kode berada dalam satu file
Di awal belajar TypeScript, biasanya kita membuat sesuatu seperti:
src/
└── app.ts
Misalnya:
class User {
// ...
}
class Product {
// ...
}
function calculateTotal() {
// ...
}
function validateUser() {
// ...
}
Semua kode berada di app.ts.
Untuk project kecil, tidak masalah.
Misalnya aplikasi Expense Tracker yang dibuat di course hanya sekitar 99 baris:
app.ts
│
├── class Expense
├── function addExpense()
├── function deleteExpense()
├── function calculateTotal()
└── ...
Karena kodenya sedikit, masih mudah dibaca.
2. Tetapi bagaimana kalau aplikasinya besar?
Bayangkan aplikasi yang sebenarnya memiliki:
- login
- register
- user management
- product management
- shopping cart
- payment
- notification
- authentication
- database
- validation
- reporting
- dan sebagainya.
Kalau semuanya dimasukkan ke:
app.ts
bisa menjadi:
app.ts
│
├── User
├── Product
├── Cart
├── Payment
├── Authentication
├── Validation
├── Notification
├── Database
├── Report
├── ...
├── ...
├── ...
└── 10.000+ lines
Akhirnya satu file bisa menjadi ribuan atau bahkan puluhan ribu baris.
Ini menimbulkan beberapa masalah.
3. Masalah menggunakan satu file besar
A. Sulit dibaca
Bayangkan kamu membuka:
app.ts
dan isinya 10.000 baris.
Kamu ingin mencari kode yang berkaitan dengan User.
Kamu harus mencari-cari di antara ribuan baris.
B. Sulit dipelihara
Misalnya ada bug di sistem pembayaran.
Idealnya kita ingin mencari:
payment.ts
Tetapi kalau semua ada di:
app.ts
kita harus mencari di file yang sangat besar.
C. Tanggung jawab bercampur
Misalnya:
class User {
// user logic
}
function calculatePayment() {
// payment logic
}
function sendEmail() {
// email logic
}
function validateProduct() {
// product validation
}
Semuanya bercampur.
Padahal secara konsep mereka berbeda.
Lebih baik:
User → user.ts
Payment → payment.ts
Email → email.ts
Product → product.ts
4. Solusinya: Modular Code
Di sinilah muncul istilah:
Modular code
Modular code berarti kita memecah aplikasi menjadi bagian-bagian kecil yang disebut module.
Misalnya daripada:
app.ts
kita buat:
src/
├── user.ts
├── product.ts
├── payment.ts
├── validation.ts
└── app.ts
Sekarang masing-masing file punya tanggung jawab.
user.ts
↓
User-related code
product.ts
↓
Product-related code
payment.ts
↓
Payment-related code
validation.ts
↓
Validation-related code
app.ts
↓
Menggunakan semuanya
Ini membuat project jauh lebih mudah dikelola.
5. Analogi sederhana: Lemari
Bayangkan kamu punya banyak pakaian.
Cara pertama:
Semua pakaian dilempar ke satu lemari besar.
┌─────────────────────────┐
│ baju │
│ celana │
│ kaos kaki │
│ jaket │
│ sepatu │
│ dasi │
│ ... │
└─────────────────────────┘
Kalau mau mencari kaos kaki:
“Di mana ya?”
Harus bongkar semuanya. 😅
Cara kedua:
┌──────────────────┐
│ 👕 Baju │
├──────────────────┤
│ 👖 Celana │
├──────────────────┤
│ 🧦 Kaos kaki │
├──────────────────┤
│ 🧥 Jaket │
└──────────────────┘
Jauh lebih mudah.
File/module dalam programming kurang lebih seperti lemari-lemari tersebut.
6. Ada 3 cara mengorganisasi TypeScript ke banyak file
Lecture menjelaskan ada tiga pendekatan:
Cara 1 — Manual import JavaScript
Tidak direkomendasikan.
Cara 2 — Namespace
Pendekatan TypeScript.
Cara 3 — ES6 Modules
Pendekatan modern dan lebih direkomendasikan.
Mari kita lihat satu per satu.
7. Cara pertama: Import JavaScript secara manual
Misalnya kita punya:
src/
├── user.ts
├── product.ts
└── app.ts
Setelah compile TypeScript:
dist/
├── user.js
├── product.js
└── app.js
Artinya:
user.ts → user.js
product.ts → product.js
app.ts → app.js
Kemudian kita bisa memasukkan semuanya secara manual ke HTML:
<script src="user.js"></script>
<script src="product.js"></script>
<script src="app.js"></script>
Kelihatannya mudah.
Tapi ada masalah.
8. Masalah manual import
Kita harus mengatur sendiri urutannya.
Misalnya:
<script src="app.js"></script>
<script src="user.js"></script>
Padahal app.js membutuhkan sesuatu dari user.js.
Maka:
app.js
↓
membutuhkan user.js
tetapi browser menjalankan:
app.js
↓
baru user.js
Bisa terjadi error.
Jadi kita harus memastikan:
<script src="user.js"></script>
<script src="product.js"></script>
<script src="app.js"></script>
Urutannya harus benar.
9. Kenapa cara manual tidak bagus?
Karena semakin besar project:
user.js
product.js
payment.js
cart.js
validation.js
authentication.js
notification.js
database.js
...
HTML menjadi:
<script src="user.js"></script>
<script src="product.js"></script>
<script src="payment.js"></script>
<script src="cart.js"></script>
<script src="validation.js"></script>
<script src="authentication.js"></script>
<script src="notification.js"></script>
<script src="database.js"></script>
Kita harus mengelola semuanya secara manual.
Selain merepotkan, mudah terjadi kesalahan.
Karena itu lecture mengatakan:
Cara ini tidak direkomendasikan.
10. Cara kedua: Namespace
Pendekatan kedua adalah menggunakan:
Namespace
Namespace merupakan fitur TypeScript.
Tujuannya adalah membantu kita mengorganisasi kode yang berhubungan ke dalam sebuah namespace.
Misalnya kita memiliki:
user.ts
Kemudian:
namespace UserManagement {
export class User {
constructor(
public name: string
) {}
}
}
Di sini kita membuat namespace:
UserManagement
dan di dalamnya terdapat:
User
Secara konsep:
UserManagement
│
└── User
11. Kenapa menggunakan namespace?
Bayangkan kita memiliki banyak kode.
UserManagement
│
├── User
├── createUser()
├── deleteUser()
└── validateUser()
ProductManagement
│
├── Product
├── createProduct()
└── deleteProduct()
Kita mengelompokkan kode berdasarkan domain/tanggung jawabnya.
Jadi namespace seperti sebuah kotak/ruangan untuk mengelompokkan kode.
12. Hal penting: export dalam namespace
Misalnya:
namespace UserManagement {
export class User {
constructor(public name: string) {}
}
}
Kenapa ada:
export
?
Karena kita ingin sesuatu di dalam namespace dapat digunakan dari luar namespace.
Secara sederhana:
namespace
│
├── export User ← boleh digunakan dari luar
│
└── internalFunction ← tidak diekspos
Jadi export kurang lebih berarti:
“Bagian ini boleh digunakan oleh kode di luar.”
13. Bagaimana namespace bekerja saat compile?
Ini bagian yang sangat penting dari lecture.
Misalnya kita memiliki:
src/
├── user.ts
├── product.ts
└── app.ts
Ada beberapa TypeScript files.
Tetapi ketika menggunakan pendekatan namespace dan konfigurasi TypeScript yang sesuai, hasil akhirnya dapat digabung menjadi satu JavaScript file.
Misalnya:
src/
├── user.ts
├── product.ts
└── app.ts
menjadi:
dist/
└── bundle.js
Isi bundle.js secara konsep:
bundle.js
│
├── compiled user.ts
├── compiled product.ts
└── compiled app.ts
Jadi:
Banyak file TypeScript → satu file JavaScript hasil bundling.
14. Keuntungan pendekatan namespace
HTML cukup memiliki:
<script src="bundle.js"></script>
Bukan:
<script src="user.js"></script>
<script src="product.js"></script>
<script src="app.js"></script>
Jadi HTML menjadi lebih sederhana.
Banyak TS files
↓
TypeScript compiler
↓
bundle.js
↓
HTML
↓
<script src="bundle.js">
15. Tetapi ada pendekatan yang lebih modern
Lecture kemudian memperkenalkan:
ES6 Modules
Ini merupakan pendekatan yang lebih modern.
Yang menarik adalah:
ES6 Modules bukan fitur khusus TypeScript.
Ini adalah fitur JavaScript modern.
Karena TypeScript merupakan superset JavaScript, TypeScript juga dapat menggunakan:
import
export
16. Apa itu module?
Secara sederhana:
Sebuah file TypeScript/JavaScript dapat menjadi module yang mengekspor sesuatu dan module lain dapat mengimpornya.
Misalnya:
user.ts
berisi:
export class User {
constructor(public name: string) {}
}
Kemudian:
app.ts
bisa menggunakan:
import { User } from "./user";
Sekarang:
user.ts
│
│ export User
↓
app.ts
│
│ import User
↓
menggunakan User
Ini adalah konsep module.
17. Analogi module
Bayangkan sebuah restoran.
Ada beberapa bagian:
Kitchen
Payment
Customer
Order
Masing-masing punya tugas sendiri.
customer.ts
↓
mengurus Customer
order.ts
↓
mengurus Order
payment.ts
↓
mengurus Payment
Kalau order.ts membutuhkan Customer, dia bisa berkata:
import { Customer } from "./customer";
Artinya:
“Saya membutuhkan
Customerdari modulecustomer.”
Sedangkan customer.ts mengatakan:
export class Customer {}
Artinya:
“Saya menyediakan
Customeragar bisa digunakan module lain.”
18. Contoh sederhana ES6 Module
user.ts
export class User {
constructor(
public name: string,
public age: number
) {}
}
User diekspor.
Kemudian:
app.ts
import { User } from "./user";
const user = new User("John", 28);
console.log(user);
Hubungannya:
user.ts
│
│ export User
↓
app.ts
│
│ import User
↓
new User(...)
19. Apa yang terjadi setelah compile?
Misalnya:
src/
├── user.ts
└── app.ts
Setelah compile:
dist/
├── user.js
└── app.js
Jadi berbeda dengan namespace yang dibahas sebelumnya.
Pada ES6 module:
Setiap TypeScript file dapat menghasilkan JavaScript file sendiri.
20. Apakah semua .js harus dimasukkan ke HTML?
Nah, ini poin penting lecture.
Misalnya hasil compile:
dist/
├── user.js
├── product.js
├── payment.js
└── app.js
Kita tidak perlu melakukan:
<script src="user.js"></script>
<script src="product.js"></script>
<script src="payment.js"></script>
<script src="app.js"></script>
Kita cukup memasukkan entry point/main file:
<script type="module" src="app.js"></script>
Kemudian:
app.js
│
├── membutuhkan user.js
│
├── membutuhkan product.js
│
└── membutuhkan payment.js
Browser dapat memahami hubungan module tersebut.
21. Browser mengetahui dependency
Misalnya:
// app.ts
import { User } from "./user";
import { Product } from "./product";
Setelah compile:
app.js
│
├── import user.js
│
└── import product.js
Browser melihat:
app.js
↓
"oh, saya membutuhkan user.js"
↓
download user.js
dan:
app.js
↓
"oh, saya juga membutuhkan product.js"
↓
download product.js
Jadi kita tidak perlu mendaftarkan semua file secara manual di HTML.
22. Perbedaan namespace dan ES6 modules
Ini bagian yang sangat penting untuk diingat.
| Namespace | ES6 Modules |
|---|---|
| Fitur TypeScript | Fitur JavaScript modern |
| Khusus TypeScript | Bisa digunakan JavaScript & TypeScript |
| Mengorganisasi kode dengan namespace | Mengorganisasi kode dengan module |
| Bisa menghasilkan satu bundle | Biasanya menghasilkan beberapa JS files |
| HTML dapat memuat satu bundle | HTML cukup memuat entry point |
| Pendekatan lebih lama | Pendekatan lebih modern |
Secara sederhana:
Namespace
TypeScript-specific
↓
multiple .ts
↓
bundle
↓
single .js
Sedangkan:
ES6 Modules
JavaScript standard
↓
multiple .ts
↓
multiple .js
↓
app.js sebagai entry point
↓
browser memahami dependencies
23. Lalu apa masalah ES6 Modules?
Lecture menyebut salah satu kekurangannya adalah jumlah HTTP request.
Misalnya kita punya:
app.js
user.js
product.js
payment.js
cart.js
validation.js
Browser harus mendapatkan beberapa file.
Secara konsep:
Browser
│
├── request → app.js
├── request → user.js
├── request → product.js
├── request → payment.js
├── request → cart.js
└── request → validation.js
Semakin banyak file yang harus diambil, semakin banyak network request yang mungkin terjadi.
Untuk project besar, ini dapat memengaruhi performance.
24. Solusinya: Bundling
Di sinilah muncul istilah:
Bundling
Bundling berarti menggabungkan beberapa JavaScript files menjadi satu atau beberapa bundle yang lebih optimal.
Misalnya awalnya:
app.js
user.js
product.js
payment.js
cart.js
validation.js
Kemudian bundler menghasilkan:
bundle.js
yang secara konsep berisi kode dari berbagai module.
┌── user.js
├── product.js
├── payment.js
├── cart.js
└── validation.js
↓
Bundler
↓
bundle.js
25. Contoh bundler: Webpack
Lecture menyebut:
Webpack
Webpack adalah salah satu tool yang dapat digunakan untuk melakukan bundling.
Jadi kita memiliki:
TypeScript
↓
multiple modules
↓
Webpack
↓
bundle
Course akan membahas ini lebih lanjut di bagian berikutnya.
Untuk sekarang belum perlu terlalu memikirkan detail Webpack.
Cukup pahami:
Bundler = tool yang membantu menggabungkan dan mengoptimalkan berbagai module/file menjadi output yang lebih siap digunakan browser.
26. Gambaran besar semua pendekatan
Sekarang kita bisa membuat gambaran seperti ini.
Pendekatan 1 — Manual
user.ts
↓
user.js ──────┐
│
product.ts │
↓ │
product.js ───┼──→ HTML
│
app.ts │
↓ │
app.js ───────┘
HTML harus mengatur semuanya.
Pendekatan 2 — Namespace
user.ts ───────┐
product.ts ────┼──→ TypeScript
app.ts ────────┘
↓
bundle
↓
bundle.js
↓
HTML
HTML cukup:
<script src="bundle.js"></script>
Pendekatan 3 — ES6 Modules
user.ts ───→ user.js
product.ts ─→ product.js
app.ts ─────→ app.js
│
├── import user
└── import product
HTML cukup memasukkan:
<script type="module" src="app.js"></script>
Browser kemudian memahami dependency antar-module.
27. Analogi paling gampang
Bayangkan kamu menulis buku.
Cara 1: Semua dalam satu file
BUKU.txt
Bab 1
Bab 2
Bab 3
Bab 4
Bab 5
...
Bab 100
Susah dikelola.
Cara 2: Pisahkan bab
chapter1.ts
chapter2.ts
chapter3.ts
chapter4.ts
Ini lebih rapi.
Namespace
Semua chapter kemudian dikumpulkan menjadi:
book.js
chapter1 ─┐
chapter2 ─┤
chapter3 ─┼──→ book.js
chapter4 ─┘
ES6 Modules
Masing-masing tetap menjadi file sendiri:
chapter1.js
chapter2.js
chapter3.js
chapter4.js
Tetapi chapter utama mengetahui chapter lain yang dibutuhkan melalui:
import ...
Browser mengikuti dependency tersebut.
28. Kenapa modular code sangat penting?
Tujuan sebenarnya bukan sekadar:
“Supaya file lebih sedikit.”
Justru kebalikannya.
Kita memiliki banyak file, tetapi setiap file menjadi kecil dan fokus.
Misalnya:
src/
│
├── models/
│ ├── user.ts
│ ├── product.ts
│ └── order.ts
│
├── services/
│ ├── user-service.ts
│ ├── payment-service.ts
│ └── order-service.ts
│
├── utils/
│ ├── validation.ts
│ └── formatting.ts
│
└── app.ts
Setiap bagian punya tanggung jawab yang jelas.
Ini membuat:
- readability meningkat
- maintainability meningkat
- debugging lebih mudah
- kerja tim lebih mudah
- code reuse lebih mudah
- dependency lebih jelas
- project lebih scalable
29. Konsep penting: Import dan Export
Kalau kamu hanya ingin mengingat dua keyword dari materi ini, ingat:
export
dan
import
export
Artinya:
“Saya menyediakan sesuatu dari file/module ini.”
Contoh:
export class User {}
import
Artinya:
“Saya ingin menggunakan sesuatu dari module lain.”
Contoh:
import { User } from "./user";
Jadi hubungan sederhananya:
user.ts
│
│ export
↓
User
│
│ import
↓
app.ts
30. Jangan bingung antara TypeScript dan JavaScript
Lecture memberikan poin yang sangat penting.
Namespace
namespace
adalah konsep/f fitur TypeScript.
JavaScript modern tidak menggunakan namespace TypeScript dengan cara yang sama.
ES6 Modules
import
export
adalah fitur JavaScript modern.
Karena TypeScript mendukung syntax JavaScript tersebut, kita bisa menulis:
import
export
di TypeScript.
Jadi:
ES6 Module
↓
JavaScript feature
↓
bisa digunakan TypeScript
31. Satu hal yang perlu diluruskan tentang “compile”
Lecture kadang menggunakan bahasa sederhana seperti:
“TypeScript compile menjadi JavaScript.”
Itu benar secara umum.
Tetapi dalam pembahasan module, ada dua proses berbeda yang perlu kamu bedakan:
1. Compile / transpile
TypeScript → JavaScript
2. Bundle
Banyak JavaScript/module → bundle
Contohnya:
user.ts
product.ts
app.ts
│
│ TypeScript compiler
↓
user.js
product.js
app.js
Kemudian jika menggunakan bundler:
user.js
product.js
app.js
│
│ bundler
↓
bundle.js
Jadi compile dan bundle bukan hal yang sama.
32. Alur lengkap yang perlu kamu pahami
Untuk ES6 Modules:
SOURCE CODE
│
┌──────────┼──────────┐
↓ ↓ ↓
user.ts product.ts app.ts
│ │ │
└──────────┼──────────┘
↓
TypeScript compiler
↓
┌──────────┼──────────┐
↓ ↓ ↓
user.js product.js app.js
│
│ import
↓
browser memahami
dependencies
│
↓
aplikasi berjalan
Kalau menggunakan bundler:
TS files
↓
compile
↓
JS modules
↓
Webpack / bundler
↓
bundle.js
↓
Browser
33. Apa yang sebenarnya sedang dipelajari di section ini?
Jangan terlalu fokus dulu pada syntax.
Tujuan utama section ini adalah memahami:
Bagaimana aplikasi TypeScript yang besar dipecah menjadi banyak bagian dan bagaimana bagian-bagian tersebut saling berkomunikasi.
Konsepnya:
LARGE APPLICATION
│
↓
Pecah menjadi modules
│
┌──────────┼──────────┐
↓ ↓ ↓
User Product Payment
│ │ │
└──────────┼──────────┘
↓
import / export
↓
application berjalan
34. Ringkasan perbandingan
| Pendekatan | Output | HTML | Catatan |
|---|---|---|---|
| Semua kode satu file | 1 JS | 1 script | Cocok project kecil |
| Manual JS import | Banyak JS | Banyak <script> | Merepotkan |
| Namespace | Banyak TS → bundle JS | 1 script | Pendekatan TypeScript lama |
| ES6 Modules | Banyak TS → banyak JS | Entry point saja | Modern |
| ES6 Modules + Bundler | Banyak TS → bundle | Bundle/entry output | Bisa dioptimalkan |
35. Mental model yang paling penting 🧠
Bayangkan seperti ini:
PROJECT BESAR
│
↓
Tidak mungkin nyaman kalau semua kode
ada dalam satu file
│
↓
PECAH MENJADI MODULE
│
├──────────────┐
↓ ↓
namespace ES6 module
│ │
│ └── import/export
│
└── namespace
│
↓
bundle
Dan untuk ES6:
export
↓
"Ini saya sediakan"
import
↓
"Ini yang saya butuhkan"
36. Hafalan super singkat
Kalau besok ditanya materi lecture ini, kamu bisa mengingat:
Project kecil → satu file masih oke.
Project besar → gunakan modular code.
Modular code → pecah kode menjadi banyak file/module.
Ada tiga pendekatan:
1. Manual JS import
❌ tidak direkomendasikan
2. Namespace
✔ fitur TypeScript
✔ bisa menghasilkan satu bundle
3. ES6 Modules
✔ fitur JavaScript modern
✔ menggunakan import/export
✔ browser memahami dependency
✔ pendekatan modern
Dan:
Compile ≠ Bundle
Compile:
.ts → .js
Bundle:
banyak .js → bundle.js
Sedangkan inti import/export:
File A
│
│ export
↓
sesuatu
│
│ import
↓
File B
Jadi sebenarnya lecture ini sedang membuka pintu menuju konsep yang sangat penting dalam development modern: module system, dependency, entry point, dan bundling. Di lecture berikutnya ketika mulai praktik namespace, konsep-konsep di atas akan terasa jauh lebih masuk akal karena kamu sudah tahu mengapa kita membutuhkan namespace dan masalah apa yang sedang coba diselesaikan.