Insights from using SvelteKit + Svelte for a year
Introductory Remarks and Self-Introduction
My name is Ikeda, and I'm in charge of front-end development at KINTO Technologies. Recently, I've been involved in the development and operation of KINTO ONE and the launch of new services and projects.
Introductory Remarks
Recently, various JS frameworks are emerging, such as React, Vue.js, AngularJS, Preact and Ember. Svelte and Solid are two that have been gaining momentum lately. (And personally, I would like to see Mithril.js grow more. You can find more information about it here: https://mithril.js.org). With this in mind, I would like to introduce the KINTO corporate site, the KINTO Technologies corporate site, and my impressions of using Svelte —which is also used in other ongoing products— and some code, including a simple SSG.
What is the SSG (static site generator) introduced in this article?
From a front-end perspective, a request is run every time you access an element, such as API GET to obtain, say, a list of blog articles and then API GET to view an article in detail. What an SSG (static site generator) does is basically create all the relevant API GET content during the build process. As an advantage, in the above example, API communication does not occur when transitioning from the blog list screen to the detailed screen, so the transition is very smooth.
There are various other architectures, such as SPA, ISR, and SSR.
What is Svelte?
Svelte is a framework with an extremely small build size, and as I'll explain later, reading and writing is extremely easy. Also, JS frameworks are nearly equal to virtual DOM, but Svelte does not include a virtual DOM because things like changes to DOM are also described in Vanilla JS during compiling. It doesn't build a virtual DOM or anything else needed for re-rendering; it simply replaces the real DOM when the state of the DOM changes.
Please see below for more details:
JS framework is based on the concept of write less code https://svelte.jp/blog/write-less-code
Product Introduction
KINTO Corporate Site
KINTO's corporate site is created in a SvelteKit (SSG) on [S3 + CloudFront] configuration. After coding, when it is merged into a certain branch, the build task is executed via GitHub Actions, reflected in S3, and distributed with CloudFront. *SvelteKit is an application framework that uses Svelte. It's similar to Next.js using React. See here for details: https://kit.svelte.dev/
KINTO Technologies Corporate Site
https://www.kinto-technologies.com/
KINTO Technologies corporate site uses Svelte (SPA) on [S3 + CloudFront].
While KINTO's corporate site uses the SSG method, KINTO Technologies' corporate site uses the SPA method. This corporate site did not have much content at the stage when the repository was set up, plus the SvelteKit beta version had not yet been released, so Svelte (SPA) was adopted. However, the amount of content is increasing, which begs the question of whether SG is really enough. With that in mind, we're now eagerly awaiting the change to SvelteKit.
What Makes Svelte Different
The biggest difference isn't the library, it's the compiler.
Whether it's Vue or React, the size of a library file will take up the build size as it is, so build size will inevitably increase.
This is a perfect framework for me, because as far as I'm concerned, fast loading speed = justice. And of course, there are plenty of devices and plug-ins that can be used to improve the loading speed and execution speed of other frameworks as well.
Where I Got Stuck When Actually Implementing It
There were really very few places where I got stuck. A simple increment can be written in a small number of lines, like this:
<script>
// define cout
let count = 0;
// onclickで使用する関数
function handleClick() {
count += 1;
}
</script>
<button on:click={handleClick}>
Clicked {count} {count === 1 ? 'time' : 'times'}
</button>
If there's anything, it's because this is only a beta version and there are still destructive changes being made, so it's necessary to pick up information each time this happens. Svelte's unique syntax is easy to understand, so I think it's difficult to get stuck even if you're seeing it for the first time.
There's also another unique syntax called Await blocks
. Take a look at the component that fetches each time you click below. You can write 'await' as is in HTML, and reading is a cinch.
<script>
let promise = getRandomNumber();
async function getRandomNumber() {
const URL = "xxx"
const res = await fetch(URL);
const text = await res.text();
if (res.ok) {
return text;
} else {
throw new Error(text);
}
}
function handleClick() {
promise = getRandomNumber();
}
</script>
{#await promise}
<p>...waiting</p>
{:then data}
<p>{data}</p>
{:catch error}
<p style="color: red">{error.message}</p>
{/await}
For readers who think, "Is it really that easy? I'm not convinced."
Don't knock it until you've tried it.
Why not give it a try for yourself?
Try It Out!
Practice
We'll reference the SvelteKit official site while we make it. First, let's make a SvelteKit project in the appropriate directory: sh:terminal npm init svelte static-site-sveltekit
Next, you'll be given a choice, so select Skeleton project and any other options as you wish. It's convenient that there's a CLI.
When selecting, it should generally look something like this:
The following is adopted in this article: eslint + JavaScript with JSDoc comments + prettier + Playwright
Generating a Static Site
This time, I'm going to try the so-called Jamstack, so I'd like to include some sort of communication.
I'll try to obtain an article about Svelte from dev.to.
*This article does not cover styling, as it increases the volume.
First, let's make the page with the list of articles.
<script context="module">
export async function load() {
let articles
try {
articles = await fetch(`https://dev.to/api/articles?tag=svelte&per_page=5&page=1`);
articles = await articles.json();
console.log(articles)
} catch (e) {
console.log(e)
}
return {
props: {
articles
}
}
}
</script>
<script>
export let articles
const PostArticles = articles
</script>
<svelte:head>
<title>Blog</title>
</svelte:head>
<div>
<h1>Svelte devto Articles</h1>
{#each PostArticles as article}
<div>
<header>
<h2>{article.title}</h2>
<h4>Tags: {article.tags}</h4>
</header>
<p>
{article.description}
</p>
<a href={`/blog/${article.id}`}>MORE</a>
</div>
{/each} {#if PostArticles.length === 0}
<div>No Articles</div>
{/if}
</div>
With async await
, you can obtain the article by fetching the dev.to API, storing it in articles, assigning it to PostArticles and rendering it with Svelte's 'each' syntax.
You can export what is written using context="module"
. In other words, it can be called even within the same component. Then pass it to the DOM in the next script section and parse it. It's very clear.
The good thing about Svelte is that the sections are clear, so it's easy for the writer and very simple to follow.
People say that Vue is easy and React is simple, but I think Svelte is both easy and simple.
I digress, but let's make a detailed article next.
<script context="module">
export async function load({ fetch, params }) {
let article
try {
article = await fetch(`https://dev.to/api/articles/${params.slug}`);
article = await article.json();
console.log(article)
} catch (e) {
console.log(e)
}
return {
props: {
article
}
}
}
</script>
<script>
export let article
const post = article
</script>
<svelte:head>
<title>{article.title}</title>
</svelte:head>
<div>
<div>
<h1>{post.title}</h1>
<section>
{@html post.body_html}
</section>
</div>
</div>
That's it. Params contains various kinds of information, so you just need to get that information, pass it and render it. That's all there is to it.
Let's Build!
I've written most of the code. So finally, let's build. As it is, there's no instruction to static generate inside svete.config.js
. https://kit.svelte.jp/docs/adapters
As mentioned in the above, let's use @sveltejs/adapter-static
. Let's start by installing it.
sh:terminal yarn add @sveltejs/adapter-static@next -D
Next, rewrite svelte.config.js.
import adapter from '@sveltejs/adapter-static';
/** @type {import('@sveltejs/kit').Config} */
const config = { kit: If { // prerender is not entered, an error will occur prerender: { default: true }, adapter: adapter({ pages: 'build', assets: 'build', fallback: null }) } }
export default config;
Now, yarn build || npm run build
The created article was stored in the build directory. Let's see if we can actually obtain the article.
yarn preview || npm run preview
We had no problems seeing it, right?
Now, all you need to do is store the article according to the project, such as S3, hosting service, or rental server.
Impressions
Once you've tried Svelte out for yourself and seen the code with your own eyes, I'm confident you'll get a sense of what makes it special. You can create an application with less code thanks to Svelte's write less code concept. So, how about it? Did that come across?
Although it's still in development as a beta version, I think you can tell this is a JS framework with a lot to offer. Have a good Svelte life, everyone.
関連記事 | Related Posts
We are hiring!
【フロントエンドエンジニア(コンテンツ開発)】新車サブスク開発G/東京
新車サブスク開発グループについてTOYOTAのクルマのサブスクリプションサービスである『 KINTO ONE 』のWebサイトの開発、運用をしています。業務内容トヨタグループの金融、モビリティサービスの内製開発組織である同社にて、自社サービスである、クルマのサブスクリプションサービス『KINTO ONE』のWebサイトコンテンツの開発・運用業務を担っていただきます。
【フロントエンドエンジニア】新車サブスク開発G/東京
新車サブスク開発グループについてTOYOTAのクルマのサブスクリプションサービスである『 KINTO ONE 』のWebサイトの開発、運用をしています。業務内容トヨタグループの金融、モビリティサービスの内製開発組織である同社にて、自社サービスである、TOYOTAのクルマのサブスクリプションサービス『KINTO ONE』のWebサイトの開発、運用を行っていただきます。