From a81aa875a8650fa4db3ebb066b10401771de8f97 Mon Sep 17 00:00:00 2001 From: dswbx Date: Tue, 14 Jan 2025 15:07:09 +0100 Subject: [PATCH 1/2] lazy import code editor once, externalized codemirror --- app/build.ts | 17 ++- app/package.json | 10 +- app/src/ui/components/code/CodeEditor.tsx | 31 ++++- app/src/ui/components/code/JsonEditor.tsx | 7 +- app/src/ui/components/code/LiquidJsEditor.tsx | 10 +- .../components/canvas/DataSchemaCanvas.tsx | 1 - tmp/lazy_codemirror.patch | 125 ------------------ 7 files changed, 51 insertions(+), 150 deletions(-) delete mode 100644 tmp/lazy_codemirror.patch diff --git a/app/build.ts b/app/build.ts index db8dae3..877044a 100644 --- a/app/build.ts +++ b/app/build.ts @@ -72,16 +72,12 @@ await tsup.build({ /** * Building UI for direct imports */ +const ui_splitting = false; await tsup.build({ minify, sourcemap, watch, - entry: [ - "src/ui/index.ts", - "src/ui/client/index.ts", - "src/ui/elements/index.ts", - "src/ui/main.css" - ], + entry: ["src/ui/index.ts", "src/ui/client/index.ts", "src/ui/main.css"], outDir: "dist/ui", external: [ "bun:test", @@ -89,19 +85,22 @@ await tsup.build({ "react-dom", "react/jsx-runtime", "react/jsx-dev-runtime", - "use-sync-external-store" + "use-sync-external-store", + /codemirror/ ], metafile: true, platform: "browser", format: ["esm"], - splitting: true, + splitting: ui_splitting, treeshake: true, loader: { ".svg": "dataurl" }, esbuildOptions: (options) => { options.logLevel = "silent"; - options.chunkNames = "chunks/[name]-[hash]"; + if (ui_splitting) { + options.chunkNames = "chunks/[name]-[hash]"; + } }, onSuccess: async () => { delayTypes(); diff --git a/app/package.json b/app/package.json index 8baeefd..709fe97 100644 --- a/app/package.json +++ b/app/package.json @@ -34,13 +34,14 @@ "lodash-es": "^4.17.21", "oauth4webapi": "^2.11.1", "swr": "^2.2.5", - "json-schema-form-react": "^0.0.2" + "json-schema-form-react": "^0.0.2", + "@uiw/react-codemirror": "^4.23.6", + "@codemirror/lang-html": "^6.4.9", + "@codemirror/lang-json": "^6.0.1", + "@codemirror/lang-liquid": "^6.2.1" }, "devDependencies": { "@aws-sdk/client-s3": "^3.613.0", - "@codemirror/lang-html": "^6.4.9", - "@codemirror/lang-json": "^6.0.1", - "@codemirror/lang-liquid": "^6.2.1", "@dagrejs/dagre": "^1.1.4", "@hello-pangea/dnd": "^17.0.0", "@hono/typebox-validator": "^0.2.6", @@ -58,7 +59,6 @@ "@types/node": "^22.10.0", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", - "@uiw/react-codemirror": "^4.23.6", "@vitejs/plugin-react": "^4.3.3", "@xyflow/react": "^12.3.2", "autoprefixer": "^10.4.20", diff --git a/app/src/ui/components/code/CodeEditor.tsx b/app/src/ui/components/code/CodeEditor.tsx index 55d119b..745f249 100644 --- a/app/src/ui/components/code/CodeEditor.tsx +++ b/app/src/ui/components/code/CodeEditor.tsx @@ -1,8 +1,22 @@ import { default as CodeMirror, type ReactCodeMirrorProps } from "@uiw/react-codemirror"; - import { useBknd } from "ui/client/bknd"; -export default function CodeEditor({ editable, basicSetup, ...props }: ReactCodeMirrorProps) { +import { json } from "@codemirror/lang-json"; +import { type LiquidCompletionConfig, liquid } from "@codemirror/lang-liquid"; + +export type CodeEditorProps = ReactCodeMirrorProps & { + _extensions?: Partial<{ + json: boolean; + liquid: LiquidCompletionConfig; + }>; +}; + +export default function CodeEditor({ + editable, + basicSetup, + _extensions = {}, + ...props +}: CodeEditorProps) { const b = useBknd(); const theme = b.app.getAdminConfig().color_scheme; const _basicSetup: Partial = !editable @@ -13,11 +27,24 @@ export default function CodeEditor({ editable, basicSetup, ...props }: ReactCode } : basicSetup; + const extensions = Object.entries(_extensions ?? {}) + .map(([ext, config]: any) => { + switch (ext) { + case "json": + return json(); + case "liquid": + return liquid(config); + } + return undefined; + }) + .filter(Boolean) as any; + return ( ); diff --git a/app/src/ui/components/code/JsonEditor.tsx b/app/src/ui/components/code/JsonEditor.tsx index 8317380..a8b4235 100644 --- a/app/src/ui/components/code/JsonEditor.tsx +++ b/app/src/ui/components/code/JsonEditor.tsx @@ -1,10 +1,9 @@ -import { json } from "@codemirror/lang-json"; -import type { ReactCodeMirrorProps } from "@uiw/react-codemirror"; import { Suspense, lazy } from "react"; import { twMerge } from "tailwind-merge"; +import type { CodeEditorProps } from "./CodeEditor"; const CodeEditor = lazy(() => import("./CodeEditor")); -export function JsonEditor({ editable, className, ...props }: ReactCodeMirrorProps) { +export function JsonEditor({ editable, className, ...props }: CodeEditorProps) { return ( diff --git a/app/src/ui/components/code/LiquidJsEditor.tsx b/app/src/ui/components/code/LiquidJsEditor.tsx index 7f145b1..be05818 100644 --- a/app/src/ui/components/code/LiquidJsEditor.tsx +++ b/app/src/ui/components/code/LiquidJsEditor.tsx @@ -1,7 +1,7 @@ -import { liquid } from "@codemirror/lang-liquid"; -import type { ReactCodeMirrorProps } from "@uiw/react-codemirror"; import { Suspense, lazy } from "react"; import { twMerge } from "tailwind-merge"; + +import type { CodeEditorProps } from "./CodeEditor"; const CodeEditor = lazy(() => import("./CodeEditor")); const filters = [ @@ -106,7 +106,7 @@ const tags = [ { label: "when" } ]; -export function LiquidJsEditor({ editable, ...props }: ReactCodeMirrorProps) { +export function LiquidJsEditor({ editable, ...props }: CodeEditorProps) { return ( diff --git a/app/src/ui/modules/data/components/canvas/DataSchemaCanvas.tsx b/app/src/ui/modules/data/components/canvas/DataSchemaCanvas.tsx index cc893e6..aeb7822 100644 --- a/app/src/ui/modules/data/components/canvas/DataSchemaCanvas.tsx +++ b/app/src/ui/modules/data/components/canvas/DataSchemaCanvas.tsx @@ -2,7 +2,6 @@ import { MarkerType, type Node, Position, ReactFlowProvider } from "@xyflow/reac import type { AppDataConfig, TAppDataEntity } from "data/data-schema"; import { useBknd } from "ui/client/BkndProvider"; import { useBkndSystemTheme } from "ui/client/schema/system/use-bknd-system"; -import { useTheme } from "ui/client/use-theme"; import { Canvas } from "ui/components/canvas/Canvas"; import { layoutWithDagre } from "ui/components/canvas/layouts"; import { Panels } from "ui/components/canvas/panels"; diff --git a/tmp/lazy_codemirror.patch b/tmp/lazy_codemirror.patch deleted file mode 100644 index 425cac5..0000000 --- a/tmp/lazy_codemirror.patch +++ /dev/null @@ -1,125 +0,0 @@ -Subject: [PATCH] lazy codemirror ---- -Index: app/src/ui/components/code/LiquidJsEditor.tsx -IDEA additional info: -Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP -<+>UTF-8 -=================================================================== -diff --git a/app/src/ui/components/code/LiquidJsEditor.tsx b/app/src/ui/components/code/LiquidJsEditor.tsx ---- a/app/src/ui/components/code/LiquidJsEditor.tsx (revision b1a32f370565aded3a34b79ffd254c3c45d1085c) -+++ b/app/src/ui/components/code/LiquidJsEditor.tsx (date 1736687726081) -@@ -1,7 +1,7 @@ --import { liquid } from "@codemirror/lang-liquid"; --import type { ReactCodeMirrorProps } from "@uiw/react-codemirror"; - import { Suspense, lazy } from "react"; - import { twMerge } from "tailwind-merge"; -+ -+import type { CodeEditorProps } from "./CodeEditor"; - const CodeEditor = lazy(() => import("./CodeEditor")); - - const filters = [ -@@ -106,7 +106,7 @@ - { label: "when" } - ]; - --export function LiquidJsEditor({ editable, ...props }: ReactCodeMirrorProps) { -+export function LiquidJsEditor({ editable, ...props }: CodeEditorProps) { - return ( - - - -Index: app/src/ui/components/code/CodeEditor.tsx -IDEA additional info: -Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP -<+>UTF-8 -=================================================================== -diff --git a/app/src/ui/components/code/CodeEditor.tsx b/app/src/ui/components/code/CodeEditor.tsx ---- a/app/src/ui/components/code/CodeEditor.tsx (revision b1a32f370565aded3a34b79ffd254c3c45d1085c) -+++ b/app/src/ui/components/code/CodeEditor.tsx (date 1736687634668) -@@ -1,8 +1,22 @@ - import { default as CodeMirror, type ReactCodeMirrorProps } from "@uiw/react-codemirror"; -- - import { useBknd } from "ui/client/bknd"; - --export default function CodeEditor({ editable, basicSetup, ...props }: ReactCodeMirrorProps) { -+import { json } from "@codemirror/lang-json"; -+import { type LiquidCompletionConfig, liquid } from "@codemirror/lang-liquid"; -+ -+export type CodeEditorProps = ReactCodeMirrorProps & { -+ _extensions?: Partial<{ -+ json: boolean; -+ liquid: LiquidCompletionConfig; -+ }>; -+}; -+ -+export default function CodeEditor({ -+ editable, -+ basicSetup, -+ _extensions = {}, -+ ...props -+}: CodeEditorProps) { - const b = useBknd(); - const theme = b.app.getAdminConfig().color_scheme; - const _basicSetup: Partial = !editable -@@ -13,11 +27,21 @@ - } - : basicSetup; - -+ const extensions = Object.entries(_extensions ?? {}).map(([ext, config]: any) => { -+ switch (ext) { -+ case "json": -+ return json(); -+ case "liquid": -+ return liquid(config); -+ } -+ }); -+ - return ( - - ); -Index: app/src/ui/components/code/JsonEditor.tsx -IDEA additional info: -Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP -<+>UTF-8 -=================================================================== -diff --git a/app/src/ui/components/code/JsonEditor.tsx b/app/src/ui/components/code/JsonEditor.tsx ---- a/app/src/ui/components/code/JsonEditor.tsx (revision b1a32f370565aded3a34b79ffd254c3c45d1085c) -+++ b/app/src/ui/components/code/JsonEditor.tsx (date 1736687681965) -@@ -1,10 +1,9 @@ --import { json } from "@codemirror/lang-json"; --import type { ReactCodeMirrorProps } from "@uiw/react-codemirror"; - import { Suspense, lazy } from "react"; - import { twMerge } from "tailwind-merge"; -+import type { CodeEditorProps } from "./CodeEditor"; - const CodeEditor = lazy(() => import("./CodeEditor")); - --export function JsonEditor({ editable, className, ...props }: ReactCodeMirrorProps) { -+export function JsonEditor({ editable, className, ...props }: CodeEditorProps) { - return ( - - - From a20b6b64a908f1200785c276356f3a1d9260e7ff Mon Sep 17 00:00:00 2001 From: dswbx Date: Sat, 18 Jan 2025 15:25:12 +0100 Subject: [PATCH 2/2] updated ui/client components, refactored deps --- app/build.ts | 15 ++++++--------- app/package.json | 6 +++--- app/src/auth/api/AuthApi.ts | 2 +- app/src/modules/ModuleApi.ts | 5 +++-- app/src/ui/client/ClientProvider.tsx | 2 +- app/src/ui/client/api/use-entity.ts | 5 +++-- app/src/ui/client/schema/auth/use-auth.ts | 5 ++--- 7 files changed, 19 insertions(+), 21 deletions(-) diff --git a/app/build.ts b/app/build.ts index 4d1480e..e931021 100644 --- a/app/build.ts +++ b/app/build.ts @@ -76,12 +76,7 @@ await tsup.build({ minify, sourcemap, watch, - entry: [ - "src/ui/index.ts", - "src/ui/client/index.ts", - "src/ui/main.css", - "src/ui/styles.css" - ], + entry: ["src/ui/index.ts", "src/ui/client/index.ts", "src/ui/main.css", "src/ui/styles.css"], outDir: "dist/ui", external: [ "bun:test", @@ -90,19 +85,21 @@ await tsup.build({ "react/jsx-runtime", "react/jsx-dev-runtime", "use-sync-external-store", - /codemirror/ + /codemirror/, + "@xyflow/react", + "@mantine/core" ], metafile: true, platform: "browser", format: ["esm"], - splitting: true, + splitting: false, + bundle: true, treeshake: true, loader: { ".svg": "dataurl" }, esbuildOptions: (options) => { options.logLevel = "silent"; - options.chunkNames = "chunks/[name]-[hash]"; }, onSuccess: async () => { delayTypes(); diff --git a/app/package.json b/app/package.json index 0bfda25..2da1a1a 100644 --- a/app/package.json +++ b/app/package.json @@ -49,7 +49,9 @@ "@uiw/react-codemirror": "^4.23.6", "@codemirror/lang-html": "^6.4.9", "@codemirror/lang-json": "^6.0.1", - "@codemirror/lang-liquid": "^6.2.1" + "@codemirror/lang-liquid": "^6.2.1", + "@xyflow/react": "^12.3.2", + "@mantine/core": "^7.13.4" }, "devDependencies": { "@aws-sdk/client-s3": "^3.613.0", @@ -60,7 +62,6 @@ "@hono/zod-validator": "^0.4.1", "@hookform/resolvers": "^3.9.1", "@libsql/kysely-libsql": "^0.4.1", - "@mantine/core": "^7.13.4", "@mantine/hooks": "^7.13.4", "@mantine/modals": "^7.13.4", "@mantine/notifications": "^7.13.5", @@ -71,7 +72,6 @@ "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", "@vitejs/plugin-react": "^4.3.3", - "@xyflow/react": "^12.3.2", "autoprefixer": "^10.4.20", "clsx": "^2.1.1", "esbuild-postcss": "^0.0.4", diff --git a/app/src/auth/api/AuthApi.ts b/app/src/auth/api/AuthApi.ts index 869103c..d02a258 100644 --- a/app/src/auth/api/AuthApi.ts +++ b/app/src/auth/api/AuthApi.ts @@ -1,5 +1,5 @@ import type { AuthActionResponse } from "auth/api/AuthController"; -import type { AppAuthSchema, AppAuthStrategies } from "auth/auth-schema"; +import type { AppAuthSchema } from "auth/auth-schema"; import type { AuthResponse, SafeUser, Strategy } from "auth/authenticate/Authenticator"; import { type BaseModuleApiOptions, ModuleApi } from "modules/ModuleApi"; diff --git a/app/src/modules/ModuleApi.ts b/app/src/modules/ModuleApi.ts index 2bd7be8..882cb90 100644 --- a/app/src/modules/ModuleApi.ts +++ b/app/src/modules/ModuleApi.ts @@ -1,5 +1,6 @@ -import { type PrimaryFieldType, isDebug } from "core"; -import { encodeSearch } from "core/utils"; +import type { PrimaryFieldType } from "core"; +import { isDebug } from "core/env"; +import { encodeSearch } from "core/utils/reqres"; export type { PrimaryFieldType }; export type BaseModuleApiOptions = { diff --git a/app/src/ui/client/ClientProvider.tsx b/app/src/ui/client/ClientProvider.tsx index 3a81775..f456f94 100644 --- a/app/src/ui/client/ClientProvider.tsx +++ b/app/src/ui/client/ClientProvider.tsx @@ -1,5 +1,5 @@ import { Api, type ApiOptions, type TApiUser } from "Api"; -import { createContext, useContext, useEffect, useState } from "react"; +import { createContext, useContext } from "react"; const ClientContext = createContext<{ baseUrl: string; api: Api }>({ baseUrl: undefined diff --git a/app/src/ui/client/api/use-entity.ts b/app/src/ui/client/api/use-entity.ts index 85a44bb..483febf 100644 --- a/app/src/ui/client/api/use-entity.ts +++ b/app/src/ui/client/api/use-entity.ts @@ -1,6 +1,7 @@ import type { DB, PrimaryFieldType } from "core"; -import { encodeSearch, objectTransform } from "core/utils"; -import type { EntityData, RepoQuery, RepoQueryIn } from "data"; +import { objectTransform } from "core/utils/objects"; +import { encodeSearch } from "core/utils/reqres"; +import type { EntityData, RepoQueryIn } from "data"; import type { ModuleApi, ResponseObject } from "modules/ModuleApi"; import useSWR, { type SWRConfiguration, mutate } from "swr"; import { type Api, useApi } from "ui/client"; diff --git a/app/src/ui/client/schema/auth/use-auth.ts b/app/src/ui/client/schema/auth/use-auth.ts index 9ea39bf..b24f2ce 100644 --- a/app/src/ui/client/schema/auth/use-auth.ts +++ b/app/src/ui/client/schema/auth/use-auth.ts @@ -1,7 +1,6 @@ -import { Api, type AuthState } from "Api"; +import type { AuthState } from "Api"; import type { AuthResponse } from "auth"; -import type { AppAuthSchema } from "auth/auth-schema"; -import { useEffect, useState } from "react"; +import { useState } from "react"; import { useApi, useInvalidate } from "ui/client"; type LoginData = {