svelte SPA with TypeScript, Routes and SCSS

svelte SPA with TypeScript, Routes and SCSS
Page content

svelte is one of the newer JavaScript-Frameworks out there. Although I do not tend to jump on the hype train, the “compile time” approach svelte uses is really promising referring to performance and size. Here is how to start a project with TypeScript, Routes and SCSS

Introduction

This tutorial is based on information I gathered during my research and project work and summarizes setting up features, I’d personally like to use. It is a basic project setup for advanced users, not for beginners and neither a replacement for the official documentation nor a guide that describes all best practises. It contains:

  • TypeScript integration for svelte projects
  • SCSS integration (CSS with superpowers)
  • routify integration, which can be used to better organize your project’s filesystem structure and code

Why svelte?

svelte is fast and small - ideal for smaller to medium-sized projects in my opinion. Instead of being stuffed with features at runtime, it converts the code and templates to native javascript at compile time, which results in delivering only vanilla JavaScript code, that is absolutely necessary. The support of Web-Components and a pretty fast boilerplate is a bonus.

Preparations

Before you start with svelte , you have to install Node.js (node, npm, npx). You’ll find further instructions on the homepage.

Step 1: Project setup

These are the basic steps to set up a new svelte project (shamelessly stolen from the official homepage):

SVELTE_PROJECT_NAME="my-svelte-project"

npx degit sveltejs/template "${SVELTE_PROJECT_NAME}"
cd "${SVELTE_PROJECT_NAME}"
# setup TypeScript (this step is optional, but I like to use it)
node scripts/setupTypeScript.js
npm install
npm run dev

Now you should see a URL to open the “Hello World!”, probably http://localhost:5000 .

Note: To actually use TypeScript in the project, you have to use <script lang="ts"> instead of <script>

Step 2: SPA routing with routify

The package routify (@roxi/routify) allows client side SPA routing for svelte . It is also “compile time”, which means that the filesystem structure will be precompiled to routes and not determined at runtime - which is awesome and follows the svelte design principles.

Dependencies

Install the following dependencies:

Note: This is different from the official instructions, because I had errors. If it does not work for you, you may also follow the official ones.

npm i -D @roxi/routify npm-run-all svelte-preprocess

Update package.json

Next, update the package.json - to use routify , you also need to update the scripts section and set "dynamicImports": false:

{
	"...": "...",
	
	
	"scripts": {
		"dev": "run-p dev:*",
		"dev:rollup": "rollup -c -w",
		"dev:routify": "routify",
		"build": "routify -b && rollup -c",
		
		"...":"..."
	},
	"routify": {
		"dynamicImports": false
	}
	
}

Integrate routify filesystem structure

To integrate routify , you need to modify the App.svelte and create some new templates in the pages directory. Since it is “compile time” routing, a directory .routify will be generated automatically, containing all your precompiled routes. This is what you also need to import. There are two ways of routing:

<!-- src/App.svelte -->
<script lang="ts">
  import { Router } from "@roxi/routify";
  import { routes } from "../.routify/routes";
</script>
<!-- Hash-based routing
<Router config={{useHash: true}} {routes} />
-->
<Router {routes} />

The file _layout.svelte is a meta-template, that will be used to render everything, that was in App.svelte before. <slot/> is the destination for all page templates.

<!-- src/pages/_layout.svelte -->
<div class="container">
    <slot/>
</div>

To ensure, everything is working before getting into detail, we add the route name index to our page template.

<!-- src/pages/index.svelte -->
index

Don’t forget to restart npm run dev. You could now check http://localhost:5000 again, if it is showing the index text. Since /.routify/ is auto generated, we can add it to our .gitignore

# .gitignore
# ...
/.routify/

Step 3: SCSS support

While this should be easy, in svelte you might run in to problems using SCSS. One way I got everything working was to start with installing these dependencies:

npm i -D node-sass postcss sass rollup-plugin-scss

Then add the following SCSS files:

/* scss/__vars.scss */

$bodyBackground: silver;
/* scss/main.scss */
@import '_vars';

body {
  background: $bodyBackground;
}

To have an entry point for loading the SCSS files, I created a template only for this purpose:

<!-- src/GlobalScssImports.svelte -->
<style lang="scss" global>
  @import "scss/main.scss";
</style>

And included it into the App.svelte:

<!-- src/App.svelte -->
<script>
	import { Router } from "@roxi/routify";
	import { routes } from "../.routify/routes";
    import GlobalCssImports from "./GlobalScssImports.svelte";
</script>
<GlobalCssImports/>
<Router config={{useHash: true}} {routes} />

Restart npm run dev again. Refresh, now you should see a page with background:silver; on http://localhost:5000 and this SCSS config should enable you to use @import statements in scss/main.scss for other files.

Step 4: Navigation and first route

To verify routes are working correctly, now create your first page template in form of contact.svelte:

<!-- src/pages/contact.svelte -->
contact

The _navigation.svelte is not a page template or route, but only used as import in _layout.svelte (templates starting with _ will be ignored by routify, except _layout.svelte and other reserved names). The helpers url and isActive can be used, to create links to routes and add CSS classes for active elements:

<!-- src/pages/_navigation.svelte -->
<script>
    import {url, isActive} from '@roxi/routify';
</script>

<nav class="main-nav">
    <ul>
        <li class:active="{$isActive('./index')}"><a href="{$url('')}">index</a></li>
        <li class:active="{$isActive('./contact')}"><a href="{$url('./contact')}">contact</a></li>
    </ul>
</nav>

Then load the _navigation.svelte into the _layout.svelte:

<!-- src/pages/_layout.svelte -->
<script>
    import Navigation from "./_navigation.svelte";
</script>

<Navigation/>

<div class="container">
    <slot/>
</div>

To actually see, if the helpers for class active do their job, we add a little SCSS:

/* scss/main.scss */
@import '_vars';

body {
  background: $bodyBackground;
}

.main-nav .active {
  font-weight:bold;
}

Now you should be able to navigate in your project, and the active nav item should be highlighted bold.

Conclusion

This is it for now. The page still looks pretty raw, but you should have a starting point with the mentioned technologies and a basic project setup for building nice little blazing fast apps. Take a look at the svelte and routify documentation for the next steps.

Andreas Fuhrich avatar
About Andreas Fuhrich
I’m a professional software developer and tech enthusiast from Germany. On this website I share my personal notes and side project details. If you like it, you could support me on github - if not, feel free to file an issue :-)