SvelteKit:一个基于Svelte开发服务端渲染网站的框架

作者:renzp94
时间:2021-05-24 08:59:55

SvelteKit是一个用于构建各种规模的Web应用程序的框架且具有出色的开发体验和基于文件系统的灵活路由。
与单页应用程序不同,SvelteKit不会在SEO,渐进增强或初始加载体验上做出让步-但与传统的服务器呈现的应用程序不同,导航是即时的,类似于应用程序的感觉。(摘自SvelteKit官网)

入门

npm init svelte@next my-app
cd my-app
npm install
npm run dev

SvelteKit是基于Svelte构建的一个服务端渲染框架,对标的是ReactNext框架,最初是基于Snowpack打包的,后来Vite出来之后,团队将其迁移到了Vite。此框架有三大特点:

  • 基于Svelte
  • 友好的服务端渲染,SEO,渐进式增强,以及SPA的流畅导航。
  • 使用基于文件系统的路由,代码拆分,离线支持。

总之如果你想尝试Svelte技术栈的话,此框架是开发的不二选择。你现在的所看到的网站就是用SvelteKit开发的静态网站。

router(路由)

SvelteKit是基于文件系统的生成的路由,默认在src/routes.svelte文件都是一个页面,路由就是文件名且区分大小写。如:routes/about.svelte/aboutroutes/userHome.svelte/userHome。所以建议使用短横线命名法命名文件,即:user-home

嵌套路由

实现嵌套路由就只需嵌套目录即可,目录下的index.svelte会自动将当前目录名转换为路由。如:routes/news/index.svelte/newsroutes/news/list.svelte/news/list

动态路由

如果需要使用动态路由可以使用[路由名].svelte来命名文件,如:routes/news/[id].svelte/news/:id。其动态的路由可作为params参数传入页面中,获取方法会在下面说明。
如果需要多个动态参数传入的话,可使用-分割。如:routes/news/[category]-[id].svelte/news/:idcategory/:id
如果路由的动态数量未知,可以使用剩余参数,即:routes/[tree]/[dir]/[...file]/:tree/:dir/...file。如:routes/master/docs/router/01.md解析为mastertreedirdocsfilerouter/01.md

layout(布局)

如果需要使用布局模板的话,可以在其目录下创建__layout.svelte,则此目录下的所有页面都会应用此布局。布局页中必须含有<slot></slot>,其代表页面内容在布局页的位置。如果在routes下创建一个__layout.svelte则所有页面都会应用此布局,如果想重置布局,则在其目录下创建一个__layout.reset.svelte文件即可,然后此目录下的所有页面都会应用此布局,而不会布局中含有布局。如果需要嵌套布局则在目录下继续创建一个__layout.svelte即可。

error(错误页面)

如果想自定义页面错误页的话,可以在目录下创建一个__error.svelte,默认就近查找,如果没有就一直往上一级目录查找,知道routes目录下,如果都没有,则使用默认的错误页,建议在routes下创建一个__error.svelte
错误页面有一个load函数,其接受一个对象:{error,status}

<script context="module">
    export function load({ error, status }) {
        return {
            props: {
                title: `${status}: ${error.message}`
            }
        };
    }
</script>

<script>
    export let title;
</script>

<h1>{title}</h1>

load 函数

每个页面、布局、错误页都有一个组件创建前运行的函数:load,此函数在服务端渲染和客户端中运行,并允许获取页面数据。此函数要在script context="module标签中。 load 函数的接收和输出的参数类型为:

// 输入
type LoadInput = {
    page: {
        host: string;
        path: string;
        params: Record<string, string>;
        query: URLSearchParams;
    };
    fetch: (info: RequestInfo, init?: RequestInit) => Promise<Response>;
    session: any;
    context: Record<string, any>;
};
// 输出
type LoadOutput = {
    status?: number;
    error?: string | Error;
    redirect?: string;
    props?: Record<string, any>;
    context?: Record<string, any>;
    maxage?: number;
};
<script context="module">
    export function load({
        page: {
            params: { id }
        }
    }) {
        return {
            props: {
                title: '详情',
                id
            }
        };
    }
</script>

<script>
    export let title;
    export let id;
</script>

<h1>{title}</h1><div>当前详情ID:{id}</div>
  • load函数里面应该使用fetch方法获取数据,以避免重复的网络请求
  • 不应该使用windowdocument灯任何浏览器对象

服务端渲染数据请求

SvelteKit允许你为每一个页面提供了一个同名的以.json.js为后缀的文件,此文件中可以导出一个异步的函数,一般在此文件中获取数据并返回,通过load函数加载数据。.json.js文件支持三个异步函数:getpostdel。异步函数的接收和输出参数类型:

type Headers = Record<string, string>;

type Request<Locals = Record<string, any>, Body = unknown> = {
    method: string;
    host: string;
    headers: Headers;
    path: string;
    params: Record<string, string>;
    query: URLSearchParams;
    rawBody: string | Uint8Array;
    body: ParameterizedBody<Body>;
    locals: Locals; // populated by hooks handle
};

type EndpointOutput = {
    status?: number;
    headers?: Headers;
    body?: string | Uint8Array | JSONValue;
};

type RequestHandler<Locals = Record<string, any>> = (
    request: Request<Locals>
) => void | EndpointOutput | Promise<EndpointOutput>;

news/[id].svelte

<script context="module">
    export const load = async ({
        page: {
            params: { id }
        },
        fetch
    }) => {
        const res = await fetch(`${id}.json`);

        if (res.ok) {
            const data = await res.json();
            return {
                props: {
                    details: data
                }
            };
        }

        const { message } = await res.json();

        return {
            error: new Error(message)
        };
    };
</script>

<script>
    export let details;
</script>

<h1>{details.title}</h1><div>{details.description}</div>

news/[id].json.js

import { fetchDetails } from 'api';

export const get: RequestHandler<string> = async ({ params: { id } }) => {
    const data = fetchDetails(id);

    return {
        body: data
    };
};

以上就是基本的SvelteKit介绍,更多的详细介绍请前往官网查看。