mirror of
https://github.com/kunkunsh/kunkun.git
synced 2025-05-24 13:45:03 +00:00
[perf]: reduce desktop frontend bundle size from 10MB to 2MB (#14)
* perf: reduce desktop frontend bundle from 10 to 2MB Use shiki fine-grained bundle, avoid bundling all languages and themes * feat: add cross-page transition for ext store back button with gasp Flip * refactor: move StoreListing.svelte in @kksh/ui back to desktop I realized that StoreListing is a pure wrapper, all the interactions are done with props. Even if this component is later used in other projects, it either lacks flexibility or require more changes. So it's moved back to desktop as a regular +page.svelte
This commit is contained in:
parent
11cc79627d
commit
d3af1b7b02
@ -8,7 +8,9 @@
|
||||
let flipState: Flip.FlipState
|
||||
|
||||
beforeNavigate(() => {
|
||||
flipState = Flip.getState(`.${Constants.CLASSNAMES.EXT_LOGO}`)
|
||||
flipState = Flip.getState(
|
||||
`.${Constants.CLASSNAMES.EXT_LOGO}, .${Constants.CLASSNAMES.BACK_BUTTON}`
|
||||
)
|
||||
})
|
||||
|
||||
afterNavigate(() => {
|
||||
@ -17,7 +19,7 @@
|
||||
}
|
||||
|
||||
Flip.from(flipState, {
|
||||
targets: ".kk-ext-logo",
|
||||
targets: `.${Constants.CLASSNAMES.EXT_LOGO}, .${Constants.CLASSNAMES.BACK_BUTTON}`,
|
||||
duration: 0.5,
|
||||
absolute: true,
|
||||
scale: true,
|
||||
|
@ -2,21 +2,19 @@
|
||||
import { getExtensionsFolder } from "@/constants"
|
||||
import { appState, extensions } from "@/stores"
|
||||
import { supabaseAPI } from "@/supabase"
|
||||
import { goBackOnEscape, goBackOnEscapeClearSearchTerm } from "@/utils/key"
|
||||
import { goBackOnEscapeClearSearchTerm } from "@/utils/key"
|
||||
import { goBack } from "@/utils/route"
|
||||
import { isCompatible } from "@kksh/api"
|
||||
import { SBExt } from "@kksh/api/supabase"
|
||||
import { isUpgradable } from "@kksh/extension"
|
||||
import { Command } from "@kksh/svelte5"
|
||||
import { StoreListing } from "@kksh/ui/extension"
|
||||
import { greaterThan, parse as parseSemver } from "@std/semver"
|
||||
import { Button, Command } from "@kksh/svelte5"
|
||||
import { Constants } from "@kksh/ui"
|
||||
import { ExtListItem } from "@kksh/ui/extension"
|
||||
import { CustomCommandInput, GlobalCommandPaletteFooter } from "@kksh/ui/main"
|
||||
import { goto } from "$app/navigation"
|
||||
import { onMount } from "svelte"
|
||||
import { ArrowLeft } from "lucide-svelte"
|
||||
import { toast } from "svelte-sonner"
|
||||
import { get } from "svelte/store"
|
||||
import { type PageData } from "./$types"
|
||||
|
||||
let { data }: { data: PageData } = $props()
|
||||
let { data } = $props()
|
||||
const { storeExtList, installedStoreExts, installedExtsMap, upgradableExpsMap } = data
|
||||
|
||||
// function isUpgradeable(item: DbExtItem): boolean {
|
||||
@ -67,15 +65,37 @@
|
||||
</script>
|
||||
|
||||
<svelte:window on:keydown={goBackOnEscapeClearSearchTerm} />
|
||||
<StoreListing
|
||||
{storeExtList}
|
||||
{appState}
|
||||
installedExtsMap={$installedExtsMap}
|
||||
upgradableExpsMap={$upgradableExpsMap}
|
||||
{onExtItemSelected}
|
||||
{onExtItemUpgrade}
|
||||
{onExtItemInstall}
|
||||
{isUpgradable}
|
||||
bind:searchTerm={$appState.searchTerm}
|
||||
onGoBack={goBack}
|
||||
/>
|
||||
|
||||
{#snippet leftSlot()}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onclick={goBack}
|
||||
class={Constants.CLASSNAMES.BACK_BUTTON}
|
||||
data-flip-id={Constants.CLASSNAMES.BACK_BUTTON}
|
||||
>
|
||||
<ArrowLeft class="size-4" />
|
||||
</Button>
|
||||
{/snippet}
|
||||
<Command.Root class="h-screen rounded-lg border shadow-md">
|
||||
<CustomCommandInput
|
||||
autofocus
|
||||
placeholder="Type a command or search..."
|
||||
{leftSlot}
|
||||
bind:value={$appState.searchTerm}
|
||||
/>
|
||||
<Command.List class="max-h-screen grow">
|
||||
<Command.Empty>No results found.</Command.Empty>
|
||||
{#each storeExtList as ext}
|
||||
<ExtListItem
|
||||
{ext}
|
||||
installedVersion={$installedExtsMap[ext.identifier]}
|
||||
isUpgradable={!!$upgradableExpsMap[ext.identifier]}
|
||||
onSelect={() => onExtItemSelected(ext)}
|
||||
onUpgrade={() => onExtItemUpgrade(ext)}
|
||||
onInstall={() => onExtItemInstall(ext)}
|
||||
/>
|
||||
{/each}
|
||||
</Command.List>
|
||||
<GlobalCommandPaletteFooter />
|
||||
</Command.Root>
|
||||
|
@ -4,6 +4,8 @@
|
||||
import { supabaseAPI } from "@/supabase"
|
||||
import { goBack } from "@/utils/route.js"
|
||||
import { Button } from "@kksh/svelte5"
|
||||
import { cn } from "@kksh/svelte5/utils"
|
||||
import { Constants } from "@kksh/ui"
|
||||
import { StoreExtDetail } from "@kksh/ui/extension"
|
||||
import { greaterThan, parse as parseSemver } from "@std/semver"
|
||||
import { error } from "@tauri-apps/plugin-log"
|
||||
@ -139,7 +141,13 @@
|
||||
|
||||
<svelte:window on:keydown={handleKeydown} />
|
||||
|
||||
<Button variant="outline" size="icon" class="fixed left-3 top-3" onclick={goBack}>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
class={cn("fixed left-3 top-3", Constants.CLASSNAMES.BACK_BUTTON)}
|
||||
data-flip-id={Constants.CLASSNAMES.BACK_BUTTON}
|
||||
onclick={goBack}
|
||||
>
|
||||
<ArrowLeftIcon />
|
||||
</Button>
|
||||
<StoreExtDetail
|
||||
|
@ -1,32 +1,35 @@
|
||||
import { defineConfig } from "vite";
|
||||
import { sveltekit } from "@sveltejs/kit/vite";
|
||||
import { sveltekit } from "@sveltejs/kit/vite"
|
||||
import { defineConfig } from "vite"
|
||||
|
||||
// @ts-expect-error process is a nodejs global
|
||||
const host = process.env.TAURI_DEV_HOST;
|
||||
const host = process.env.TAURI_DEV_HOST
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig(async () => ({
|
||||
plugins: [sveltekit()],
|
||||
plugins: [sveltekit()],
|
||||
|
||||
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
|
||||
//
|
||||
// 1. prevent vite from obscuring rust errors
|
||||
clearScreen: false,
|
||||
// 2. tauri expects a fixed port, fail if that port is not available
|
||||
server: {
|
||||
port: 1420,
|
||||
strictPort: true,
|
||||
host: host || false,
|
||||
hmr: host
|
||||
? {
|
||||
protocol: "ws",
|
||||
host,
|
||||
port: 1421,
|
||||
}
|
||||
: undefined,
|
||||
watch: {
|
||||
// 3. tell vite to ignore watching `src-tauri`
|
||||
ignored: ["**/src-tauri/**"],
|
||||
},
|
||||
},
|
||||
}));
|
||||
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
|
||||
//
|
||||
// 1. prevent vite from obscuring rust errors
|
||||
clearScreen: false,
|
||||
// 2. tauri expects a fixed port, fail if that port is not available
|
||||
server: {
|
||||
port: 1420,
|
||||
strictPort: true,
|
||||
host: host || false,
|
||||
hmr: host
|
||||
? {
|
||||
protocol: "ws",
|
||||
host,
|
||||
port: 1421
|
||||
}
|
||||
: undefined,
|
||||
watch: {
|
||||
// 3. tell vite to ignore watching `src-tauri`
|
||||
ignored: ["**/src-tauri/**"]
|
||||
}
|
||||
},
|
||||
build: {
|
||||
minify: true
|
||||
}
|
||||
}))
|
||||
|
@ -1,6 +1,10 @@
|
||||
<!-- Don't Load All languages and themes, use fine-grained bundle-->
|
||||
<!-- https://shiki.style/guide/bundles#fine-grained-bundle -->
|
||||
<script lang="ts">
|
||||
import { cn } from "@kksh/ui/utils"
|
||||
import { codeToHtml } from "shiki"
|
||||
import { mode } from "mode-watcher"
|
||||
import { createHighlighterCore } from "shiki/core"
|
||||
import { createOnigurumaEngine } from "shiki/engine/oniguruma"
|
||||
import { onMount } from "svelte"
|
||||
|
||||
const {
|
||||
@ -8,12 +12,23 @@
|
||||
lang,
|
||||
theme,
|
||||
class: className
|
||||
}: { code: string; lang: string; theme?: string; class?: string } = $props()
|
||||
}: {
|
||||
code: string
|
||||
lang: "json" | "typescript"
|
||||
theme?: "vitesse-dark" | "vitesse-light"
|
||||
class?: string
|
||||
} = $props()
|
||||
let html = $state("")
|
||||
|
||||
onMount(async () => {
|
||||
html = await codeToHtml(code, {
|
||||
lang: lang,
|
||||
theme: theme ?? "vitesse-dark"
|
||||
const highlighter = await createHighlighterCore({
|
||||
themes: [import("shiki/themes/vitesse-dark.mjs"), import("shiki/themes/vitesse-light.mjs")],
|
||||
langs: [import("shiki/langs/json.mjs"), import("shiki/langs/typescript.mjs")],
|
||||
engine: createOnigurumaEngine(import("shiki/wasm"))
|
||||
})
|
||||
html = highlighter.codeToHtml(code, {
|
||||
lang,
|
||||
theme: theme ?? ($mode === "dark" ? "vitesse-dark" : "vitesse-light")
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
@ -14,7 +14,7 @@
|
||||
</script>
|
||||
|
||||
<CommandPrimitive.Group
|
||||
class={cn("text-foreground overflow-hidden p-1 select-none", className)}
|
||||
class={cn("text-foreground select-none overflow-hidden p-1", className)}
|
||||
bind:ref
|
||||
{...restProps}
|
||||
>
|
||||
|
@ -1,63 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { SBExt } from "@kksh/api/supabase"
|
||||
import { Button, Command } from "@kksh/svelte5"
|
||||
import { CustomCommandInput, GlobalCommandPaletteFooter } from "@kksh/ui/main"
|
||||
import { cn } from "@kksh/ui/utils"
|
||||
import { afterNavigate, beforeNavigate } from "$app/navigation"
|
||||
import { type Snippet } from "svelte"
|
||||
import ArrowLeft from "svelte-radix/ArrowLeft.svelte"
|
||||
import type { Writable } from "svelte/store"
|
||||
import ExtListItem from "./ExtListItem.svelte"
|
||||
|
||||
let {
|
||||
storeExtList,
|
||||
installedExtsMap,
|
||||
onExtItemSelected,
|
||||
onExtItemUpgrade,
|
||||
onExtItemInstall,
|
||||
upgradableExpsMap,
|
||||
isUpgradable,
|
||||
appState,
|
||||
onGoBack,
|
||||
searchTerm = $bindable("")
|
||||
}: {
|
||||
storeExtList: SBExt[]
|
||||
installedExtsMap: Record<string, string>
|
||||
onExtItemSelected: (ext: SBExt) => void
|
||||
onExtItemUpgrade: (ext: SBExt) => void
|
||||
onExtItemInstall: (ext: SBExt) => void
|
||||
upgradableExpsMap: Record<string, boolean>
|
||||
isUpgradable: (dbExt: SBExt, installedExtVersion: string) => boolean
|
||||
onGoBack?: () => void
|
||||
appState: Writable<{ searchTerm: string }>
|
||||
searchTerm: string
|
||||
} = $props()
|
||||
</script>
|
||||
|
||||
{#snippet leftSlot()}
|
||||
<Button variant="outline" size="icon" onclick={onGoBack}>
|
||||
<ArrowLeft class="size-4" />
|
||||
</Button>
|
||||
{/snippet}
|
||||
<Command.Root class="h-screen rounded-lg border shadow-md">
|
||||
<CustomCommandInput
|
||||
autofocus
|
||||
placeholder="Type a command or search..."
|
||||
leftSlot={leftSlot as Snippet}
|
||||
bind:value={searchTerm}
|
||||
/>
|
||||
<Command.List class="max-h-screen grow">
|
||||
<Command.Empty>No results found.</Command.Empty>
|
||||
{#each storeExtList as ext}
|
||||
<ExtListItem
|
||||
{ext}
|
||||
installedVersion={installedExtsMap[ext.identifier]}
|
||||
isUpgradable={!!upgradableExpsMap[ext.identifier]}
|
||||
onSelect={() => onExtItemSelected(ext)}
|
||||
onUpgrade={() => onExtItemUpgrade(ext)}
|
||||
onInstall={() => onExtItemInstall(ext)}
|
||||
/>
|
||||
{/each}
|
||||
</Command.List>
|
||||
<GlobalCommandPaletteFooter />
|
||||
</Command.Root>
|
@ -1,4 +1,3 @@
|
||||
export { default as ExtListItem } from "./ExtListItem.svelte"
|
||||
export { default as StoreListing } from "./StoreListing.svelte"
|
||||
export { default as StoreExtDetail } from "./StoreExtDetail.svelte"
|
||||
export { default as PermissionInspector } from "./PermissionInspector.svelte"
|
||||
|
@ -1,3 +1,4 @@
|
||||
export const CLASSNAMES = {
|
||||
EXT_LOGO: "kk-ext-logo"
|
||||
EXT_LOGO: "kk-ext-logo",
|
||||
BACK_BUTTON: "kk-back-button"
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user