BelajarKoding Logobelajarkoding

Platform belajar web development Indonesia. Artikel, cheat sheets, roadmap, dan code challenges untuk developer Indonesia.

Navigasi

  • Artikel
  • Cheat Sheets
  • Roadmap
  • Challenges
  • Pricing
  • Search

Produk Lain

  • JagoHermes
  • KelasClaude
  • KilatKoding
  • BelajarVibeCoding
  • JualanKoding

Support

  • Privacy Policy
  • Terms of Service
  • Email

© 2026 BelajarKoding. All rights reserved.

Galih PratamaBagian dari ekosistem Galih Pratama
belajarkoding LogobyGalih Pratama
RoadmapArtikelCheat SheetsChallengesUpgrade
belajarkoding LogobyGalih Pratama
RoadmapArtikelCheat SheetsChallengesUpgrade
belajarkoding LogobyGalih Pratama
RoadmapArtikelCheat SheetsChallengesUpgrade

Daftar Isi

Core ConceptsProject Setupvite.config.tsConditional ConfigPluginsDev Server dan HMRHMR APIProxyEnvironment VariablesBuild OptimizationDynamic Import untuk Code SplittingDependency Pre-bundlingLibrary ModeSSR (Server-Side Rendering)Plugin APICSS SupportStatic AssetsTypeScript SupportGlossary
ViteBuild ToolsFrontendTypeScript

Vite Cheat Sheet

Referensi cepat Vite build tool. Config, plugins, dev server, HMR, build optimization, SSR, library mode, environment variables, dan plugin API. Perfect buat frontend developer TypeScript.

TypeScript12 min read2.224 kata
Silakan login atau daftar untuk membaca cheat sheet ini.

Baca Cheat Sheet Lengkap

Login atau daftar akun gratis untuk membaca cheat sheet ini.

LoginDaftar Gratis
Share:

#Core Concepts

Vite adalah build tool modern yang pakai native ES modules saat development dan Rollup untuk production build. Development server start hampir instan karena gak perlu bundle dulu. Berikut konsep inti yang perlu kamu pahami.

ConceptDescription
Dev ServerServe modules on-demand via native ESM
HMRHot Module Replacement, update module tanpa full reload
BuildProduction bundle dengan Rollup
PluginExtension yang hook ke Vite build pipeline
Optimize DepsPre-bundle dependencies pakai esbuild

#Project Setup

Bikin project Vite baru dengan template yang sesuai.

bash
# Bikin project baru (interactive)
npm create vite@latest my-app
 
# Dengan template spesifik
npm create vite@latest my-app -- --template react-ts
npm create vite@latest my-app -- --template vue-ts
npm create vite@latest my-app -- --template vanilla-ts
npm create vite@latest my-app -- --template svelte-ts
 
# Templates yang tersedia:
#   vanilla, vanilla-ts
#   vue, vue-ts













#vite.config.ts

File konfigurasi utama Vite. Semua pengaturan dev server, build, dan plugins ada di sini.

typescript
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';
 
export default defineConfig
































#Conditional Config

Kamu bisa return function dari defineConfig untuk konfigurasi yang berbeda antara dev dan build.

typescript
import { defineConfig } from 'vite';
 
