Svelte (https://svelte.dev/) is a tool for building JavaScript-based web applications. It is an alternative to web frameworks like React, Vue, and Angular. Like them, Svelte focuses on defining user-interface (UI) components and their interactions. Each UI component is an independent, potentially reusable part of a larger user interface that can be independently designed and implemented.
Svelte has many benefits over other web frameworks:
Apps produced using Svelte require less code than most frameworks to implement the equivalent functionality.
Svelte produces smaller bundle sizes, which results in decreased browser load times.
Svelte greatly simplifies state management, both within and across components. (State management includes organizing the data that drives an app and responding to changes in the data.)
Sapper (https://sapper.svelte.dev/) is a framework built on top of Svelte for creating more advanced web applications. It adds many features over Svelte, including page routing, server-side rendering, code splitting, and static site generation. But web applications that do not need these features, or that wish to implement them in a different way, can opt to use Svelte by itself.
Svelte Native (https://svelte-native.technology/) also builds on Svelte. It integrates the use of NativeScript for building Android and iOS mobile applications.
Note Throughout this book when referring to various options for creating web applications, I will refer to them as “frameworks,” even though some use the term “library.”
Do we really need another tool for building web applications?
Putting in the effort to learn yet another approach is only worthwhile if it brings significant benefits. Perhaps it could require writing less code to achieve the same outcome. Maybe it could do less actual work at runtime to accomplish the same result. Or perhaps it could result in fewer total bytes needing to be downloaded to browsers.
Check, check, and check! Svelte delivers on all of these goals and more.
Like other frameworks, Svelte can be used to build entire web applications. Svelte components can be used in a single application or can be defined in a library that is shared by multiple applications. It can also be used to create custom elements (web components) that are usable in web apps implemented with other frameworks or with no framework at all.
Rich Harris, who formerly worked at The Guardian and is currently at The New York Times, developed Svelte starting in 2016. He previously created the Ractive web framework (https://ractive.js.org/), which is used at The Guardian and inspired parts of Vue. He also created the Rollup module bundler, which is an alternative to Webpack and Parcel.
The word svelte means slender, which describes both the syntax of Svelte and the bundle sizes it produces.
Svelte has many advantages over existing web frameworks. The most significant of these are summarized in the following sections.
Other popular web frameworks include large runtime libraries to support all their features. But Svelte is not a runtime library. It is a web application compiler implemented in TypeScript.
Note A compiler is software that translates code in one programming language to another. Typically this is from a high-level language (such as Go or Java) to a lower-level language (such as machine code or bytecode).
Note TypeScript is an open source programming language that is a superset of JavaScript; its programs are compiled to JavaScript. TypeScript adds many features above JavaScript, the most significant of which is the ability to define the types of variables and functions. TypeScript is developed and maintained by Microsoft.
Svelte UI components are defined in .svelte
files. These can contain a combination of JavaScript, CSS, and HTML. For example, a component could contain HTML elements for a login form, CSS to style it, and JavaScript to pass the data entered to an authentication service when the Login button is clicked.
The Svelte compiler compiles .svelte
files to JavaScript and CSS. This has many benefits, one being that new features can be added to Svelte without bloating the bundle size of deployed applications. The compiler only includes code for the features of Svelte that are actually used.
Svelte apps have significantly smaller bundle sizes than equivalent apps created with other web frameworks. This means that Svelte apps can be downloaded to browsers more quickly.
Note In the context of web applications, bundles are JavaScript files that are created by combining, optimizing, and minimizing all the JavaScript code needed by an application.
In large part, Svelte achieves smaller bundle sizes by including only the required framework code instead of an entire framework library. For example, the Todo app presented in chapter 2 has a bundle size that is 13% of the size of an equivalent React app. Links to Svelte, React, and Vue versions of this app can be found in chapter 2.
Note All of these web frameworks incorporate some amount of “tree shaking” to eliminate unused code. But Svelte retains far less framework code. For example, React apps must ship code that produces virtual DOM representations and finds differences between them. The use of virtual DOMs is described later.
FreeCodeCamp’s comparison of frameworks, “A RealWorld Comparison of Front-End Frameworks with Benchmarks (2019 update),” catalogs statistics on building a real world web application using many web frameworks (http://mng.bz/8pxz). In this case, the app used in the comparison is a social blogging site called “Conduit,” similar to Medium.com.
The reported gzipped app size for some popular framework choices include
Clearly Svelte shines on this metric.
Svelte requires less code to implement the same functionality. The reported number of lines of code from these same benchmarks are
This is significant for multiple reasons. Having less code to read means there is less code to understand. It also means there are fewer places for bugs to hide.
Some web frameworks, including React and Vue, use a virtual Document Object Model (DOM) to optimize updating the real DOM in response to data changes. When component state changes, the framework builds a new version of the DOM in memory and then compares it to the previous version. Only the differences are applied to the real DOM. Although this is faster than updating everything in the real DOM, it does take time to build a virtual DOM and compare it to the previous one.
Reactivity is the ability to update the DOM in response to application and component state changes. Svelte provides reactivity by tracking changes to top-level component variables (not scoped inside functions) that affect what components render. It updates only the affected parts of the DOM rather than re-rendering the entire component. This allows Svelte to do less work than many frameworks to keep the DOM in sync with application state.
Check out Stefan Krause’s benchmarks at https://krausest.github.io/js-framework-benchmark/current.html. The app used in these tests renders a table with 4 columns and 1,000 rows. On this page you can select the frameworks to be compared and see side-by-side statistics. For example, select “angular-v8.0.1-keyed,” “react-v16.8.6-keyed,” “svelte-v3.5.1-keyed,” and “vue-v2.6.2-keyed.” This returns the results for application startup time shown in figure 1.1. These results demonstrate that Svelte is quite fast compared to other options.
Note The term keyed in these selections means the code creates an association between data and DOM elements. When the data changes, the associated DOM element is updated. Adding and removing array elements causes DOM elements to be added and removed. The test results in figure 1.1 are from “keyed” implementations because that is more representative of what apps typically use to make updating of existing DOM elements more efficient.
Figure 1.1 Benchmark boot-up time and download time
Using less memory is a significant benefit when web applications are run on older computers or mobile devices, which tend to have less available memory for running applications.
The benchmark site used in the previous section reports the comparison for memory usage shown in figure 1.2. These results demonstrate that Svelte apps typically use less memory than other options.
.svelte
files do not define any kind of JavaScript container for the component. Instead, a component is defined by a combination of a script
element, HTML to render, and a style
element.
This approach is simpler than that used by most other web frameworks. Fewer lines of code are required to define a component, and there are fewer JavaScript concepts to think about. For example, Angular components are defined by a class, React components are defined by a function or a class, Vue 2 components are defined by an object literal, and Vue 3 components are defined by functions.
By default, the CSS specified in each Svelte component only applies to that component. This means that CSS rules defined in a .svelte
file do not accidentally “leak out” and affect the styling of other components.
Styles are treated differently in other frameworks. In Angular, styles specified in the styles
property of a component are also scoped to the component by default. In Vue, styles are only scoped to components if they are specified inside a style
element with the scoped
attribute. React does not provide support for scoping styles to components, which is one reason why CSS-in-JS solutions are popular in React applications. There is little appeal for these CSS-in-JS solutions in Svelte.
Figure 1.2 Benchmark memory utilization in MBs
Svelte provides a clear place to specify global styles that can affect any component. This is in the file public/global.css
.
Management of application and component state is much easier in Svelte compared to other frameworks. Contributing features include context, stores, and module context, each of which will be covered in detail later.
Svelte makes it easy to bind the value of a form control to a component variable. Form controls include input
, textarea
, and select
elements. Top-level variables in .svelte
files represent the state of a component.
When the value of a bound variable changes, the values of associated form controls are automatically updated. When the user changes the value of a bound form control, the value of the associated variable is automatically updated.
Svelte has built-in support for a variety of animations. Adding animation to an application is surprisingly simple. This encourages the use of more animation, which can result in a better user experience.
Examples of such animations in a Todo app include causing new todo items to fade into view and deleted todo items to fade out of view. If todo items are maintained in categorized lists, animation can be used to smoothly move an item out of its current category and into a new category.
Svelte provides runtime warnings for accessibility issues. For example, img
elements that have no alt
attribute are flagged. This makes it more likely that Svelte applications will be usable by users that require special ways of interacting with web browsers.
In the context of web applications, reactivity is the ability of the DOM to be updated automatically in response to changes in data (a.k.a. state). This can be compared to spreadsheets. A change to the value of one cell can cause the values displayed in other cells to change. This happens when a cell’s value is based on the values of other cells using a formula.
Svelte makes implementing reactivity easier than other frameworks. It supports a unique way of managing the state of a component that relies on watching top-level variables (explained in section 3.9). It also simplifies the ways in which state can be shared across components.
The “Rethinking Reactivity” conference talk given by Rich Harris on multiple occasions clearly describes the concerns that motivated the creation of Svelte (www.youtube .com/watch?v=gJ2P6hGwcgo). The top 10 points in this talk all correlate to features implemented in Svelte:
Implement real “reactive programming” as seen in spreadsheets. When a value changes, other values can update in response.
Avoid use of a virtual DOM. Rich says, “As engineers we should be offended by all that inefficiency.”
Write less code. It’s better for developers and better for performance. Rich says, “There’s only one reliable way to speed up your code, and that is to get rid of it.”
Scope styles to components so they don’t leak out and affect each other.
Make it easy to add transitions and animations, using CSS for performance.
Allow framework features to be added without bloating the bundle size of apps that don’t use them.
Use Sapper (a wrapper around Svelte) to add page routing, code splitting, server-side rendering, and more.
Use Svelte Native for mobile apps. This is an alternative to React Native.
Using Svelte is appropriate for nearly any web application. However, there are issues you should consider that may cause some developers to prefer other frameworks.
Svelte is implemented in TypeScript, but until July 21, 2020 it did not support using TypeScript to define components out of the box. This could be achieved with a little configuration and added tooling. But now, opting into the use of TypeScript is much easier. See https://svelte.dev/blog/svelte-and-typescript for details.
Note Chapter 20 discusses using svelte-preprocessor to support using TypeScript in .svelte
files. The official TypeScript support added in July, 2020 uses this. Chapter 20 also touches on using the command-line tool svelte-check to check for errors in .svelte
files, including TypeScript errors. Appendix F discusses using the VS Code extension Svelte for VS Code, which uses the Svelte Language Server to report errors in opened .svelte
files, including TypeScript errors.
Svelte is not a particularly good option for web applications that must run in Internet Explorer. Polyfills are required to run Svelte apps in Internet Explorer 11 (see https:// github.com/sveltejs/svelte/issues/2621 and https://mvolkmann.github.io/blog/topics/ #/blog/svelte/supporting-ie11/). Svelte apps are unlikely to run in versions of Internet Explorer before version 11. Fortunately, it is no longer a requirement for most web applications to run in Internet Explorer.
Some web frameworks (such as React and Vue) make it easy to generate the content for different parts of a component in separate functions within a component definition. Contrast this with the approach used by Svelte, where all the HTML for a component is specified outside its JavaScript code. A downside of the Svelte approach is that dividing the HTML to be rendered into separately managed chunks requires defining additional components in separate .svelte
files. However, since these files contain almost no boilerplate code, creating a new component is easy.
Web frameworks that predate Svelte have had many years for their supporting libraries to be created. One example is collections of pre-built components. Fewer of these libraries currently exist for Svelte, but the number is growing.
Consider whether the benefits of Svelte outweigh the limitations described here. I’m confident that after a little experience with Svelte, you will conclude, as I have, that they do!
Figure 1.3 shows the role of the Svelte compiler. User-interface (UI) components are implemented in .svelte
files. These can contain JavaScript code (in a script
element), CSS (in a style
element), and HTML to be rendered.
Figure 1.3 Flow of files into and out of the Svelte compiler
.svelte
files can import other .svelte
files to use as child components. For example, a TodoList
component that represents an entire Todo application can import and use a Todo
component that represents a single todo item, perhaps with a checkbox, the text of the item, and a Delete button.
.svelte
files can also import things such as functions from .js
files and from third-party libraries (typically obtained from npm). For example, functions from the popular Lodash library can be imported and used in a Svelte app.
The Svelte compiler compiles all of this into a single bundle.js
file and a single bundle.css
file. These contain only the JavaScript code and CSS rules that are used in the application. Only the parts of the Svelte library that are needed are included in bundle.js
.
Styling that can affect any component is placed in the global.css
file. The main HTML file, index.html
, includes global.css
and the bundle files produced by the Svelte compiler. This HTML file is loaded into a web browser to run the application.
The Svelte compiler also generates bundle.css.map
and bundle.js.map
files, which support mapping from the generated code to original source lines. These are used by debuggers, such as those built into browsers.
In most web frameworks, the code that is delivered to web browsers to run an application includes code written by the developers and a framework library. If the framework implements a large number of features, the code to support those features is often delivered even if only a subset of the features is actually used.
Some say that Svelte “disappears” once an app is built. This refers to not including a Svelte library in the bundle produced by the Svelte compiler. But some Svelte library code is included.
The Svelte library is mostly defined by JavaScript files in the node_modules/svelte
directory. The main functions are defined in internal.js
, which is currently around 1,400 lines of code. Other library files are used for specific features, including easing.js
, motion.js
, register.js
, store.js
, and transition.js
.
As you will see later, Svelte applications are compiled by running the npm
run
dev
or npm
run
build
commands. These produce files in the public
directory, including bundle.js
and bundle.css
. Svelte library functions that are used by the app are copied to the top of bundle.js
. For small to medium size apps (such as a Todo app), this amounts to around 500 lines of code.
The Svelte library code doesn’t disappear, but it is very small compared to other web frameworks.
Sapper is a framework that builds on Svelte. It includes all of Svelte and adds many features that are not included in Svelte by default. These features can be added to Svelte applications, but it is easier to use Sapper and automatically gain them.
The name Sapper has two meanings. First, it is a contraction of “Svelte app maker.” Second, the English word sapper is defined as “a soldier responsible for tasks such as building and repairing roads and bridges, laying and clearing mines, etc.” In a sense, this is what Sapper does for Svelte.
Like Svelte, Sapper was created and is maintained by Rich Harris along with many other contributors.
Each of the following features are added by Sapper. We’ll look at them in detail in later chapters.
Sapper provides page routing. Page routing associates URLs with “pages” in an app and defines how navigation between pages is described in markup. Sapper page routing is entirely defined by directory and file naming conventions. This makes it easier to understand and implement than approaches that require calling library functions to configure routing.
Sapper supports page layouts. Page layouts define a common layout for sets of pages within an app. For example, many pages might contain common header
, footer
, and nav
sections. Page layouts remove the need to repeat these common sections on each page that requires them.
Sapper provides server-side rendering (SSR), which generates the HTML for visited pages on the server instead of in the browser. This can provide a better user experience, because the JavaScript for the page does not have to be downloaded before the page is rendered. It can also result in better search engine optimization (SEO). Sapper SSR does this automatically for the first page visited within a session.
Sapper supports server routes. Server routes provide an easy way to implement Node-based API services in the same project as the client-side web application. This is convenient for developers who wish to work on the full stack of an application rather than only the frontend. Using this feature is optional. The API/REST services used by Svelte and Sapper apps can be implemented with any technology stack.
Sapper supports code splitting. Code splitting allows the JavaScript required for each page of the application to be downloaded only when a page is visited for the first time. This is much more efficient than downloading all the code for the entire application when the first page is visited.
Sapper supports prefetching. Prefetching provides faster page loads by anticipating the next page a user will visit based on mouse hovers. This can be configured on each page link. The first time a user hovers over such a page link, Sapper will begin downloading the JavaScript required by the page. It can also initiate calls to API services that gather data required by the page.
Sapper supports static site generation. Static site generation (or exporting) crawls a Svelte web application at build time and generates the HTML that each page renders. This results in highly efficient websites because each page is, in a sense, prerendered.
Sites created this way are not required to be entirely static. They can still include JavaScript code and take advantage of Svelte reactivity for updating the DOM.
Sapper supports offline usage. Sapper web applications use a service worker in order to remain usable, perhaps in a limited sense, when network connectivity is lost. This is done by caching certain files and responses so that cached versions are used when there is no connection to the internet.
Sapper supports end-to-end testing. Sapper apps come with support for using Cypress to implement tests that walk through an application in the way a user would, performing tasks like logging in, navigating to various pages, entering text, and clicking buttons.
The “pages” of a Sapper app are defined in .svelte
files that reside in the src/routes
directory. The components used by these pages are defined in .svelte
files that reside in the src/components
directory. Navigation between pages is implemented with plain HTML anchor elements (<a>
) that specify a page name in their href
attribute.
By default, Sapper apps are served by the Polka server library. This is a Node-based library that has nearly the same API as Express, but Polka is more efficient in terms of performance and size. If desired, Sapper apps can easily be modified to use Express instead.
As you saw earlier, the Svelte compiler generates bundle.js
and bundle.css
files that contain all the JavaScript and CSS for the entire application. Sapper is different. It generates separate .js
and .css
files for each page of the application. These are placed in the _ _
sapper_ _/build/client
directory. On each page load, only the JavaScript and CSS needed for that page are downloaded.
Using Sapper instead of straight Svelte is as easy as creating a project with a different initial set of directories and files. These sets of files can be created with the npx
command, as you will see later.
All of the features described in the previous section are available by default in Sapper applications. No additional libraries are required.
Using Sapper instead of Svelte is recommended any time an app needs one or more of the features provided by Sapper, and when developers approve of the way Sapper has implemented them. For example, developers who prefer an alternative way of describing page routes might opt to use Svelte, where they can choose a routing strategy. For most apps, the approaches used by Sapper are acceptable.
At the time of writing, Sapper had not yet reached version 1.0.0. This means that its features are still subject to breaking changes. Developers who are concerned about this may want to wait until Sapper is more mature before using it in production applications.
However, the features provided by Sapper are so valuable and well-implemented that it may be better to use it in its current state than attempt to duplicate these features in a Svelte app. After all, it is likely that you already use many npm packages that are not yet tagged as version 1 or above.
NativeScript (https://nativescript.org/) is a framework for creating mobile applications that run on Android and iOS devices. It was created and is maintained by Telerik, which was acquired by Progress Software in 2014.
NativeScript applications are built using XML syntax (with custom elements), CSS, and JavaScript. They can be written without using any web framework, or they can use Angular, React, Svelte, or Vue.
NativeScript applications use native components rather than web views. In this sense, NativeScript is similar to React Native. Plugins allow access to all native device APIs.
Svelte Native (https://svelte-native.technology/) builds on top of NativeScript to enable developers to build mobile applications using Svelte. It provides a thin layer over the NativeScript API, which will make it easy to ensure compatibility with future NativeScript versions.
Chapter 21 will provide an introduction to writing Svelte Native applications.
Svelte differs from other currently popular web frameworks in several ways. Let’s examine some of them.
Angular apps require developers to write more code to accomplish the same tasks. Svelte code is more, well, ... svelte.
Angular concepts appeal to Java and C# developers who are accustomed to writing lots of classes and using dependency injection.
Angular apps typically use “effects” and libraries like RxJS and ngrx/store. These increase the time required to become proficient in Angular.
React components use JSX (short for JavaScript XML) to describe what should be rendered. JSX is an extension to JavaScript syntax that looks like HTML. React converts this to function calls that produce DOM nodes. Although JSX is very similar to HTML, there are differences. Some developers dislike JSX because they do not like mixing it into their JavaScript code. While Svelte components define their JavaScript, CSS, and HTML in the same file, they are specified in distinct sections of the file.
React uses a virtual DOM. Issues with this were described earlier.
The number of concepts that must be grasped to be proficient in React continues to grow. For example, hooks are a big topic, and there are many others to learn. There are multiple ways to deal with state, including this.setState
, the useState
hook, Redux, and many more. On the horizon we have Suspense and Concurrent Mode. Svelte is much easier to learn.
Vue 2 components are described with object literals. These describe many things about a component, including the props it accepts, computed properties (based on others), data used (component state), watch functions (to react to state changes), and methods (such as event handling). Code in Vue 2 components make frequent use of the this
keyword, and some developers feel this makes the code more difficult to understand. It also makes the code more verbose. Vue 3 components are described with functions. In addition, Vue uses a virtual DOM, and the issues with this were described earlier.
But with Svelte components, all of these things are defined using plain JavaScript variables and functions with the help of reactive statements (described in the next chapter).
This book assumes that you understand the fundamentals of using HTML, CSS, and JavaScript in the context of implementing web applications. You should be familiar with basic HTML (including form elements), CSS syntax (including the box model), and JavaScript syntax (including some features added in ECMAScript 2015 and beyond).
Getting started with Svelte and Sapper only requires that you have a recent version of Node.js installed. An installer can be downloaded from https://nodejs.org/.
Note As it states on the main Node.js website (https://nodejs.org/), “Node.js is a JavaScript runtime built on Chrome’s V8 JavaScript engine.” Node.js enables you to build many kinds of applications using JavaScript. These include network applications such as HTTP servers and tooling such as code linters, code formatters, and even the Svelte compiler.
Installing Node.js provides the commands node
, npm
, and npx
:
The node
command is used to start the local servers that are needed to test an app and to run other development tasks, such as linting, code formatting, and running tests.
The npm
command is used to install the libraries used by a project.
The npx
command is used to create new Svelte and Sapper projects.
Note Although it’s not yet ready for production use, another Svelte-related tool to consider is svelte-gl (https://github.com/sveltejs/gl). This library is similar to three.js (https://threejs.org/), but it’s tailored for use in Svelte. It takes as input a 3D scene graph description and outputs WebGL code to render it. You can see a demo at http://mng.bz/lG02.
Prepare to be amazed at how easy web development can be, compared to the approaches you currently use!
Svelte is a tool for building web applications that is an alternative to currently popular web frameworks like React, Vue, and Angular.
Svelte has many features that make it an attractive option, such as writing less code, producing smaller bundles (which improves startup times), and simplifying state management.
Sapper builds on Svelte, adding more features like page routing, server-side rendering, code splitting, and static site generation.
Svelte Native uses the features of Svelte to provide an alternative to React Native for building Android and iOS mobile applications.