Skip to content

Commit 3ba5825

Browse files
committed
Improve bundling of core devtools to not leak to client
1 parent a5448af commit 3ba5825

7 files changed

Lines changed: 94 additions & 99 deletions

File tree

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
},
4848
"size-limit": [
4949
{
50-
"path": "packages/devtools/dist/index.js",
50+
"path": "packages/devtools/dist/esm/index.js",
5151
"limit": "60 KB"
5252
},
5353
{
@@ -85,4 +85,4 @@
8585
"@tanstack/solid-devtools": "workspace:*",
8686
"@tanstack/devtools-vite": "workspace:*"
8787
}
88-
}
88+
}

packages/devtools/package.json

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,27 +18,16 @@
1818
"devtools"
1919
],
2020
"type": "module",
21-
"types": "dist/index.d.ts",
22-
"module": "dist/index.js",
21+
"types": "dist/esm/index.d.ts",
22+
"module": "dist/esm/index.js",
2323
"exports": {
24-
"workerd": {
25-
"types": "./dist/index.d.ts",
26-
"import": "./dist/server.js"
24+
".": {
25+
"import": {
26+
"types": "./dist/esm/index.d.ts",
27+
"default": "./dist/esm/index.js"
28+
}
2729
},
28-
"browser": {
29-
"development": {
30-
"types": "./dist/index.d.ts",
31-
"import": "./dist/dev.js"
32-
},
33-
"types": "./dist/index.d.ts",
34-
"import": "./dist/index.js"
35-
},
36-
"node": {
37-
"types": "./dist/index.d.ts",
38-
"import": "./dist/server.js"
39-
},
40-
"types": "./dist/index.d.ts",
41-
"import": "./dist/index.js"
30+
"./package.json": "./package.json"
4231
},
4332
"sideEffects": false,
4433
"engines": {
@@ -56,7 +45,7 @@
5645
"test:lib:dev": "pnpm test:lib --watch",
5746
"test:types": "tsc",
5847
"test:build": "publint --strict",
59-
"build": "tsup"
48+
"build": "vite build"
6049
},
6150
"dependencies": {
6251
"@solid-primitives/event-listener": "^2.4.3",
@@ -77,4 +66,4 @@
7766
"tsup-preset-solid": "^2.2.0",
7867
"vite-plugin-solid": "^2.11.8"
7968
}
80-
}
69+
}

packages/devtools/src/context/devtools-context.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
getStorageItem,
88
setStorageItem,
99
} from '../utils/storage'
10-
import { initialState } from './devtools-store'
10+
import { initialState } from './initial-state'
1111
import type { DevtoolsStore } from './devtools-store'
1212
import type { JSX, Setter } from 'solid-js'
1313

