[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:
Huakun Shen 2024-11-04 16:51:31 -05:00 committed by GitHub
parent 11cc79627d
commit d3af1b7b02
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 106 additions and 121 deletions

View File

@ -8,7 +8,9 @@
let flipState: Flip.FlipState let flipState: Flip.FlipState
beforeNavigate(() => { beforeNavigate(() => {
flipState = Flip.getState(`.${Constants.CLASSNAMES.EXT_LOGO}`) flipState = Flip.getState(
`.${Constants.CLASSNAMES.EXT_LOGO}, .${Constants.CLASSNAMES.BACK_BUTTON}`
)
}) })
afterNavigate(() => { afterNavigate(() => {
@ -17,7 +19,7 @@
} }
Flip.from(flipState, { Flip.from(flipState, {
targets: ".kk-ext-logo", targets: `.${Constants.CLASSNAMES.EXT_LOGO}, .${Constants.CLASSNAMES.BACK_BUTTON}`,
duration: 0.5, duration: 0.5,
absolute: true, absolute: true,
scale: true, scale: true,

View File

@ -2,21 +2,19 @@
import { getExtensionsFolder } from "@/constants" import { getExtensionsFolder } from "@/constants"
import { appState, extensions } from "@/stores" import { appState, extensions } from "@/stores"
import { supabaseAPI } from "@/supabase" import { supabaseAPI } from "@/supabase"
import { goBackOnEscape, goBackOnEscapeClearSearchTerm } from "@/utils/key" import { goBackOnEscapeClearSearchTerm } from "@/utils/key"
import { goBack } from "@/utils/route" import { goBack } from "@/utils/route"
import { isCompatible } from "@kksh/api"
import { SBExt } from "@kksh/api/supabase" import { SBExt } from "@kksh/api/supabase"
import { isUpgradable } from "@kksh/extension" import { isUpgradable } from "@kksh/extension"
import { Command } from "@kksh/svelte5" import { Button, Command } from "@kksh/svelte5"
import { StoreListing } from "@kksh/ui/extension" import { Constants } from "@kksh/ui"
import { greaterThan, parse as parseSemver } from "@std/semver" import { ExtListItem } from "@kksh/ui/extension"
import { CustomCommandInput, GlobalCommandPaletteFooter } from "@kksh/ui/main"
import { goto } from "$app/navigation" import { goto } from "$app/navigation"
import { onMount } from "svelte" import { ArrowLeft } from "lucide-svelte"
import { toast } from "svelte-sonner" 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 const { storeExtList, installedStoreExts, installedExtsMap, upgradableExpsMap } = data
// function isUpgradeable(item: DbExtItem): boolean { // function isUpgradeable(item: DbExtItem): boolean {
@ -67,15 +65,37 @@
</script> </script>
<svelte:window on:keydown={goBackOnEscapeClearSearchTerm} /> <svelte:window on:keydown={goBackOnEscapeClearSearchTerm} />
<StoreListing
{storeExtList} {#snippet leftSlot()}
{appState} <Button
installedExtsMap={$installedExtsMap} variant="outline"
upgradableExpsMap={$upgradableExpsMap} size="icon"
{onExtItemSelected} onclick={goBack}
{onExtItemUpgrade} class={Constants.CLASSNAMES.BACK_BUTTON}
{onExtItemInstall} data-flip-id={Constants.CLASSNAMES.BACK_BUTTON}
{isUpgradable} >
bind:searchTerm={$appState.searchTerm} <ArrowLeft class="size-4" />
onGoBack={goBack} </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>

View File

@ -4,6 +4,8 @@
import { supabaseAPI } from "@/supabase" import { supabaseAPI } from "@/supabase"
import { goBack } from "@/utils/route.js" import { goBack } from "@/utils/route.js"
import { Button } from "@kksh/svelte5" import { Button } from "@kksh/svelte5"
import { cn } from "@kksh/svelte5/utils"
import { Constants } from "@kksh/ui"
import { StoreExtDetail } from "@kksh/ui/extension" import { StoreExtDetail } from "@kksh/ui/extension"
import { greaterThan, parse as parseSemver } from "@std/semver" import { greaterThan, parse as parseSemver } from "@std/semver"
import { error } from "@tauri-apps/plugin-log" import { error } from "@tauri-apps/plugin-log"
@ -139,7 +141,13 @@
<svelte:window on:keydown={handleKeydown} /> <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 /> <ArrowLeftIcon />
</Button> </Button>
<StoreExtDetail <StoreExtDetail

View File

@ -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 // @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/ // https://vitejs.dev/config/
export default defineConfig(async () => ({ export default defineConfig(async () => ({
plugins: [sveltekit()], plugins: [sveltekit()],
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build` // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
// //
// 1. prevent vite from obscuring rust errors // 1. prevent vite from obscuring rust errors
clearScreen: false, clearScreen: false,
// 2. tauri expects a fixed port, fail if that port is not available // 2. tauri expects a fixed port, fail if that port is not available
server: { server: {
port: 1420, port: 1420,
strictPort: true, strictPort: true,
host: host || false, host: host || false,
hmr: host hmr: host
? { ? {
protocol: "ws", protocol: "ws",
host, host,
port: 1421, port: 1421
} }
: undefined, : undefined,
watch: { watch: {
// 3. tell vite to ignore watching `src-tauri` // 3. tell vite to ignore watching `src-tauri`
ignored: ["**/src-tauri/**"], ignored: ["**/src-tauri/**"]
}, }
}, },
})); build: {
minify: true
}
}))

View File

@ -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"> <script lang="ts">
import { cn } from "@kksh/ui/utils" 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" import { onMount } from "svelte"
const { const {
@ -8,12 +12,23 @@
lang, lang,
theme, theme,
class: className 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("") let html = $state("")
onMount(async () => { onMount(async () => {
html = await codeToHtml(code, { const highlighter = await createHighlighterCore({
lang: lang, themes: [import("shiki/themes/vitesse-dark.mjs"), import("shiki/themes/vitesse-light.mjs")],
theme: theme ?? "vitesse-dark" 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> </script>

View File

@ -14,7 +14,7 @@
</script> </script>
<CommandPrimitive.Group <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 bind:ref
{...restProps} {...restProps}
> >

View File

@ -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>

View File

@ -1,4 +1,3 @@
export { default as ExtListItem } from "./ExtListItem.svelte" export { default as ExtListItem } from "./ExtListItem.svelte"
export { default as StoreListing } from "./StoreListing.svelte"
export { default as StoreExtDetail } from "./StoreExtDetail.svelte" export { default as StoreExtDetail } from "./StoreExtDetail.svelte"
export { default as PermissionInspector } from "./PermissionInspector.svelte" export { default as PermissionInspector } from "./PermissionInspector.svelte"

View File

@ -1,3 +1,4 @@
export const CLASSNAMES = { export const CLASSNAMES = {
EXT_LOGO: "kk-ext-logo" EXT_LOGO: "kk-ext-logo",
BACK_BUTTON: "kk-back-button"
} }