Masukkan Password
91 Menambahkan Dukungan TypeScript ke Webpack
Lecture ini adalah bagian yang sangat penting, karena di sini Webpack akhirnya benar-benar dikonfigurasi untuk:
- membaca file TypeScript,
- menggunakan
ts-loader, - mencari module
.tsdan.js, - membuat source map untuk debugging,
- melakukan build dengan command
npm run build, - dan menghasilkan
bundle.js.
Kalau lecture sebelumnya baru menyiapkan “alat-alatnya”, lecture ini mulai menjalankan mesinnya.
1. Gambaran besar dulu
Sebelumnya kita punya banyak file:
src/
├── app.ts
├── models/
│ └── user.ts
└── user-utils/
└── user-action.ts
Sekarang kita ingin:
app.ts
│
↓
Webpack
│
┌─────┴─────┐
↓ ↓
ts-loader dependency
│ │
↓ ↓
TypeScript user.ts
│
└─────┬─────┘
↓
bundle.js
↓
dist/
Jadi hasil akhirnya:
dist/
└── bundle.js
Dan browser akan menjalankan:
bundle.js
bukan lagi app.js.
2. Ada beberapa konfigurasi penting dalam lecture ini
Kita akan membahas:
1. module.rules
2. test
3. use
4. exclude
5. resolve.extensions
6. sourceMap
7. devtool
8. npm run build
9. hasil bundle.js
Ini cukup banyak, tetapi sebenarnya semuanya saling berhubungan.
3. module.rules: memberi tahu Webpack cara menangani file
Di webpack.config.js, kita menambahkan:
module: {
rules: [
...
]
}
Pertanyaan sederhananya:
“Webpack, kalau kamu menemukan sebuah file, kamu harus melakukan apa terhadap file tersebut?”
Jawabannya ditentukan oleh rules.
4. Kenapa namanya rules?
Karena kita bisa membuat banyak aturan.
Misalnya project besar memiliki:
.ts
.css
.scss
.png
.svg
.json
Kita bisa mengatakan:
Kalau .ts → gunakan ts-loader
Kalau .css → gunakan CSS loader
Kalau .scss → gunakan Sass loader
Kalau gambar → gunakan image handling tertentu
Jadi:
module
└── rules
├── rule untuk TypeScript
├── rule untuk CSS
├── rule untuk image
└── ...
Dalam project lecture ini kita baru membutuhkan satu rule, yaitu untuk TypeScript.
5. Rule pertama: test
Kita membuat rule kira-kira seperti:
{
test: /\.ts$/,
use: "ts-loader",
exclude: /node_modules/
}
Mari kita pecah.
Pertama:
test: /\.ts$/
Artinya:
“Periksa file yang ditemukan. Apakah file tersebut merupakan file
.ts?”
6. Apa itu /\.ts$/?
Ini adalah regular expression (regex).
Memang terlihat menyeramkan untuk pemula:
/\.ts$/
Tapi sebenarnya kita bisa membacanya bagian demi bagian.
/ ... /
Bagian ini menandai bahwa kita sedang menulis regex.
/regex/
\.
Tanda titik dalam regex memiliki arti khusus.
Kalau kita ingin mencari titik literal, kita menggunakan:
\.
Jadi:
\.ts
berarti:
.ts
ts
Artinya memang karakter:
ts
$
$ berarti:
harus berada di akhir string/file name
Jadi:
/\.ts$/
kurang lebih berarti:
“Cari file yang namanya berakhir dengan
.ts.”
7. Contoh test
Dengan:
test: /\.ts$/
maka:
app.ts ✅
user.ts ✅
user-action.ts ✅
Sedangkan:
app.js ❌
style.css ❌
image.png ❌
Jadi rule ini hanya berlaku untuk TypeScript files.
8. Kenapa kita membutuhkan test?
Karena Webpack bisa menemukan banyak jenis file.
Misalnya:
app.ts
style.css
logo.png
data.json
Kita tidak mau mengatakan:
“Gunakan
ts-loaderuntuk semuanya.”
Karena ts-loader hanya untuk TypeScript.
Jadi:
test
↓
file ini tipe apa?
↓
.ts?
↓
kalau iya → gunakan ts-loader
9. use: "ts-loader"
Setelah Webpack menemukan .ts, kita perlu memberitahu:
“Gunakan apa untuk memprosesnya?”
Jawabannya:
use: "ts-loader"
Jadi:
file .ts
↓
test: /\.ts$/
↓
cocok
↓
use: ts-loader
↓
ts-loader memproses TypeScript
10. Hubungan Webpack dan ts-loader
Ini inti dari lecture.
Ingat:
Webpack sendiri bukan TypeScript compiler.
Webpack adalah bundler.
Jadi kita membutuhkan ts-loader untuk membantu Webpack menangani TypeScript.
Diagramnya:
Webpack
│
↓
menemukan app.ts
│
↓
test: /\.ts$/
│
↓
cocok!
│
↓
ts-loader
│
↓
TypeScript compiler
│
↓
JavaScript
│
↓
Webpack
│
↓
bundle.js
11. ts-loader juga membaca tsconfig.json
Lecture mengatakan bahwa ts-loader akan memperhatikan:
tsconfig.json
Jadi konfigurasi TypeScript kita tetap berguna.
Misalnya:
{
"compilerOptions": {
"target": "es2015",
"module": "es2015",
"sourceMap": true
}
}
ts-loader akan menggunakan konfigurasi TypeScript tersebut saat memproses file .ts.
Jadi hubungan keduanya:
webpack.config.js
│
↓
ts-loader
│
↓
tsconfig.json
│
↓
TypeScript compiler
12. exclude: /node_modules/
Kemudian lecture menambahkan:
exclude: /node_modules/
Artinya:
Jangan jalankan rule TypeScript ini terhadap file yang berada di
node_modules.
Kenapa?
Karena node_modules berisi dependency pihak ketiga.
Misalnya:
node_modules/
├── webpack/
├── typescript/
├── ts-loader/
├── ...
Kita tidak ingin Webpack mengambil semua source dependency tersebut lalu mencoba meng-compile semuanya sebagai bagian dari aplikasi kita.
13. Kenapa node_modules harus dikecualikan?
Bayangkan project kita:
src/
├── app.ts
└── user.ts
node_modules/
├── webpack/
├── typescript/
├── ts-loader/
├── package-a/
├── package-b/
└── ...
Kita hanya ingin:
src/*.ts
diproses.
Bukan:
node_modules/**/*.ts
Jadi:
exclude: /node_modules/
berarti:
“Webpack, jangan terapkan rule ini ke dependency di
node_modules.”
14. Jadi rule lengkapnya
Secara konsep:
module: {
rules: [
{
test: /\.ts$/,
use: "ts-loader",
exclude: /node_modules/
}
]
}
Bacanya:
“Kalau kamu menemukan file
.ts, gunakants-loaderuntuk memprosesnya, kecuali file tersebut berada dinode_modules.”
Ini cara paling mudah untuk memahami rule tersebut.
15. Sekarang masalah baru: extension .ts
Ingat lecture sebelumnya?
Kita mengubah:
import User from "../models/user.js";
menjadi:
import User from "../models/user";
Dan:
import { createUser }
from "./user-utils/user-action";
Kenapa?
Karena kita ingin Webpack mencari file TypeScript juga.
16. resolve.extensions
Untuk itu kita menggunakan:
resolve: {
extensions: [".ts", ".js"]
}
Ini memberitahu Webpack:
“Kalau ada import tanpa extension, coba cari file
.tsdan.js.”
17. Contoh sederhana
Kita memiliki:
user-action.ts
Tetapi di app.ts kita menulis:
import { createUser } from "./user-action";
Webpack akan mencoba mencari berdasarkan:
extensions: [".ts", ".js"]
Sehingga secara konsep:
./user-action
│
├── coba ./user-action.ts
│
└── coba ./user-action.js
Ketika menemukan:
user-action.ts
Webpack menggunakannya.
18. Kenapa .js juga tetap dimasukkan?
Karena project tidak harus hanya berisi TypeScript.
Bisa saja ada:
helper.ts
some-library.js
Jadi kita mengatakan:
extensions: [".ts", ".js"]
Artinya:
“Webpack boleh menyelesaikan import ke
.tsmaupun.js.”
19. Kesalahan yang terjadi di lecture
Lecture sempat menulis resolve dengan bentuk yang salah.
Awalnya kurang lebih:
resolve: [".ts", ".js"]
Kemudian Webpack menghasilkan error:
configuration.resolve should be an object
Kenapa?
Karena resolve harus berupa object, bukan array.
Yang benar:
resolve: {
extensions: [".ts", ".js"]
}
Ini contoh error konfigurasi yang sangat bagus untuk dipahami.
20. Bedakan resolve dan extensions
Strukturnya:
resolve
└── extensions
├── .ts
└── .js
Jadi:
resolve: {
extensions: [".ts", ".js"]
}
Bukan:
resolve: [".ts", ".js"] // ❌
Karena:
resolve = object
extensions = array
21. Sekarang kita masuk ke Source Map
Lecture kemudian membuka:
tsconfig.json
dan mencari:
"sourceMap": true
Ini digunakan untuk debugging.
22. Apa itu source map?
Ini konsep yang sangat penting.
Browser sebenarnya menjalankan:
bundle.js
Tetapi kita menulis kode:
app.ts
user.ts
user-action.ts
Kalau terjadi error, kita ingin browser menunjukkan:
“Error-nya ada di
app.tsbaris 10.”
Bukan:
“Error ada di
bundle.jsbaris 1.384.”
Nah, source map membantu menghubungkan:
JavaScript hasil build
↕
source code asli
TypeScript
23. Analogi source map
Bayangkan kamu menerjemahkan buku:
Bahasa Indonesia
↓
Bahasa Jepang
Jika ada kesalahan di hasil terjemahan pada halaman 500, kamu ingin tahu:
“Kalimat asli di buku Indonesia yang menyebabkan ini bagian mana?”
Source map seperti peta penghubung antara:
hasil compile
dengan:
source code asli
24. Mengaktifkan source map di TypeScript
Di tsconfig.json:
{
"compilerOptions": {
"sourceMap": true
}
}
Artinya:
“Buat informasi source map ketika TypeScript diproses.”
25. Tapi kenapa belum cukup?
Lecture mengatakan:
hanya mengaktifkan
sourceMap: truebelum cukup.
Webpack juga perlu diberi tahu bagaimana source map digunakan.
Untuk itu:
devtool: "inline-source-map"
26. Apa fungsi devtool?
devtool adalah konfigurasi Webpack yang menentukan bagaimana source map/debugging ditangani.
Lecture menggunakan:
devtool: "inline-source-map"
Jadi konsepnya:
tsconfig.json
sourceMap: true
↓
buat mapping source
webpack.config.js
devtool: "inline-source-map"
↓
Webpack menggunakan mapping tersebut
↓
browser debugging lebih mudah
27. Kenapa ini sangat berguna?
Tanpa source map:
Browser
↓
bundle.js
↓
Error
↓
"bundle.js:1"
Susah dibaca.
Dengan source map:
Browser
↓
bundle.js
↓
source map
↓
app.ts / user.ts
↓
baris kode asli
Jauh lebih mudah debugging.
28. Sekarang konfigurasi Webpack kita mulai lengkap
Secara konsep, file kita menjadi seperti:
const path = require("path");
module.exports = {
entry: "./src/app.ts",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "dist")
},
module: {
rules: [
{
test: /\.ts$/,
use: "ts-loader",
exclude: /node_modules/
}
]
},
resolve: {
extensions: [".ts", ".js"]
},
devtool: "inline-source-map"
};
Ini adalah mental model konfigurasi yang sedang dibuat di lecture.
29. Mari kita baca konfigurasi itu seperti manusia
Daripada menghafalkan syntax, baca seperti kalimat:
Webpack,
1. Mulai dari:
src/app.ts
2. Hasilnya:
dist/bundle.js
3. Kalau menemukan:
file .ts
maka:
gunakan ts-loader
4. Jangan proses:
node_modules
5. Kalau ada import tanpa extension:
coba .ts dan .js
6. Aktifkan source map:
supaya debugging mudah.
Kalau kamu bisa membaca konfigurasi seperti ini, kamu sudah memahami konsepnya.
30. Sekarang bagaimana cara menjalankan Webpack?
Kita masuk ke:
package.json
Sebelumnya kita punya:
"scripts": {
}
Kemudian kita tambahkan:
"scripts": {
"build": "webpack"
}
31. Apa itu scripts?
npm memungkinkan kita membuat command sendiri di:
"scripts"
Misalnya:
"scripts": {
"build": "webpack"
}
Sekarang kita bisa menjalankan:
npm run build
npm akan melihat:
build
↓
webpack
Jadi:
npm run build
sebenarnya menjalankan:
webpack
32. Kenapa tidak langsung mengetik webpack?
Bisa saja dalam kondisi tertentu.
Tetapi menggunakan npm script memiliki keuntungan.
Misalnya project memiliki:
"scripts": {
"build": "webpack",
"start": "...",
"test": "..."
}
Developer cukup mengetahui command standar:
npm run build
npm run start
npm test
Dan project menyimpan command tersebut di package.json.
33. Ini juga berkaitan dengan local dependency
Ingat kita meng-install Webpack secara lokal:
node_modules/webpack
Ketika kita menjalankan:
npm run build
npm akan menggunakan executable dari dependency project tersebut.
Jadi kita tidak perlu bergantung pada Webpack global.
Ini adalah salah satu alasan penting menggunakan npm scripts.
34. Sebelum build
Lecture menghapus isi folder:
dist/
Misalnya sebelumnya:
dist/
├── app.js
├── models/
│ └── user.js
└── user-utils/
└── user-action.js
Kemudian dikosongkan:
dist/
Kenapa?
Supaya kita bisa melihat hasil build Webpack dengan jelas.
35. Menjalankan npm run build
Sekarang:
npm run build
Alurnya:
npm run build
↓
scripts.build
↓
webpack
↓
webpack.config.js
↓
entry = src/app.ts
↓
Webpack mengikuti import
↓
.ts ditemukan
↓
ts-loader
↓
TypeScript → JavaScript
↓
Webpack bundling
↓
dist/bundle.js
36. Hasil akhirnya
Setelah berhasil:
dist/
└── bundle.js
Ini sangat penting.
Sebelumnya kita memiliki banyak output .js.
Sekarang:
src/
├── app.ts
├── user.ts
└── user-action.ts
↓ Webpack
dist/
└── bundle.js
Itulah tujuan utama bundling.
37. Kenapa hanya ada bundle.js?
Karena Webpack membaca dependency graph.
Misalnya:
app.ts
│
↓
user-action.ts
│
↓
user.ts
Webpack mengumpulkan code yang diperlukan:
app
+
user-action
+
user
dan mengemasnya menjadi:
bundle.js
38. Browser sekarang harus menjalankan bundle.js
Sebelumnya index.html mungkin memiliki:
<script type="module" src="app.js"></script>
Tetapi sekarang kita tidak lagi punya output:
app.js
Kita punya:
bundle.js
Jadi harus diubah menjadi:
<script type="module" src="dist/bundle.js"></script>
atau sesuai struktur folder project lecture.
Intinya:
HTML harus menunjuk ke file hasil build Webpack.
39. Kenapa browser tidak lagi menjalankan app.js?
Karena app.js sebagai output terpisah tidak lagi menjadi hasil build utama.
Sekarang:
app.ts
↓
Webpack
↓
bundle.js
Jadi browser menjalankan:
bundle.js
40. Apa yang terjadi dengan console.log?
Lecture melihat output dari:
console.log(...)
yang berasal dari file-file source.
Misalnya user.ts memiliki:
console.log("user JS file executed");
Setelah bundling:
user.ts
↓
ts-loader
↓
JavaScript
↓
Webpack
↓
bundle.js
console.log tersebut tetap ada dalam bundle.
Ketika browser menjalankan:
bundle.js
console tetap muncul.
41. Tentang debugger yang menyebabkan reload terus
Lecture menemukan debugger di browser.
Misalnya ada:
debugger;
Ketika browser menjalankan kode itu, browser akan pause di debugger.
Akibatnya terlihat seperti aplikasi terus berhenti/reload.
Setelah debugger dilepas dan menekan:
Continue
aplikasi kembali berjalan normal.
Jadi ini bukan error Webpack.
Ini adalah:
debugger statement
yang memang sengaja menghentikan eksekusi JavaScript.
42. Perhatikan perubahan tanggung jawab
Ini adalah salah satu hal terpenting dari seluruh seri lecture Webpack.
Sebelumnya
tsc
↓
compile TypeScript
↓
JavaScript files
↓
browser
Sekarang
Webpack
│
├── ts-loader
│ ↓
│ compile TypeScript
│
├── dependency resolution
│
├── bundling
│
└── output
↓
bundle.js
↓
browser
Jadi Webpack sekarang menjadi pusat proses build.
43. Kenapa kita tidak lagi menggunakan tsc --watch?
Karena nanti Webpack Dev Server akan mengambil alih development workflow.
Sebelumnya:
tsc --watch
↓
compile TS
Sekarang:
Webpack Dev Server
↓
Webpack
↓
ts-loader
↓
compile TS
↓
bundle
↓
update browser
Itulah yang akan dibahas di lecture berikutnya.
44. Semua konfigurasi yang dibuat dalam lecture
Sekarang mari kita rangkum file per file.
A. tsconfig.json
Kita mengatur:
target
module
sourceMap
Contoh konsep:
{
"compilerOptions": {
"target": "es2015",
"module": "es2015",
"sourceMap": true
}
}
Tujuannya:
TypeScript
↓
JavaScript ES2015
+
source map
B. webpack.config.js
Kita mengatur:
entry
output
module.rules
resolve.extensions
devtool
C. package.json
Kita menambahkan:
"scripts": {
"build": "webpack"
}
45. Hubungan ketiga file tersebut
Ini diagram yang sangat bagus untuk diingat:
package.json
│
↓
npm run build
│
↓
Webpack
│
↓
webpack.config.js
│
┌──────────────┼──────────────┐
↓ ↓ ↓
entry rules resolve
│ │ │
↓ ↓ ↓
app.ts ts-loader .ts/.js
│
↓
tsconfig.json
│
┌──────┴──────┐
↓ ↓
target sourceMap
│ │
└──────┬──────┘
↓
JavaScript
↓
bundle.js
46. Error yang muncul tadi sebenarnya mengajarkan sesuatu
Webpack memberikan:
configuration.resolve should be an object
Jangan hanya melihat error sebagai sesuatu yang buruk.
Error ini memberi tahu kita bentuk data yang diharapkan.
Webpack menginginkan:
resolve: {
extensions: [...]
}
bukan:
resolve: [...]
Ini pola yang akan sering kamu temui ketika bekerja dengan configuration tools:
Configuration harus mengikuti schema yang sudah ditentukan tool.
47. Bedakan module di tsconfig dan module di Webpack
Ini juga sangat penting karena namanya sama.
Kita punya:
tsconfig.json
"module": "es2015"
Ini adalah compiler option TypeScript.
Artinya berkaitan dengan sistem module JavaScript yang dihasilkan TypeScript.
webpack.config.js
module: {
rules: [...]
}
Ini adalah configuration property milik Webpack.
Artinya:
“Bagaimana Webpack memproses module/file yang ditemukannya?”
Jadi meskipun namanya sama:
module
konteksnya berbeda.
tsconfig.module
↓
TypeScript module system
webpack.module
↓
Webpack module processing/rules
Jangan sampai tertukar.
48. Bagian rules bisa diperluas di project nyata
Sekarang kita hanya punya:
rules: [
{
test: /\.ts$/,
use: "ts-loader",
exclude: /node_modules/
}
]
Tetapi nanti project kompleks bisa punya:
rules: [
{
test: /\.ts$/,
use: "ts-loader",
exclude: /node_modules/
},
// rule CSS
// rule images
// rule fonts
// rule lainnya
]
Jadi rules merupakan tempat kita memberi tahu Webpack:
“Kalau menemukan tipe file tertentu, perlakukan dengan cara tertentu.”
49. Mental model test → use → exclude
Ini bagus untuk dihafalkan:
test
↓
"File apa ini?"
use
↓
"Kalau cocok, pakai apa?"
exclude
↓
"File mana yang jangan diproses?"
Contoh:
{
test: /\.ts$/,
use: "ts-loader",
exclude: /node_modules/
}
Dibaca:
“Kalau file berakhiran
.ts, gunakants-loader, kecuali file itu berasal darinode_modules.”
50. Mental model entry → resolve → loader → output
Ini bahkan lebih penting:
ENTRY
↓
Mulai dari mana?
↓
src/app.ts
RESOLVE
↓
Cari dependency dengan extension apa?
↓
.ts / .js
LOADER
↓
Kalau .ts, diproses bagaimana?
↓
ts-loader
OUTPUT
↓
Hasil disimpan di mana?
↓
dist/bundle.js
Ini adalah jantung konfigurasi Webpack.
51. Ringkasan keseluruhan lecture
Lecture ini melakukan workflow:
1. tsconfig.json
↓
target = ES2015
module = ES2015
sourceMap = true
2. webpack.config.js
↓
entry = ./src/app.ts
↓
output = dist/bundle.js
↓
.ts → ts-loader
↓
exclude node_modules
↓
resolve .ts dan .js
↓
devtool = inline-source-map
3. package.json
↓
"build": "webpack"
4. Jalankan
↓
npm run build
5. Hasil
↓
dist/bundle.js
6. index.html
↓
gunakan bundle.js
52. Yang perlu kamu pahami vs yang tidak perlu dihafal
🟢 Wajib paham
entry= titik awaloutput= hasil buildrules= aturan pemrosesan filetest= file apa yang cocok dengan ruleuse= loader yang digunakanexclude= file/folder yang dikecualikanresolve.extensions= extension yang boleh dicarits-loader= membantu Webpack memproses TypeScriptsourceMap+devtool= membantu debuggingnpm run build= menjalankan Webpack melalui npm script
🟡 Tidak perlu langsung hafal
Regex:
/\.ts$/
Cukup pahami bahwa itu berarti:
“file yang berakhiran
.ts.”
Dan syntax:
path.resolve(__dirname, "dist")
cukup pahami sebagai:
“absolute path menuju folder
dist.”
53. Gambaran akhir yang harus ada di kepala kamu 🧠
Bayangkan Webpack sebagai manager pabrik.
src/app.ts
│
↓
┌─────────┐
│ Webpack │
└────┬────┘
│
"Saya mulai dari sini"
│
↓
entry
│
↓
menemukan file .ts
│
↓
test: /\.ts$/
│
↓
ts-loader
│
↓
TypeScript → JavaScript
│
↓
ikuti semua import
│
↓
bundling
│
↓
dist/bundle.js
│
↓
Browser
Dan sourceMap adalah peta yang membantu browser mengatakan:
"Kode yang sedang berjalan di bundle.js
sebenarnya berasal dari app.ts baris sekian."
🎯 Inti lecture dalam satu kalimat:
Lecture ini mengajarkan Webpack bagaimana memproses file TypeScript menggunakan
ts-loader, bagaimana mencari dependency.ts/.js, bagaimana membuat source map untuk debugging, lalu bagaimana menjalankan proses tersebut dengannpm run buildhingga seluruh project TypeScript dibundle menjadidist/bundle.js.
Dan setelah lecture ini, satu hal besar yang belum dibahas adalah bagaimana membuat Webpack Dev Server supaya kita tidak perlu melakukan npm run build secara manual setiap kali mengubah kode. Itu yang menjadi langkah berikutnya.