Skip to content

Commit 470bfaf

Browse files
committed
feat: rework route css mounting
1 parent f5e2a19 commit 470bfaf

File tree

3 files changed

+71
-3
lines changed

3 files changed

+71
-3
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1+
export { mountAssets } from "../shared/css.js";
12
export { mount } from "./mount.js";
23
export { StartClient, StartClientTanstack } from "./StartClient.jsx";
3-

packages/start/src/server/lazyRoute.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { type Component, createComponent, type JSX, lazy, onCleanup } from "solid-js";
2-
2+
import { mountAssets } from "../shared/css.js";
33
import { type Asset, renderAsset } from "./renderAsset.jsx";
44

55
export default function lazyRoute<T extends Record<string, any>>(
@@ -59,8 +59,9 @@ export default function lazyRoute<T extends Record<string, any>>(
5959
preloadStyles(styles);
6060
}
6161
const Comp: Component<T> = props => {
62+
mountAssets(styles);
63+
6264
return [
63-
...styles.map((asset: Asset) => renderAsset(asset)),
6465
createComponent(Component, props)
6566
];
6667
};

packages/start/src/shared/css.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { createRenderEffect, createResource, onCleanup, sharedConfig } from "solid-js";
2+
import { isServer, useAssets } from "solid-js/web";
3+
import { renderAsset, type Asset } from "../server/renderAsset.jsx";
4+
5+
const instances: Record<string, { uses: number; el: HTMLElement }> = {};
6+
export const mountAssets = (assets: Asset[]) => {
7+
if (!assets.length) return;
8+
9+
if (isServer) {
10+
useAssets(() => assets.map((asset: Asset) => renderAsset(asset)));
11+
const a: [] = (sharedConfig.context as any).assets;
12+
const index = a.length - 1;
13+
onCleanup(() => {
14+
// TODO: index is not properly tracked!
15+
a.splice(index, assets.length);
16+
});
17+
return;
18+
}
19+
20+
const keys: string[] = [];
21+
for (const asset of assets) {
22+
const attrs = Object.entries(asset.attrs);
23+
let key = asset.tag;
24+
for (const [k, v] of attrs) {
25+
if (k === "key") continue;
26+
key += `[${k}='${v}']`;
27+
}
28+
keys.push(key);
29+
30+
console.log("mount", key);
31+
32+
const ssrEl = document.querySelector("head " + key) as HTMLElement;
33+
const instance = (instances[key] ??= {
34+
uses: 0,
35+
el: ssrEl ?? document.createElement(asset.tag)
36+
});
37+
instance.uses++;
38+
39+
if (instance.uses > 1 || ssrEl) continue;
40+
41+
const [r] = createResource(() => {
42+
return new Promise(res => {
43+
instance.el.addEventListener("load", res, { once: true });
44+
instance.el.addEventListener("error", res, { once: true });
45+
});
46+
});
47+
createRenderEffect(r);
48+
49+
for (const [k, v] of attrs) {
50+
if (k === "key") continue;
51+
instance.el.setAttribute(k, v);
52+
}
53+
document.head.append(instance.el);
54+
}
55+
56+
onCleanup(() => {
57+
for (const key of keys) {
58+
const instance = instances[key]!;
59+
instance.uses--;
60+
if (instance.uses === 0) {
61+
console.log("unmount", key);
62+
instance.el.remove();
63+
delete instances[key];
64+
}
65+
}
66+
});
67+
};

0 commit comments

Comments
 (0)