Svelte Introduction
What makes Svelte a compiler instead of a runtime library, and how to scaffold a project.
What makes Svelte different
React and Vue both ship a runtime library to the browser that does its work at runtime — tracking a virtual DOM (React) or a reactivity graph (Vue), then diffing and patching the real DOM as your app's data changes. Svelte takes a different approach entirely: it's a compiler, not a runtime library.
When you build a Svelte app, the Svelte compiler analyzes your components at build time and generates plain, highly optimized JavaScript that surgically updates exactly the DOM nodes that need to change when a specific value updates — no virtual DOM, no diffing step, no framework runtime shipped to the browser to do that work. The result is typically smaller bundle sizes and less work done in the browser, because most of the "figuring out what changed" happens once, ahead of time, during the build — not repeatedly, in the user's browser, on every update.
This is the single most important thing to understand about Svelte before writing any code: where React or Vue answer "how do we efficiently update the DOM at runtime," Svelte mostly answers "how do we generate the exact update code we need, before the app ever runs."
Installing Svelte
The modern way to start a Svelte project is through SvelteKit, Svelte's official application framework (routing, server-side rendering, and build tooling included) — the equivalent of what Next.js is to React:
npx sv create my-app
cd my-app
npm install
npm run dev
sv create (the current Svelte CLI) walks you through choosing SvelteKit's options — TypeScript, ESLint, Prettier, and more — and scaffolds a working project with a dev server. If you only want a component library or a small embedded widget without SvelteKit's full application/routing layer, a plain Vite + Svelte template is also available via npm create vite@latest -- --template svelte.
A minimal Svelte component
A .svelte file is a single self-contained component — script, markup, and styles together, similar in spirit to a Vue Single File Component:
<script>
let name = "NOA Labs";
</script>
<h1>Hello, {name}!</h1>
<style>
h1 {
color: darkorchid;
}
</style>
Three sections, each optional: a <script> block for the component's logic, plain markup for the template (with {} embedding a JavaScript expression, similar to JSX and Vue's {{ }}), and a <style> block that's automatically scoped to just this component — a h1 rule here won't leak out and affect headings elsewhere in the app.
Compare this to the equivalent in React or Vue: there's no useState, no ref(), no special wrapper around name at all. It's a plain let variable. That's possible specifically because Svelte's compiler can see, at build time, that name is used in the template, and generates the code needed to keep the DOM in sync whenever it's reassigned — which is exactly what the next page covers.
Common mistakes
- Assuming Svelte still needs a virtual-DOM-style runtime shipped to the browser the way React and Vue do — it doesn't; the compiler does that reconciliation work ahead of time, at build time.
- Confusing Svelte (the compiler and component syntax) with SvelteKit (the application framework built on top of it, providing routing and SSR) — you can use Svelte components without SvelteKit for a smaller embedded widget, but most full applications use SvelteKit.
- Expecting
<style>blocks to affect elements outside the component — by default they're scoped, unlike a plain global stylesheet.