From d3af1b7b026a26ecdb5d9c40f3b73bc82cdfb339 Mon Sep 17 00:00:00 2001 From: Huakun Shen Date: Mon, 4 Nov 2024 16:51:31 -0500 Subject: [PATCH 1/2] [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 --- .../src/routes/extension/store/+layout.svelte | 6 +- .../src/routes/extension/store/+page.svelte | 62 +++++++++++------- .../extension/store/[identifier]/+page.svelte | 10 ++- apps/desktop/vite.config.js | 55 ++++++++-------- packages/ui/src/components/code/shiki.svelte | 25 ++++++-- .../custom/draggable-command-group.svelte | 2 +- .../components/extension/StoreListing.svelte | 63 ------------------- packages/ui/src/components/extension/index.ts | 1 - packages/ui/src/constants.ts | 3 +- 9 files changed, 106 insertions(+), 121 deletions(-) delete mode 100644 packages/ui/src/components/extension/StoreListing.svelte diff --git a/apps/desktop/src/routes/extension/store/+layout.svelte b/apps/desktop/src/routes/extension/store/+layout.svelte index f1c04bd..965001f 100644 --- a/apps/desktop/src/routes/extension/store/+layout.svelte +++ b/apps/desktop/src/routes/extension/store/+layout.svelte @@ -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, diff --git a/apps/desktop/src/routes/extension/store/+page.svelte b/apps/desktop/src/routes/extension/store/+page.svelte index 74f3680..7f53ef9 100644 --- a/apps/desktop/src/routes/extension/store/+page.svelte +++ b/apps/desktop/src/routes/extension/store/+page.svelte @@ -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 @@ - + +{#snippet leftSlot()} + +{/snippet} + + + + No results found. + {#each storeExtList as ext} + onExtItemSelected(ext)} + onUpgrade={() => onExtItemUpgrade(ext)} + onInstall={() => onExtItemInstall(ext)} + /> + {/each} + + + diff --git a/apps/desktop/src/routes/extension/store/[identifier]/+page.svelte b/apps/desktop/src/routes/extension/store/[identifier]/+page.svelte index 23d82af..67ce854 100644 --- a/apps/desktop/src/routes/extension/store/[identifier]/+page.svelte +++ b/apps/desktop/src/routes/extension/store/[identifier]/+page.svelte @@ -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 @@ - ({ - 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 + } +})) diff --git a/packages/ui/src/components/code/shiki.svelte b/packages/ui/src/components/code/shiki.svelte index 2d663e2..6c3ed2b 100644 --- a/packages/ui/src/components/code/shiki.svelte +++ b/packages/ui/src/components/code/shiki.svelte @@ -1,6 +1,10 @@ + + diff --git a/packages/ui/src/components/custom/draggable-command-group.svelte b/packages/ui/src/components/custom/draggable-command-group.svelte index 37adbeb..c1268df 100644 --- a/packages/ui/src/components/custom/draggable-command-group.svelte +++ b/packages/ui/src/components/custom/draggable-command-group.svelte @@ -14,7 +14,7 @@ diff --git a/packages/ui/src/components/extension/StoreListing.svelte b/packages/ui/src/components/extension/StoreListing.svelte deleted file mode 100644 index 178dceb..0000000 --- a/packages/ui/src/components/extension/StoreListing.svelte +++ /dev/null @@ -1,63 +0,0 @@ - - -{#snippet leftSlot()} - -{/snippet} - - - - No results found. - {#each storeExtList as ext} - onExtItemSelected(ext)} - onUpgrade={() => onExtItemUpgrade(ext)} - onInstall={() => onExtItemInstall(ext)} - /> - {/each} - - - diff --git a/packages/ui/src/components/extension/index.ts b/packages/ui/src/components/extension/index.ts index 78a3780..5e813b7 100644 --- a/packages/ui/src/components/extension/index.ts +++ b/packages/ui/src/components/extension/index.ts @@ -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" diff --git a/packages/ui/src/constants.ts b/packages/ui/src/constants.ts index 713f046..5b6b427 100644 --- a/packages/ui/src/constants.ts +++ b/packages/ui/src/constants.ts @@ -1,3 +1,4 @@ export const CLASSNAMES = { - EXT_LOGO: "kk-ext-logo" + EXT_LOGO: "kk-ext-logo", + BACK_BUTTON: "kk-back-button" } From a3dbdb02dee939472c224d6ef349947edd38bc20 Mon Sep 17 00:00:00 2001 From: Huakun Shen Date: Tue, 5 Nov 2024 16:58:15 -0500 Subject: [PATCH 2/2] ci: add CI for app build and publish --- .github/workflows/beta-build.yml | 270 ++++++++++++++++++++++++++ .github/workflows/desktop-publish.yml | 110 +++++++++++ 2 files changed, 380 insertions(+) create mode 100644 .github/workflows/beta-build.yml create mode 100644 .github/workflows/desktop-publish.yml diff --git a/.github/workflows/beta-build.yml b/.github/workflows/beta-build.yml new file mode 100644 index 0000000..4fbe826 --- /dev/null +++ b/.github/workflows/beta-build.yml @@ -0,0 +1,270 @@ +name: Build Beta Package + +on: + schedule: + - cron: "22 22 * * *" + workflow_dispatch: + inputs: + updater: + description: "Enable updater?" + required: true + type: boolean + default: true + platform_windows: + description: "windows" + required: true + type: boolean + default: true + platform_linux: + description: "linux" + required: true + type: boolean + default: false + platform_macos_aarch64: + description: "macos-aarch64" + required: true + type: boolean + default: false + platform_macos_x86_64: + description: "macos-x86_64" + required: true + type: boolean + default: false + isDebug: + description: "is debug?" + required: true + type: boolean + default: false + retention_days: + description: "Artifacts retention time (days)" + required: true + type: string + default: "1" + +jobs: + preprocess: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.setting.outputs.matrix }} + build_mode: ${{ steps.setting.outputs.build_mode }} + build_path: ${{ steps.setting.outputs.build_path }} + retention_days: ${{ steps.setting.outputs.retention_days }} + file_prefix: ${{ steps.filename.outputs.file_prefix }} + # build_time: ${{ steps.filename.outputs.build_time }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Install yq + uses: mikefarah/yq@master + with: + cmd: yq -V + + - name: Update tauri.conf.json + if: ${{ github.event_name != 'schedule' && !inputs.updater }} + run: yq -i '.bundle.active = false' src-tauri/tauri.conf.json + working-directory: apps/desktop + + - name: Upload tauri-config + if: ${{ github.event_name != 'schedule' && !inputs.updater }} + uses: actions/upload-artifact@v4 + with: + name: tauri-config + path: apps/desktop/src-tauri/tauri.conf.json + retention-days: 1 + + - name: Get file name + id: filename + working-directory: apps/desktop + run: | + productName=$(yq e -r '.productName' src-tauri/tauri.conf.json) + # ersion=$(yq e -r '.version' package.json) + # build_time=$(TZ=UTC-8 date +%y%m%d%H) + git_des=$(git describe --long --tags --always --dirty) + echo "file_prefix=${productName}_${git_des}" >> "$GITHUB_OUTPUT" + # echo "build_time=${build_time}" >> "$GITHUB_OUTPUT" + + - name: Setting variable + id: setting + run: | + matrix="" + if [ "${{ github.event_name }}" == "schedule" ]; then + matrix="\"windows-latest\",\"ubuntu-22.04\",\"macos-14\",\"macos-12\"" + build_mode="" + build_path="release" + retention_days='1' + else + if [ "${{ inputs.platform_windows }}" == "true" ]; then + matrix="${matrix}\"windows-latest\"," + fi + if [ "${{ inputs.platform_linux }}" == "true" ]; then + matrix="${matrix}\"ubuntu-22.04\"," + fi + if [ "${{ inputs.platform_macos_aarch64 }}" == "true" ]; then + matrix="${matrix}\"macos-14\"," + fi + if [ "${{ inputs.platform_macos_x86_64 }}" == "true" ]; then + matrix="${matrix}\"macos-12\"," + fi + if [ -z "${matrix}" ]; then + matrix="\"windows-latest\"," + fi + matrix="${matrix%,}" + build_mode="${{ inputs.isDebug && '--debug' || '' }}" + build_path="${{ inputs.isDebug && 'debug' || 'release' }}" + retention_days="${{ inputs.retention_days }}" + fi + echo "matrix=[${matrix}]" >> "$GITHUB_OUTPUT" + echo "build_mode=${build_mode}" >> "$GITHUB_OUTPUT" + echo "build_path=${build_path}" >> "$GITHUB_OUTPUT" + echo "retention_days=${retention_days}" >> "$GITHUB_OUTPUT" + + auto-build: + needs: preprocess + permissions: + contents: write + strategy: + fail-fast: false + matrix: + os: ${{ fromJson(needs.preprocess.outputs.matrix) }} + + runs-on: ${{ matrix.os }} + env: + BUILD_MODE: ${{ needs.preprocess.outputs.build_mode }} + BUILD_PATH: ${{ needs.preprocess.outputs.build_path }} + RETENTION_DAYS: ${{ needs.preprocess.outputs.retention_days }} + FILE_PREFIX: ${{ needs.preprocess.outputs.file_prefix }} + # BUILD_TIME: ${{ needs.preprocess.outputs.build_time }} + TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} + TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} + NO_STRIP: true + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + submodules: "true" + + - name: Download artifact + if: ${{ github.event_name != 'schedule' && !inputs.updater }} + uses: actions/download-artifact@v4 + with: + name: tauri-config + path: src-tauri + + - name: Install pnpm + uses: pnpm/action-setup@v3 + with: + version: latest + + - name: Install Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: pnpm + + - uses: oven-sh/setup-bun@v1 + with: + bun-version: 1.1.27 + + - name: Install protobuf (Mac) + if: startsWith(matrix.os, 'macos') + run: | + brew install protobuf + - name: Install and Protobuf (Ubuntu) + if: matrix.os == 'ubuntu-22.04' + run: | + sudo apt install -y protobuf-compiler + - name: Install protoc and openssl for windows + if: matrix.os == 'windows-latest' + run: | + choco install protoc + choco install openssl + echo OPENSSL_DIR='"C:\\Program Files\\OpenSSL-Win64"' >> $env:GITHUB_ENV + echo OPENSSL_INCLUDE_DIR='"C:\\Program Files\\OpenSSL-Win64\\include"' >> $env:GITHUB_ENV + echo OPENSSL_LIB_DIR='"C:\\Program Files\\OpenSSL-Win64\\lib"' >> $env:GITHUB_ENV + - name: Install dependencies (ubuntu only) + if: matrix.os == 'ubuntu-22.04' + run: | + sudo apt-get update + sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + # 那些目标仅在 macos 运行器上使用,因此将其置于 `if` 语句中,以稍微加快 Windows 和 Linux 的构建速度。 + targets: ${{ startsWith(matrix.os, 'macos') && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }} + + - name: Rust cache + uses: swatinem/rust-cache@v2 + with: + workspaces: "./apps/desktop/src-tauri -> target" + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Prepare + run: pnpm prepare + + - name: Build Packages + run: pnpm build + + - name: Build the app (Windows) + working-directory: apps/desktop + env: + CI: false + run: pnpm tauri build ${{ env.BUILD_MODE}} ${{ matrix.os == 'windows-latest' && '-b nsis' || '' }} + + - name: Rename macos-aarch64 + if: matrix.os == 'macos-14' + run: mv target/${{ env.BUILD_PATH }}/bundle/dmg/*.dmg target/${{ env.BUILD_PATH }}/bundle/dmg/${{ env.FILE_PREFIX }}-aarch64.dmg + + - name: Rename macos-x86_64 + if: matrix.os == 'macos-12' + run: mv target/${{ env.BUILD_PATH }}/bundle/dmg/*.dmg target/${{ env.BUILD_PATH }}/bundle/dmg/${{ env.FILE_PREFIX }}-amd64.dmg + + - name: Rename windows + if: matrix.os == 'windows-latest' + run: | + # mv target/${{ env.BUILD_PATH }}/bundle/msi/*.msi target/${{ env.BUILD_PATH }}/bundle/msi/${{ env.FILE_PREFIX }}-amd64.msi + mv target/${{ env.BUILD_PATH }}/bundle/nsis/*.exe target/${{ env.BUILD_PATH }}/bundle/nsis/${{ env.FILE_PREFIX }}-amd64.exe + + - name: Rename linux + if: matrix.os == 'ubuntu-22.04' + run: | + mv target/${{ env.BUILD_PATH }}/bundle/deb/*.deb target/${{ env.BUILD_PATH }}/bundle/deb/${{ env.FILE_PREFIX }}-amd64.deb + mv target/${{ env.BUILD_PATH }}/bundle/rpm/*.rpm target/${{ env.BUILD_PATH }}/bundle/rpm/${{ env.FILE_PREFIX }}-amd64.rpm + mv target/${{ env.BUILD_PATH }}/bundle/appimage/*.AppImage target/${{ env.BUILD_PATH }}/bundle/appimage/${{ env.FILE_PREFIX }}-amd64.AppImage + + - name: Upload artifacts (Windows) + if: matrix.os == 'windows-latest' + uses: actions/upload-artifact@v4 + with: + name: ${{ env.FILE_PREFIX }}_windows-amd64 + path: | + # target/${{ env.BUILD_PATH }}/bundle/msi/*.msi + target/${{ env.BUILD_PATH }}/bundle/nsis/*.exe + retention-days: ${{ env.RETENTION_DAYS}} + compression-level: 0 + + - name: Upload artifacts (MacOS) + if: startsWith(matrix.os, 'macos') + uses: actions/upload-artifact@v4 + with: + name: ${{ env.FILE_PREFIX }}_${{ matrix.os == 'macos-14' && 'macos-aarch64' || 'macos-amd64' }} + path: target/${{ env.BUILD_PATH }}/bundle/dmg/*.dmg + retention-days: ${{ env.RETENTION_DAYS}} + compression-level: 0 + + - name: Upload artifacts (Linux) + if: matrix.os == 'ubuntu-22.04' + uses: actions/upload-artifact@v4 + with: + name: ${{ env.FILE_PREFIX }}_linux-amd64 + path: | + target/${{ env.BUILD_PATH }}/bundle/deb/*.deb + target/${{ env.BUILD_PATH }}/bundle/rpm/*.rpm + target/${{ env.BUILD_PATH }}/bundle/appimage/*.AppImage + retention-days: ${{ env.RETENTION_DAYS}} + compression-level: 0 diff --git a/.github/workflows/desktop-publish.yml b/.github/workflows/desktop-publish.yml new file mode 100644 index 0000000..c83d642 --- /dev/null +++ b/.github/workflows/desktop-publish.yml @@ -0,0 +1,110 @@ +name: "Desktop App Publish" + +on: + push: + tags: + - "v*" + workflow_dispatch: + +jobs: + publish-tauri: + permissions: + contents: write + strategy: + fail-fast: false + matrix: + settings: + - platform: "macos-14" # for Arm based macs (M1 and above). + args: "--target aarch64-apple-darwin --verbose" + - platform: "macos-14" # for Intel based macs. + args: "--target x86_64-apple-darwin --verbose" + - platform: "macos-14" # for Both Arm and Intel based macs. + args: "--target universal-apple-darwin --verbose" + - platform: "ubuntu-22.04" # for Tauri v1 you could replace this with ubuntu-20.04. + args: "--verbose" + - platform: "windows-latest" + args: "--verbose" + + runs-on: ${{ matrix.settings.platform }} + steps: + - uses: actions/checkout@v4 + with: + submodules: "true" + + - name: install dependencies (ubuntu only) + if: matrix.settings.platform == 'ubuntu-22.04' # This must match the platform value defined above. + run: | + sudo apt-get update + sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf + # You can remove the one that doesn't apply to your app to speed up the workflow a bit. + - name: Install protobuf (Mac) + if: matrix.settings.platform == 'macos-14' + run: | + brew install protobuf + - name: Install Protobuf (Ubuntu) + if: matrix.settings.platform == 'ubuntu-22.04' + run: | + sudo apt install -y protobuf-compiler + - name: Install protoc and openssl for windows + if: matrix.settings.platform == 'windows-latest' + run: | + choco install protoc + choco install openssl + echo OPENSSL_DIR='"C:\\Program Files\\OpenSSL-Win64"' >> $env:GITHUB_ENV + echo OPENSSL_INCLUDE_DIR='"C:\\Program Files\\OpenSSL-Win64\\include"' >> $env:GITHUB_ENV + echo OPENSSL_LIB_DIR='"C:\\Program Files\\OpenSSL-Win64\\lib"' >> $env:GITHUB_ENV + - uses: pnpm/action-setup@v4 + - name: setup node + uses: actions/setup-node@v4 + with: + node-version: lts/* + cache: "pnpm" # Set this to npm, yarn or pnpm. + cache-dependency-path: ./pnpm-lock.yaml + + - name: Install Rust stable + uses: dtolnay/rust-toolchain@stable + with: + # Those targets are only used on macos runners so it's in an `if` to slightly speed up windows and linux builds. + targets: ${{ matrix.settings.platform == 'macos-14' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }} + - name: Add rust target (macos only) + if: matrix.settings.platform == 'macos-14' + run: | + rustup target add aarch64-apple-darwin + rustup target add x86_64-apple-darwin + - name: Rust cache + uses: swatinem/rust-cache@v2 + with: + workspaces: "./apps/desktop/src-tauri -> target" + - uses: oven-sh/setup-bun@v1 + with: + bun-version: 1.1.27 + - name: Install Dependencies + # If you don't have `beforeBuildCommand` configured you may want to build your frontend here too. + run: | + pnpm install + pnpm prepare + - name: Get App Version + if: matrix.settings.platform == 'windows-latest' + id: appversion + run: | + echo "version=$(node -p "require('./apps/desktop/package.json').version")" >> $env:GITHUB_OUTPUT + - uses: tauri-apps/tauri-action@v0 + env: + CI: false + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} + APPLE_ID: ${{ secrets.APPLE_ID }} + APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} + TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} + with: + tagName: Kunkun-v__VERSION__ # the action automatically replaces \_\_VERSION\_\_ with the app version. + releaseName: "Kunkun v__VERSION__" + releaseBody: "See the assets to download this version and install." + releaseDraft: true + prerelease: false + args: ${{ matrix.settings.args }} ${{ contains(steps.appversion.outputs.version, 'beta') && matrix.settings.platform == 'windows-latest' && '-b nsis' || '' }} + projectPath: "./apps/desktop"