export default defineConfig(({ command, mode }) => {
  if (command === 'serve') {
    // Dev server config
    return {
      server: {











VariableDescription
commandserve saat dev, build saat build
modedevelopment, production, atau custom
isSsrBuildtrue saat SSR build
isPreviewtrue saat preview command

#Plugins

Plugin extend kemampuan Vite. Beberapa plugin populer:

typescript
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import vue from '@vitejs/plugin-vue';
import { svelte } from





























PluginDescription
@vitejs/plugin-reactFast Refresh untuk React
@vitejs/plugin-vueVue SFC support
@tailwindcss/viteTailwind CSS v4 integration
vite-plugin-pwaService Worker dan PWA
vite-plugin-compressionGzip dan Brotli output
rollup-plugin-visualizerVisualisasi bundle size
vite-plugin-mkcertLocal HTTPS certificate
vite-plugin-svg-iconsSVG sprite dari folder

#Dev Server dan HMR

Dev server Vite sangat cepat karena pakai native ESM. HMR update module secara targeted tanpa reload halaman.

typescript
// vite.config.ts
export default defineConfig({
  server: {
    port: 3000,
    open: true,
    host: '0.0.0.0', // expose ke network
    https: true,     // HTTPS di dev
    strictPort: true












#HMR API

Komponen bisa accept HMR updates untuk hot reload yang targeted.

typescript
// React component dengan HMR (via @vitejs/plugin-react sudah otomatis)
import { useEffect } from 'react';
 
// Vanilla JS HMR
export function setupCounter(element: HTMLButtonElement) {
  let counter =






















#Proxy

Proxy berguna untuk avoid CORS issues saat development. Request ke API di-forward ke backend server.

typescript
// vite.config.ts
export default defineConfig({
  server: {
    proxy: {
      // String shorthand
      '/api': 'http://localhost:8080',
 
      // Dengan options
      '/api': {
        target: 'http://localhost:8080'

















OptionDescription
targetURL backend tujuan
changeOriginUbah Host header ke target URL
rewriteModify path sebelum forward
wsEnable WebSocket proxying
secureVerify SSL certificate target
bypassFunction untuk skip proxy

#Environment Variables

Vite expose environment variables via import.meta.env. Hanya variables dengan prefix VITE_ yang di-expose ke client.

bash
# .env
VITE_API_URL=https://api.example.com
VITE_APP_TITLE=My App
 
# .env.development
VITE_API_URL=http://localhost:8080
 
# .env.production
VITE_API_URL=https://api.example.com
 
# .env.staging
VITE_API_URL=https://staging-api.example.com
typescript
// Akses di code
console.log(import.meta.env.VITE_API_URL);
console.log(import.meta.env.VITE_APP_TITLE);
 
// TypeScript type safety
// src/vite-env.d.ts
/// <reference types









VariableDescription
import.meta.env.MODEMode saat ini (development, production)
import.meta.env.BASE_URLBase URL public saat deploy
import.meta.env.PRODtrue saat production
import.meta.env.DEVtrue saat development
import.meta.env.SSRtrue saat server-side build
import.meta.env.VITE_*Custom env variables
FileKapan dipakai
.envSelalu dimuat
.env.localSelalu dimuat, di-ignore git
.env.[mode]Hanya saat mode match
.env.[mode].localMode-specific, di-ignore git

#Build Optimization

Vite pakai Rollup untuk production build. Berbagai strategi optimasi tersedia.

typescript
// vite.config.ts
export default defineConfig({
  build: {
    target: 'es2020',        // Target browser JS
    outDir: 


































StrategyDescription
Manual ChunksPisahkan vendor code ke file terpisah
Code SplittingLazy load routes dengan dynamic import
Asset InlineInline asset kecil sebagai base64
CSS SplitPisahkan CSS per chunk
Minifyesbuild (cepat) atau terser (lebih agresif)

#Dynamic Import untuk Code Splitting

typescript
// Lazy load route
const AdminDashboard = lazy(() => import('./pages/AdminDashboard'));
 
// Prefetch saat idle
const button = document.querySelector('#load-chart');
button?.addEventListener(









#Dependency Pre-bundling

Vite pre-bundle dependencies pakai esbuild untuk konversi CJS ke ESM dan reduce number of requests.

typescript
// vite.config.ts
export default defineConfig({
  optimizeDeps: {
    include: ['lodash-es', 'date-fns'],
    exclude: ['my-local-package'],
    esbuildOptions: {
      target: 'es2020',
      define: {
        global: 'globalThis',
      },


OptionDescription
includeForce pre-bundle dependency
excludeExclude dari pre-bundling
entriesCustom entry points untuk scanning

#Library Mode

Vite bisa build library yang publishable ke npm. Output bisa ESM, CJS, atau UMD.

typescript
// vite.config.ts
import { resolve } from 'path';
import { defineConfig } from 'vite';
import dts from 'vite-plugin-dts';
 
export default defineConfig({






















jsonc
// package.json untuk library
{
  "name": "my-lib",
  "version": "1.0.0",
  "type": "module",
  "main": "./dist/my-lib.cjs.js",
  "module": "./dist/my-lib.es.js",
  "types": 








#SSR (Server-Side Rendering)

Vite punya built-in middleware untuk SSR development.

typescript
// vite.config.ts
export default defineConfig({
  server: {
    ssr: {
      external: ['express'], // Pakai saat SSR
    },
  },
  ssr: {





























SSR ConceptDescription
vite.ssrLoadModule()Load module untuk SSR di dev
vite.transformIndexHtml()Transform HTML dengan HMR client
ssr.externalPakai versi Node untuk lib ini
ssr.noExternalBundle lib ini untuk SSR

#Plugin API

Kamu bisa bikin plugin Vite sendiri. Plugin punya hooks untuk berbagai tahap build.

typescript
import type { Plugin, PluginOption } from 'vite';
 
function myPlugin(options: { 

















































HookDescription
configModify atau extend Vite config
configResolvedAkses final resolved config
buildStartDipanggil saat build mulai
transformTransform source code per file
transformIndexHtmlModify HTML entry
configureServerCustom dev server logic
loadResolve dan load module
resolveIdCustom module resolution
buildEndDipanggil saat build selesai

#CSS Support

Vite support CSS modules, preprocessor, dan PostCSS out of the box.

typescript
// vite.config.ts
export default defineConfig({
  css: {
    modules: {
      // Generate class names
      generateScopedName: '[name]__[local]___[hash:base64:5]',
      localsConvention: 'camelCase',
    },
    preprocessorOptions: {
      scss: {
        additionalData: 












typescript
// CSS Modules
import styles from './button.module.css';
 
export function Button() {
  return `<button class="${styles.btn}">Click</button>`;
}

#Static Assets

typescript
// Import asset sebagai URL
import imgUrl from './assets/logo.png';
// imgUrl => '/assets/logo.2h3k4j.png'
 
// Import asset sebagai string
import svgString from './icon.svg?raw';
 
// Import sebagai Web Worker
import MyWorker from './worker?worker';
const



#TypeScript Support

Vite gak melakukan type checking saat build. Pakai tsc atau vue-tsc secara terpisah.

jsonc
// package.json
{
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview",
    "typecheck": "tsc --noEmit"
  }
}
jsonc
// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "module": "ESNext",
    "lib": ["ES2020", "DOM", "DOM.Iterable"],









#Glossary

TermDefinition
Base URLPath prefix untuk public assets
ChunkBagian dari bundle output
Code SplittingMemecah bundle ke lazy-loaded chunks
Dependency Pre-bundlingPre-process node_modules dengan esbuild
HMRHot Module Replacement, update tanpa full reload
Library ModeBuild output sebagai library yang publishable
Manual ChunksCustom split vendor code ke file terpisah
Optimize DepsPre-bundling dependencies untuk dev cepat
PluginExtension yang hook ke build pipeline
RollupBundler yang dipakai untuk production build
SSRServer-Side Rendering
TransformHook untuk modify source code per file
VITE_Prefix untuk env variables yang di-expose ke client

Happy coding dengan Vite! ⚡

# react, react-ts
# preact, preact-ts
# lit, lit-ts
# svelte, svelte-ts
# solid, solid-ts
# Jalankan dev server
npm run dev
# Build untuk production
npm run build
# Preview build production
npm run preview
({
plugins: [react()],
root: '.',
base: '/',
publicDir: 'public',
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
'@components': path.resolve(__dirname, './src/components'),
'@utils': path.resolve(__dirname, './src/utils'),
},
},
server: {
port: 3000,
open: true,
host: true,
cors: true,
},
build: {
outDir: 'dist',
sourcemap: true,
target: 'es2020',
minify: 'esbuild',
chunkSizeWarningLimit: 1000,
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
utils: ['lodash-es', 'date-fns'],
},
},
},
},
});
port:
3000
,
},
};
} else {
// Build config
return {
build: {
outDir: 'dist',
},
};
}
});
'@sveltejs/vite-plugin-svelte'
;
import tailwindcss from '@tailwindcss/vite';
import { visualizer } from 'rollup-plugin-visualizer';
import { VitePWA } from 'vite-plugin-pwa';
import compression from 'vite-plugin-compression';
import mkcert from 'vite-plugin-mkcert';
export default defineConfig({
plugins: [
react(),
// vue(),
// svelte(),
tailwindcss(),
VitePWA({
registerType: 'autoUpdate',
manifest: {
name: 'My App',
short_name: 'MyApp',
},
}),
compression({
algorithm: 'gzip',
ext: '.gz',
}),
visualizer({
open: true,
filename: 'stats.html',
}),
mkcert(), // HTTPS untuk localhost
],
});
,
// error kalau port dipakai
// HMR config
hmr: {
protocol: 'ws',
host: 'localhost',
port: 3001,
clientPort: 3000,
},
// Watch options
watch: {
ignored: ['**/node_modules/**', '**/dist/**'],
},
},
});
0
;
const setCounter = (count: number) => {
counter = count;
element.innerHTML = `count is ${counter}`;
};
element.addEventListener('click', () => setCounter(counter + 1));
setCounter(0);
}
// HMR accept manual
if (import.meta.hot) {
import.meta.hot.accept((newModule) => {
console.log('Module updated', newModule);
});
// Cleanup sebelum dispose
import.meta.hot.dispose(() => {
console.log('Module disposed, cleanup resources');
});
// Persist state across HMR
const data = import.meta.hot.data;
data.count ??= 0;
}
,
changeOrigin: true,
secure: false,
rewrite: (path) => path.replace(/^\/api/, ''),
configure: (proxy, options) => {
proxy.on('proxyReq', (proxyReq, req, res) => {
console.log('Proxying:', req.url);
});
},
},
// WebSocket proxy
'/socket.io': {
target: 'ws://localhost:8080',
ws: true,
},
},
},
});
=
"vite/client"
/>
interface ImportMetaEnv {
readonly VITE_API_URL: string;
readonly VITE_APP_TITLE: string;
readonly VITE_DEBUG: string;
}
interface ImportMeta {
readonly env: ImportMetaEnv;
}
'dist'
,
sourcemap: 'hidden', // Source maps tersembunyi
minify: 'esbuild', // esbuild (cepat) atau terser (lebih kecil)
cssCodeSplit: true, // Split CSS per chunk
assetsInlineLimit: 4096, // Inline asset < 4KB sebagai base64
chunkSizeWarningLimit: 500,
reportCompressedSize: true,
rollupOptions: {
input: {
main: 'index.html',
admin: 'admin.html',
},
output: {
// Manual chunking
manualChunks(id) {
if (id.includes('node_modules')) {
if (id.includes('react')) return 'react-vendor';
if (id.includes('lodash')) return 'lodash-vendor';
return 'vendor';
}
},
// Asset naming
chunkFileNames: 'assets/js/[name]-[hash].js',
assetFileNames: 'assets/[ext]/[name]-[hash].[ext]',
entryFileNames: 'assets/js/[name]-[hash].js',
},
// External dependencies (untuk library mode)
external: ['react', 'react-dom'],
},
},
// Performance hints
esbuild: {
drop: ['console', 'debugger'], // Hapus console.log di production
legalComments: 'none',
},
});
'click'
, ()
=>
{
import('./chart').then((module) => {
module.renderChart();
});
});
// Preload critical chunks
const link = document.createElement('link');
link.rel = 'modulepreload';
link.href = '/assets/critical.js';
document.head.appendChild(link);
},
},
});
build: {
lib: {
entry: resolve(__dirname, 'src/index.ts'),
name: 'MyLib',
fileName: (format) => `my-lib.${format}.js`,
formats: ['es', 'cjs', 'umd'],
},
rollupOptions: {
external: ['react', 'react-dom'],
output: {
globals: {
react: 'React',
'react-dom': 'ReactDOM',
},
},
},
},
plugins: [
dts({
insertTypesEntry: true,
}),
],
});
"./dist/index.d.ts"
,
"exports": {
".": {
"import": "./dist/my-lib.es.js",
"require": "./dist/my-lib.cjs.js",
"types": "./dist/index.d.ts"
}
},
"files": ["dist"]
}
noExternal: ['my-component-lib'], // Bundle lib ini untuk SSR
},
});
// SSR development dengan middleware
import { createServer } from 'vite';
import express from 'express';
async function createApp() {
const app = express();
const vite = await createServer({
server: { middlewareMode: true },
appType: 'custom',
});
app.use(vite.middlewares);
app.use('*', async (req, res) => {
const template = await vite.transformIndexHtml(
req.originalUrl,
fs.readFileSync('./index.html', 'utf-8')
);
const { render } = await vite.ssrLoadModule('/src/entry-server.tsx');
const appHtml = await render(req.url);
const html = template.replace('<!--app-html-->', appHtml);
res.status(200).set({ 'Content-Type': 'text/html' }).end(html);
});
app.listen(3000);
}
msg
:
string
})
:
Plugin
{
return {
name: 'my-plugin',
// Hook lifecycle
config(config, { command }) {
console.log('Config resolved');
return {
// Merge config
};
},
configResolved(resolvedConfig) {
console.log('Final config', resolvedConfig);
},
options(rollupOptions) {
console.log('Rollup options');
},
buildStart() {
console.log('Build started', options.msg);
},
transform(code, id) {
// Transform source code
if (id.endsWith('.md')) {
return convertMarkdownToJs(code);
}
},
transformIndexHtml(html) {
// Modify index.html
return html.replace('</head>', '<script>injected</script></head>');
},
configureServer(server) {
// Custom dev server middleware
server.middlewares.use('/api/custom', (req, res) => {
res.end(JSON.stringify({ hello: 'world' }));
});
},
load(id) {
// Virtual modules
if (id === 'virtual:my-module') {
return 'export default "hello"';
}
},
buildEnd() {
console.log('Build finished');
},
};
}
// Pakai plugin
export default defineConfig({
plugins: [myPlugin({ msg: 'Hello' })],
});
closeBundle
Dipanggil setelah semua bundles selesai
`@import "@/styles/variables.scss";`
,
},
less: {
javascriptEnabled: true,
},
},
postcss: {
plugins: [
// Atau pakai postcss.config.js
],
},
devSourcemap: true,
},
});
worker
=
new
MyWorker
();
// Import dengan inline query
import logo from './logo.png?inline'; // Selalu inline sebagai base64
import wasmUrl from './module.wasm?url';
"moduleResolution": "bundler",
"jsx": "react-jsx",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"types": ["vite/client"]
},
"include": ["src"]
}