Skip to content

Commit

Permalink
optimize hydration keys
Browse files Browse the repository at this point in the history
  • Loading branch information
ryansolid committed Jul 24, 2024
1 parent f909c1c commit 424a31a
Show file tree
Hide file tree
Showing 11 changed files with 99 additions and 69 deletions.
6 changes: 6 additions & 0 deletions .changeset/slow-pugs-join.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"babel-preset-solid": patch
"solid-js": patch
---

optimize hydration keys
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,21 @@
"@rollup/plugin-replace": "^5.0.2",
"@types/node": "^18.11.19",
"@vitest/coverage-c8": "^0.29.7",
"babel-plugin-jsx-dom-expressions": "^0.37.23",
"babel-plugin-jsx-dom-expressions": "^0.38.0",
"coveralls": "^3.1.1",
"csstype": "^3.1.0",
"dom-expressions": "0.37.23",
"hyper-dom-expressions": "0.37.23",
"dom-expressions": "0.38.0",
"hyper-dom-expressions": "0.38.0",
"jsdom": "^21.1.1",
"lit-dom-expressions": "0.37.23",
"lit-dom-expressions": "0.38.0",
"ncp": "^2.0.0",
"npm-run-all": "^4.1.5",
"prettier": "^2.8.8",
"rimraf": "^3.0.2",
"rollup": "^3.7.5",
"rollup-plugin-cleanup": "^3.2.1",
"rollup-plugin-copy": "^3.4.0",
"seroval": "^1.0.4",
"seroval": "^1.1.0",
"simple-git-hooks": "^2.8.1",
"symlink-dir": "^5.0.1",
"tsconfig-replace-paths": "^0.0.11",
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-preset-solid/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"test": "node test.js"
},
"dependencies": {
"babel-plugin-jsx-dom-expressions": "^0.37.23"
"babel-plugin-jsx-dom-expressions": "^0.38.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0"
Expand Down
4 changes: 2 additions & 2 deletions packages/solid/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@
],
"dependencies": {
"csstype": "^3.1.0",
"seroval": "^1.0.4",
"seroval-plugins": "^1.0.3"
"seroval": "^1.1.0",
"seroval-plugins": "^1.1.0"
}
}
2 changes: 1 addition & 1 deletion packages/solid/src/reactive/signal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,7 @@ export function createResource<T, S, R>(
);