@@ -39,11 +39,11 @@ export interface TanStackDevtoolsPlugin {
3939
* ```
4040
*/
4141
name:
42-
| string
43-
| ((
44-
el: HTMLHeadingElement,
45-
theme: DevtoolsStore['settings']['theme'],
46-
) => void)
42+
| string
43+
| ((
44+
el: HTMLHeadingElement,
45+
theme: DevtoolsStore['settings']['theme'],
46+
) => void)
4747
/**
4848
* Unique identifier for the plugin.
4949
* If not provided, it will be generated based on the name.

packages/devtools/src/context/devtools-store.ts

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -79,29 +79,3 @@ export type DevtoolsStore = {
7979
}
8080
plugins?: Array<TanStackDevtoolsPlugin>
8181
}
82-
83-
export const initialState: DevtoolsStore = {
84-
settings: {
85-
defaultOpen: false,
86-
hideUntilHover: false,
87-
position: 'bottom-right',
88-
panelLocation: 'bottom',
89-
openHotkey: ['Shift', 'A'],
90-
requireUrlFlag: false,
91-
urlFlag: 'tanstack-devtools',
92-
theme:
93-
typeof window !== 'undefined' &&
94-
typeof window.matchMedia !== 'undefined' &&
95-
window.matchMedia('(prefers-color-scheme: dark)').matches
96-
? 'dark'
97-
: 'light',
98-
triggerImage: '',
99-
triggerHidden: false,
100-
},
101-
state: {
102-
activeTab: 'plugins',
103-
height: 400,
104-
activePlugins: [],
105-
persistOpen: false,
106-
},
107-
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import type { DevtoolsStore } from './devtools-store'
2+
3+
export const initialState: DevtoolsStore = {
4+
settings: {
5+
defaultOpen: false,
6+
hideUntilHover: false,
7+
position: 'bottom-right',
8+
panelLocation: 'bottom',
9+
openHotkey: ['Shift', 'A'],
10+
requireUrlFlag: false,
11+
urlFlag: 'tanstack-devtools',
12+
theme:
13+
typeof window !== 'undefined' &&
14+
typeof window.matchMedia !== 'undefined' &&
15+
window.matchMedia('(prefers-color-scheme: dark)').matches
16+
? 'dark'
17+
: 'light',
18+
triggerImage: '',
19+
triggerHidden: false,
20+
},
21+
state: {
22+
activeTab: 'plugins',
23+
height: 400,
24+
activePlugins: [],
25+
persistOpen: false,
26+
},
27+
}

packages/devtools/src/core.tsx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
import { lazy } from 'solid-js'
2-
import { Portal, render } from 'solid-js/web'
1+
32
import { ClientEventBus } from '@tanstack/devtools-event-bus/client'
4-
import { DevtoolsProvider } from './context/devtools-context'
5-
import { initialState } from './context/devtools-store'
6-
import { PiPProvider } from './context/pip-context'
3+
import { initialState } from './context/initial-state'
74
import type { ClientEventBusConfig } from '@tanstack/devtools-event-bus/client'
85
import type {
96
TanStackDevtoolsConfig,
@@ -61,16 +58,18 @@ export class TanStackDevtoolsCore {
6158
}
6259
}
6360

64-
mount<T extends HTMLElement>(el: T) {
65-
// tsup-preset-solid statically replaces this variable during build, which eliminates this code from server bundle
66-
if (import.meta.env.SSR) return
61+
async mount<T extends HTMLElement>(el: T) {
6762

6863
if (this.#isMounted) {
6964
throw new Error('Devtools is already mounted')
7065
}
66+
const { render, Portal } = await import('solid-js/web')
67+
const { lazy } = await import('solid-js')
7168
const mountTo = el
7269
const dispose = render(() => {
7370
this.#Component = lazy(() => import('./devtools'))
71+
const DevtoolsProvider = lazy(() => import('./context/devtools-context').then(m => ({ default: m.DevtoolsProvider })))
72+
const PiPProvider = lazy(() => import('./context/pip-context').then(m => ({ default: m.PiPProvider })))
7473
const Devtools = this.#Component
7574
this.#eventBus = new ClientEventBus(this.#eventBusConfig)
7675
this.#eventBus.start()

packages/react-devtools/src/devtools.tsx

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ export const TanStackDevtools = ({
111111
eventBusConfig,
112112
}: TanStackDevtoolsReactInit): ReactElement | null => {
113113
const devToolRef = useRef<HTMLDivElement>(null)
114-
114+
const devtoolInstance = useRef<TanStackDevtoolsCore>(null)
115115
const [pluginContainers, setPluginContainers] = useState<
116116
Record<string, HTMLElement>
117117
>({})
@@ -135,23 +135,23 @@ export const TanStackDevtools = ({
135135
typeof plugin.name === 'string'
136136
? plugin.name
137137
: (e, theme) => {
138-
const id = e.getAttribute('id')!
139-
const target = e.ownerDocument.getElementById(id)
140-
141-
if (target) {
142-
setTitleContainers((prev) => ({
143-
...prev,
144-
[id]: e,
145-
}))
146-
}
147-
148-
convertRender(
149-
plugin.name as PluginRender,
150-
setTitleComponents,
151-
e,
152-
theme,
153-
)
154-
},
138+
const id = e.getAttribute('id')!
139+
const target = e.ownerDocument.getElementById(id)
140+
141+
if (target) {
142+
setTitleContainers((prev) => ({
143+
...prev,
144+
[id]: e,
145+
}))
146+
}
147+
148+
convertRender(
149+
plugin.name as PluginRender,
150+
setTitleComponents,
151+
e,
152+
theme,
153+
)
154+
},
155155
render: (e, theme) => {
156156
const id = e.getAttribute('id')!
157157
const target = e.ownerDocument.getElementById(id)
@@ -170,28 +170,34 @@ export const TanStackDevtools = ({
170170
[plugins],
171171
)
172172

173-
const [devtools] = useState(
174-
() =>
175-
new TanStackDevtoolsCore({
176-
config,
177-
eventBusConfig,
178-
plugins: pluginsMap,
179-
}),
180-
)
173+
// initialize devtools instance
174+
useEffect(() => {
175+
if (devtoolInstance.current) {
176+
return
177+
}
178+
devtoolInstance.current = new TanStackDevtoolsCore({
179+
config,
180+
eventBusConfig,
181+
plugins: pluginsMap,
182+
})
183+
}, [config, eventBusConfig, pluginsMap])
184+
181185

182186
useEffect(() => {
183-
devtools.setConfig({
187+
devtoolInstance.current?.setConfig({
184188
plugins: pluginsMap,
185189
})
186-
}, [devtools, pluginsMap])
190+
}, [devtoolInstance, pluginsMap])
187191

188192
useEffect(() => {
189-
if (devToolRef.current) {
190-
devtools.mount(devToolRef.current)
193+
if (!devToolRef.current) {
194+
return
191195
}
192196

193-
return () => devtools.unmount()
194-
}, [devtools])
197+
devtoolInstance.current?.mount(devToolRef.current)
198+
199+
return () => devtoolInstance.current?.unmount()
200+
}, [devtoolInstance])
195201

196202
const hasPlugins =
197203
Object.values(pluginContainers).length > 0 &&
@@ -206,14 +212,14 @@ export const TanStackDevtools = ({
206212

207213
{hasPlugins
208214
? Object.entries(pluginContainers).map(([key, pluginContainer]) =>
209-
createPortal(<>{PluginComponents[key]}</>, pluginContainer),
210-
)
215+
createPortal(<>{PluginComponents[key]}</>, pluginContainer),
216+
)
211217
: null}
212218

213219
{hasTitles
214220
? Object.entries(titleContainers).map(([key, titleContainer]) =>
215-
createPortal(<>{TitleComponents[key]}</>, titleContainer),
216-
)
221+
createPortal(<>{TitleComponents[key]}</>, titleContainer),
222+
)
217223
: null}
218224
</>
219225
)

0 commit comments

Comments
 (0)