SvelteKit gives you two options when you scaffold a new project, demo app & skeleton. Skeleton is what you would typically use when building a new project, trouble is it really is a lean setup, it gives you a solid foundation to build on and structure however you would like.
A lot of the freelance work I do is building regular run-of-the-mill informational websites for startups and larger corporates. Here's a rundown of the changes I make on every project and why, you may find some of them useful too!
Here's a summary of what we'll look at:
- Integrating SCSS
- Injecting SCSS into component <style> tags
- Hashing global styles to avoid cache issues
- Creating aliases for components and library folders
- Adding a version number meta tag to the <head>
- Allowing extension-less imports
- Forcing trailing slash on urls for better SEO
- Adding a layout page wrapper for global functionality Bonus Adding faux terminal kit api for install/updates
Get a skeleton kit installation setup before following below
package.json
Let's kick things off with package.json, we need two key packages to get SCSS working (sass & svelte-preprocess). The former will actually read and compile our SCSS code whilst the latter will allow Svelte to parse SCSS in component style tags.
You'll also notice i've listed @neuekit/reboot and @neuekit/utils these are of course optional, I use them on all my projects, @neuekit/reboot is similar to normalize.css or sanitize.css etc. and @neuekit/utils is similar to lodash etc.
pnpm i sass svelte-preprocess @neuekit/reboot @neuekit/utils -D
svelte.config.js
Now we have our packages installed we can adjust our svelte.config.js
This file is pretty much the central control file for how Kit behaves so we do a fair bit in here.
- By importing preprocess from svelte-preprocess we will be able to write SCSS in our svelte files
- Importing both fs and path let us grab the project version from package.json to use later in our meta tag
- Setting
trailingSlash: 'always'
improves consistency for search engines and prevents possible duplicate content warnings - Adding a define item takes the package version we exposed earlier and lets us access it as the variable 'process.env.version'. We use process.env to avoid typescript warnings
- Adding a resolve object lets us create our folder aliases and lets us define the known extensions allowing us to write imports like this:
import Button from '$components/Button'
- The ssr noExternal option may be required for some dependencies if you run into Vite issues
- Preprocess array lets us define preprocess modules like svelte-preprocess
- Finally the preprocess scss prependData option lets us inject code into style tags to make global SCSS code available without importing it everytime
import adapter from '@sveltejs/adapter-auto'
import preprocess from 'svelte-preprocess'
import { readFileSync } from 'fs'
import path from 'path'
const { version } = JSON.parse(readFileSync(new URL('package.json', import.meta.url), 'utf8'))
/** @type {import('@sveltejs/kit').Config} */
export default {
kit: {
adapter: adapter(),
trailingSlash: 'always',
vite: {
define: {
'process.env.version': JSON.stringify(version)
},
resolve: {
alias: {
$components: path.resolve('./src/components'),
$library: path.resolve('./src/library')
},
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.svelte']
},
ssr: {
noExternal: ['@neuekit/utils']
}
}
},
preprocess: [
preprocess({ scss: { prependData: `@import 'src/library/utils.scss';` } })
]
}
jsconfig.json / tsconfig.json
In order to finalise the setup of our new folder aliases we need to add references to our jsconfig.json / tsconfig.json file to help TypeScript understand them
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"$library": ["src/library"],
"$library/*": ["src/library/*"],
"$components": ["src/components"],
"$components/*": ["src/components/*"]
}
},
"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"]
}
src/app.scss
This file will house our global styles, the code below is optional, in my projects I keep all my functions and mixins etc. in utils.scss and import that manually into app.scss as well as the automatic injection we did above into svelte style tags
@import 'library/utils.scss'
src/components
This is the folder we created an alias for above, we can now import components like this: import Button from '$components/Button'
src/library
This is the other folder we created an alias for above, we can now import library files and utilities etc. like this:
import { theme_store } from '$library/stores'
src/library/utils.scss
This file typically holds my SCSS functions alongside any useful mixins and global variables. With the changes we made above they will be exposed in app.scss and any svelte style tag
src/routes/__layout.svelte
Layout wraps every route file (pages), I use this to import my global styles and my reboot. Doing this rather than a link tag in app.html means the files will be hashed and we won't run into any caching issue post deployment.
This is also where I make use of the project version number, which I set in a meta tag in the page head. I use this to check which version clients are looking at and to quickly see if a deployment has landed when i'm not looking at Netlify/Vercel
Note: <slot />
will contain our page contents (index.svelte for example)
<script>
import '@neuekit/reboot/reboot.css'
import '../app.scss'
</script>
<svelte:head>
<meta version="{process.env.version}">
</svelte:head>
<main>
<slot />
</main>
.zshrc
As a little bonus, you can add a terminal function to simplify installing Svelte Kit and keeping it up to date. Feel free to swap pnpm for npm or yarn
kit() {
if [[ $1 = i ]]; then
pnpm init svelte@next . && pnpm i
elif [[ $1 = up ]]; then
pnpm i @sveltejs/kit@next @sveltejs/adapter-auto@next -D
fi
}
Once added you can create a new SvelteKit project with:
kit i
and update to the latest @next releases with:
kit up
That's it!
You made it to the end, I hope some of these points will improve your quality of life when using Svelte Kit as they have mine.
I occasionally tweet sveltey things on twitter @Matt_Pilott
Top comments (0)