Last active
January 5, 2023 04:34
-
-
Save hakimzulkufli/7f03908995794bc2335fe5c0a6b96c53 to your computer and use it in GitHub Desktop.
Detect and Resolve layout files automatically like SvelteKit using Inertia.js (Laravel + Vite + Svelte)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { createInertiaApp } from "@inertiajs/inertia-svelte"; | |
import { InertiaProgress } from "@inertiajs/progress"; | |
import { resolvePageComponent } from "laravel-vite-plugin/inertia-helpers"; | |
import DefaultLayout from "$/Pages/__layout.svelte"; | |
const appName = window.document.getElementsByTagName("title")[0]?.innerText || "App Name"; | |
const layouts = import.meta.glob('./Pages/**/__layout.svelte'); | |
const pages = import.meta.glob('./Pages/**/*.svelte'); | |
/** | |
* Resolve layout file recursively a la SvelteKit. | |
* | |
* @param { string } page Path to current page. | |
*/ | |
async function resolveLayoutFile(page, loadedLayouts = []) | |
{ | |
if (!page) { | |
return loadedLayouts; | |
} | |
const path = (page.substr(0, page.lastIndexOf('/'))); | |
const layout = layouts[path + '/__layout.svelte']; | |
if (typeof layout === 'function') { | |
loadedLayouts.unshift(layout()); | |
} | |
return resolveLayoutFile(path, loadedLayouts); | |
}; | |
/** | |
* Smartly resolve page component by the following convention: | |
* 1. Treat as directory and find Index.svelte; | |
* 2. If fails, treat as path to a page component. | |
* | |
* @param { string } pageName Page name. | |
* @returns Page component. | |
*/ | |
async function resolvePage(pageName) | |
{ | |
var page, name = pageName; | |
try { | |
page = await resolvePageComponent(`./Pages/${pageName}/Index.svelte`, pages); | |
name = `${pageName}/Index.svelte`; | |
} catch (error) { | |
page = await resolvePageComponent(`./Pages/${pageName}.svelte`, pages); | |
} | |
return { | |
page: page, | |
name: name | |
}; | |
} | |
/** | |
* Resolve page component and load layout file. | |
* | |
* @param { string } pageName Page name. | |
* @returns Page component. | |
*/ | |
async function importPage(pageName) | |
{ | |
return await resolvePage(pageName) | |
.then(async ({page, name}) => { | |
const module = page; | |
const layouts = (await resolveLayoutFile(`./Pages/${name}.svelte`)); | |
/** | |
* Technically you won't need to specify a fallback DefaultLayout | |
* since we're looking for it recursively but just in case you there's none found | |
* and have a default layout stored somewhere, we can tell it to use that instead. | |
*/ | |
const loadedLayouts = (await Promise.all(layouts)).map((layout) => layout.default) || DefaultLayout; | |
return Object.assign({ layout: loadedLayouts }, module); | |
}); | |
} | |
/** | |
* Render Inertia.js app. | |
*/ | |
createInertiaApp({ | |
resolve: (pageName) => importPage(pageName), | |
setup({ el, App, props }) { | |
new App({ target: el, props }); | |
} | |
}); | |
/** | |
* Progress bar. | |
*/ | |
InertiaProgress.init({ color: "#4B5563" }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is my attempt to mimic SvelteKit's layout files loading by finding and nesting them recursively up the directories. I really liked how SvelteKit handled it. This is far more easier than having to define the layout on every file, especially when you have multiple layouts.
I don't know how performant this is. Never tried with an SSR. I've only just started using this method in a brand new project.