if (sharedConfig.context) {
id = `${sharedConfig.context.id}${sharedConfig.context.count++}`;
id = sharedConfig.getNextContextId();
let v;
if (options.ssrLoadFrom === "initial") initP = options.initialValue as T;
else if (sharedConfig.load && (v = sharedConfig.load(id))) initP = v;
Expand Down
4 changes: 2 additions & 2 deletions packages/solid/src/render/Suspense.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export function Suspense(props: { fallback?: JSX.Element; children: JSX.Element
},
owner = getOwner();
if (sharedConfig.context && sharedConfig.load) {
const key = sharedConfig.context.id + sharedConfig.context.count;
const key = sharedConfig.getContextId();
let ref = sharedConfig.load(key);
if (ref) {
if (typeof ref !== "object" || ref.status !== "success") p = ref;
Expand Down Expand Up @@ -200,7 +200,7 @@ export function Suspense(props: { fallback?: JSX.Element; children: JSX.Element
return createRoot(disposer => {
dispose = disposer;
if (ctx) {
setHydrateContext({ id: ctx.id + "f", count: 0 });
setHydrateContext({ id: ctx.id + "F", count: 0 });
ctx = undefined;
}
return props.fallback;
Expand Down
2 changes: 1 addition & 1 deletion packages/solid/src/render/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -388,5 +388,5 @@ export function lazy<T extends Component<any>>(
let counter = 0;
export function createUniqueId(): string {
const ctx = sharedConfig.context;
return ctx ? `${ctx.id}${ctx.count++}` : `cl-${counter++}`;
return ctx ? sharedConfig.getNextContextId() : `cl-${counter++}`;
}
2 changes: 1 addition & 1 deletion packages/solid/src/render/flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ export function ErrorBoundary(props: {
}): JSX.Element {
let err;
if (sharedConfig!.context && sharedConfig!.load)
err = sharedConfig.load(sharedConfig.context.id + sharedConfig.context.count);
err = sharedConfig.load(sharedConfig.getContextId());
const [errored, setErrored] = createSignal<any>(
err,
"_SOLID_DEV_" ? { name: "errored" } : undefined
Expand Down
21 changes: 19 additions & 2 deletions packages/solid/src/render/hydration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,26 @@ type SharedConfig = {
done?: boolean;
count?: number;
effects?: Computation<any, any>[];
getContextId(): string;
getNextContextId(): string;
};

export const sharedConfig: SharedConfig = { context: undefined, registry: undefined };
export const sharedConfig: SharedConfig = {
context: undefined,
registry: undefined,
getContextId() {
return getContextId(this.context!.count);
},
getNextContextId() {
return getContextId(this.context!.count++);
}
};

function getContextId(count: number) {
const num = String(count),
len = num.length - 1;
return sharedConfig.context!.id + (len ? String.fromCharCode(96 + len) : "") + num;
}

export function setHydrateContext(context?: HydrationContext): void {
sharedConfig.context = context;
Expand All @@ -23,7 +40,7 @@ export function setHydrateContext(context?: HydrationContext): void {
export function nextHydrateContext(): HydrationContext | undefined {
return {
...sharedConfig.context,
id: `${sharedConfig.context!.id}${sharedConfig.context!.count++}-`,
id: sharedConfig.getNextContextId(),
count: 0
};
}
37 changes: 27 additions & 10 deletions packages/solid/src/server/rendering.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,27 @@ function resolveSSRNode(node: any): string {

type SharedConfig = {
context?: HydrationContext;
getContextId(): string;
getNextContextId(): string;
};
export const sharedConfig: SharedConfig = {};
export const sharedConfig: SharedConfig = {
context: undefined,
getContextId() {
if (!this.context) throw new Error(`getContextId cannot be used under non-hydrating context`);
return getContextId(this.context.count);
},
getNextContextId() {
if (!this.context)
throw new Error(`getNextContextId cannot be used under non-hydrating context`);
return getContextId(this.context.count++);
}
};

function getContextId(count: number) {
const num = String(count),
len = num.length - 1;
return sharedConfig.context!.id + (len ? String.fromCharCode(96 + len) : "") + num;
}

function setHydrateContext(context?: HydrationContext): void {
sharedConfig.context = context;
Expand All @@ -60,16 +79,14 @@ function nextHydrateContext(): HydrationContext | undefined {
return sharedConfig.context
? {
...sharedConfig.context,
id: `${sharedConfig.context.id}${sharedConfig.context.count++}-`,
id: sharedConfig.getNextContextId(),
count: 0
}
: undefined;
}

export function createUniqueId(): string {
const ctx = sharedConfig.context;
if (!ctx) throw new Error(`createUniqueId cannot be used under non-hydrating context`);
return `${ctx.id}${ctx.count++}`;
return sharedConfig.getNextContextId();
}

export function createComponent<T>(Comp: (props: T) => JSX.Element, props: T): JSX.Element {
Expand Down Expand Up @@ -266,7 +283,7 @@ export function ErrorBoundary(props: {
clean: any,
sync = true;
const ctx = sharedConfig.context!;
const id = ctx.id + ctx.count;
const id = sharedConfig.getContextId();
function displayFallback() {
cleanNode(clean);
ctx.serialize(id, error);
Expand Down Expand Up @@ -368,7 +385,7 @@ export function createResource<T, S>(
source = true as ResourceSource<S>;
}
const contexts = new Set<SuspenseContextType>();
const id = sharedConfig.context!.id + sharedConfig.context!.count++;
const id = sharedConfig.getNextContextId();
let resource: { ref?: any; data?: T } = {};
let value = options.storage ? options.storage(options.initialValue)[0]() : options.initialValue;
let p: Promise<T> | T | null;
Expand Down Expand Up @@ -562,7 +579,7 @@ export function SuspenseList(props: {
export function Suspense(props: { fallback?: string; children: string }) {
let done: undefined | ((html?: string, error?: any) => boolean);
const ctx = sharedConfig.context!;
const id = ctx.id + ctx.count;
const id = sharedConfig.getContextId();
const o = createOwner();
const value: SuspenseContextType =
ctx.suspense[id] ||
Expand Down Expand Up @@ -607,14 +624,14 @@ export function Suspense(props: { fallback?: string; children: string }) {
done = ctx.async ? ctx.registerFragment(id) : undefined;
return catchError(() => {
if (ctx.async) {
setHydrateContext({ ...ctx, count: 0, id: ctx.id + "0-f", noHydrate: true });
setHydrateContext({ ...ctx, count: 0, id: ctx.id + "0F", noHydrate: true });
const res = {
t: `<template id="pl-${id}"></template>${resolveSSRNode(props.fallback)}<!--pl-${id}-->`
};
setHydrateContext(ctx);
return res;
}
setHydrateContext({ ...ctx, count: 0, id: ctx.id + "0-f" });
setHydrateContext({ ...ctx, count: 0, id: ctx.id + "0F" });
ctx.serialize(id, "$$f");
return props.fallback;
}, suspenseError);
Expand Down
78 changes: 34 additions & 44 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 424a31a

Please sign in to comment.