Skip to content

Commit 26e631e

Browse files
thephezclaude
andauthored
perf(dashnote): defer SDK value imports in note + contract helpers (#77)
* perf(dashnote): defer SDK value imports in note + contract helpers NotesWorkspace, SessionContext, and LoginModal statically imported contract.ts, createNote.ts, and updateNote.ts, each of which pulled Document/DataContract/Identifier from @dashevo/evo-sdk. That anchored the 8 MB SDK chunk to the entry graph via a hoisted static import, so the browser fetched it before first paint despite the modulePreload filter in vite.config.ts. Move the value imports behind a lazy module cache (matching the loginWithPrivateKey pattern in 2b2c5a0) so the chunk loads only when an authenticated write actually needs it. Throttled Lighthouse (Slow 4G + 4× CPU, simulated mobile): LCP 30.8 s → 2.0 s, FCP 16.1 s → 1.7 s, perf score 0.55 → 0.98. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(dashnote): extract shared SDK lazy-loader to src/dash/sdkModule Pull the duplicated `loadSdkModule` helper (type alias + cached promise + loader function with retry-on-failure) out of contract.ts, createNote.ts, and updateNote.ts into a single src/dash/sdkModule.ts, and have each consumer import it. No behavior change — ESM module-graph caching makes the previous three private promises functionally equivalent to one shared promise. Tutorial files now show only their Dash SDK recipe without the bundler-deferral plumbing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent e251265 commit 26e631e

4 files changed

Lines changed: 24 additions & 6 deletions

File tree

example-apps/dashnote/src/dash/contract.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@
55
* sdk.contracts.publish({ dataContract, identityKey, signer })
66
* sdk.identities.nonce(identityId)
77
*/
8-
import { DataContract, Identifier } from "@dashevo/evo-sdk";
9-
108
import type { Logger } from "../lib/logger";
9+
import { loadSdkModule } from "./sdkModule";
1110
import type { DashKeyManager, DashSdk } from "./types";
1211

1312
export const NOTE_SCHEMAS = {
@@ -78,6 +77,7 @@ export async function refreshContractCache({
7877
if (!contractId || typeof sdk.getWasmSdkConnected !== "function") return;
7978
const wasm = await sdk.getWasmSdkConnected();
8079
if (!wasm || typeof wasm.removeCachedContract !== "function") return;
80+
const { Identifier } = await loadSdkModule();
8181
const identifier = new Identifier(contractId);
8282
try {
8383
wasm.removeCachedContract(identifier);
@@ -98,6 +98,7 @@ export async function registerContract({
9898
log?.("Registering Dashnote note contract…");
9999
const { identity, identityKey, signer } = await keyManager.getAuth();
100100
const identityNonce = await sdk.identities.nonce(identity.id.toString());
101+
const { DataContract } = await loadSdkModule();
101102
const dataContract = new DataContract({
102103
ownerId: identity.id,
103104
identityNonce: (identityNonce || 0n) + 1n,

example-apps/dashnote/src/dash/createNote.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
*
44
* SDK method: sdk.documents.create({ document, identityKey, signer })
55
*/
6-
import { Document } from "@dashevo/evo-sdk";
7-
86
import type { Logger } from "../lib/logger";
7+
import { loadSdkModule } from "./sdkModule";
98
import type { DashKeyManager, DashSdk } from "./types";
109

1110
export interface CreateNoteParams {
@@ -27,6 +26,7 @@ export async function createNote({
2726
}: CreateNoteParams): Promise<string> {
2827
log?.("Creating note…");
2928
const { identity, identityKey, signer } = await keyManager.getAuth();
29+
const { Document } = await loadSdkModule();
3030
const trimmedTitle = title?.trim();
3131
const document = new Document({
3232
properties: {
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Defer the @dashevo/evo-sdk value import so it doesn't anchor the SDK chunk
2+
// to the entry graph via files statically imported by SessionContext /
3+
// LoginModal / NotesWorkspace. Cached after first call; cleared on failure
4+
// so a transient chunk fetch can retry.
5+
export type SdkModule = typeof import("@dashevo/evo-sdk");
6+
7+
let sdkModulePromise: Promise<SdkModule> | null = null;
8+
9+
export function loadSdkModule(): Promise<SdkModule> {
10+
if (!sdkModulePromise) {
11+
sdkModulePromise = import("@dashevo/evo-sdk").catch((err) => {
12+
sdkModulePromise = null;
13+
throw err;
14+
});
15+
}
16+
return sdkModulePromise;
17+
}

example-apps/dashnote/src/dash/updateNote.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@
66
* sdk.documents.get(contractId, documentTypeName, documentId)
77
* sdk.documents.replace({ document, identityKey, signer })
88
*/
9-
import { Document } from "@dashevo/evo-sdk";
10-
119
import type { Logger } from "../lib/logger";
10+
import { loadSdkModule } from "./sdkModule";
1211
import type { DashKeyManager, DashSdk } from "./types";
1312

1413
export interface UpdateNoteParams {
@@ -37,6 +36,7 @@ export async function updateNote({
3736
throw new Error(`Note ${noteId} not found.`);
3837
}
3938

39+
const { Document } = await loadSdkModule();
4040
const revision = BigInt(existingDoc.revision ?? 0) + 1n;
4141
const trimmedTitle = title?.trim();
4242
const document = new Document({

0 commit comments

Comments
 (0)