DEV Community

Max Core
Max Core

Posted on • Edited on

SvelteKit: How to make code-based router, instead of file-based router [August 2023]

I. Create urls.js somewhere you like it:

const urls = {
    '/'          : {re: /^\/$/,            page: 'src/home.svelte',     layout: 'src/base.svelte', error: 'src/error.svelte'},
    '/signin'    : {re: /^\/signin\/?$/,   page: 'src/signin.svelte',   parent: '/'},  // layout and error will be inherited from url with key '/'
    '/settings'  : {re: /^\/settings\/?$/, page: 'src/settings.svelte', parent: '/', layout: 'src/user.svelte'},  // layout from parent will be combined with custom layout
    '/[username]': {re: /^\/([\w]+)\/?$/,  page: 'src/feed.svelte',     parent: '/', layout: 'src/user.svelte'},
}

export function getRoutes() {
    let result = {}
    for (const [id, item] of Object.entries(Urls)) {
        const parent = item.parent ? result[item.parent] : null;
        const route = {
            id: id,
            pattern: item.re,
            params: item.params || [],
            layout: item.layout ? {
                child_pages: [],
                universal: item.universal,
                server: item.server,
                component: item.layout,
            } : null,
            leaf: {
                universal: item.universal,
                server: item.server,
                component: item.page,
            },
            error: {component: item.error || parent?.error?.component},
            endpoint: item.endpoint ? { file: item.endpoint } : null,
            parent: parent,
        }

        if (!route.params.length) {
            const matches = id.match(/\[([^\]]*)]/g) || [];
            for (const match of matches) {
                route.params.push({
                    name: match.replace('[', '').replace(']', ''),
                    matcher: undefined,
                    optional: false,
                    rest: false,
                    chained: false
                })
            }
        }

        result[id] = route;
    }
    return Object.values(result);
}
Enter fullscreen mode Exit fullscreen mode

2. Add routes to svelte.config.js

import {getRoutes} from './urls.js';

const config = {
    ...
    routes: getRoutes(),
    ...
}
Enter fullscreen mode Exit fullscreen mode

3. Open create_manifest_data/index.js

node_modules/@sveltejs/kit/src/core/sync/create_manifest_data/index.js

a) Find:

prevent_conflicts(routes);

const root = routes[0];
Enter fullscreen mode Exit fullscreen mode

b) Past between that two lines:

routes.length = 0;
routes.push(...config.routes);
Enter fullscreen mode Exit fullscreen mode

c) Find:

routes: sort_routes(routes)
Enter fullscreen mode Exit fullscreen mode

d) Replace with:

routes: routes
Enter fullscreen mode Exit fullscreen mode

4. One could install patch-package, so this changes will be automatically applied in future without manual hacks:

> npm i patch-package
> npx patch-package @sveltejs/kit
Enter fullscreen mode Exit fullscreen mode

package.json:

{
  ...
  "scripts": {
    ...
    "postinstall": "patch-package" // <— add this
Enter fullscreen mode Exit fullscreen mode

That's all!

Top comments (0)