@tanstack/router-plugin 1.167.2 → 1.167.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/core/code-splitter/compilers.cjs +28 -21
- package/dist/cjs/core/code-splitter/compilers.cjs.map +1 -1
- package/dist/cjs/core/code-splitter/plugins/framework-plugins.cjs +6 -1
- package/dist/cjs/core/code-splitter/plugins/framework-plugins.cjs.map +1 -1
- package/dist/cjs/core/code-splitter/plugins/react-refresh-ignored-route-exports.cjs +49 -0
- package/dist/cjs/core/code-splitter/plugins/react-refresh-ignored-route-exports.cjs.map +1 -0
- package/dist/cjs/core/code-splitter/plugins/react-refresh-ignored-route-exports.d.cts +2 -0
- package/dist/cjs/core/code-splitter/plugins/react-refresh-route-components.cjs +24 -12
- package/dist/cjs/core/code-splitter/plugins/react-refresh-route-components.cjs.map +1 -1
- package/dist/cjs/core/code-splitter/plugins.d.cts +2 -0
- package/dist/cjs/core/route-hmr-statement.cjs +58 -15
- package/dist/cjs/core/route-hmr-statement.cjs.map +1 -1
- package/dist/cjs/core/route-hmr-statement.d.cts +1 -1
- package/dist/cjs/core/router-code-splitter-plugin.cjs +3 -3
- package/dist/cjs/core/router-code-splitter-plugin.cjs.map +1 -1
- package/dist/cjs/core/router-hmr-plugin.cjs +2 -2
- package/dist/cjs/core/router-hmr-plugin.cjs.map +1 -1
- package/dist/cjs/core/utils.cjs +6 -0
- package/dist/cjs/core/utils.cjs.map +1 -1
- package/dist/cjs/core/utils.d.cts +1 -0
- package/dist/esm/core/code-splitter/compilers.js +23 -16
- package/dist/esm/core/code-splitter/compilers.js.map +1 -1
- package/dist/esm/core/code-splitter/plugins/framework-plugins.js +6 -1
- package/dist/esm/core/code-splitter/plugins/framework-plugins.js.map +1 -1
- package/dist/esm/core/code-splitter/plugins/react-refresh-ignored-route-exports.d.ts +2 -0
- package/dist/esm/core/code-splitter/plugins/react-refresh-ignored-route-exports.js +46 -0
- package/dist/esm/core/code-splitter/plugins/react-refresh-ignored-route-exports.js.map +1 -0
- package/dist/esm/core/code-splitter/plugins/react-refresh-route-components.js +25 -13
- package/dist/esm/core/code-splitter/plugins/react-refresh-route-components.js.map +1 -1
- package/dist/esm/core/code-splitter/plugins.d.ts +2 -0
- package/dist/esm/core/route-hmr-statement.d.ts +1 -1
- package/dist/esm/core/route-hmr-statement.js +58 -15
- package/dist/esm/core/route-hmr-statement.js.map +1 -1
- package/dist/esm/core/router-code-splitter-plugin.js +3 -3
- package/dist/esm/core/router-code-splitter-plugin.js.map +1 -1
- package/dist/esm/core/router-hmr-plugin.js +3 -3
- package/dist/esm/core/router-hmr-plugin.js.map +1 -1
- package/dist/esm/core/utils.d.ts +1 -0
- package/dist/esm/core/utils.js +6 -1
- package/dist/esm/core/utils.js.map +1 -1
- package/package.json +4 -4
- package/src/core/code-splitter/compilers.ts +47 -25
- package/src/core/code-splitter/plugins/framework-plugins.ts +2 -0
- package/src/core/code-splitter/plugins/react-refresh-ignored-route-exports.ts +65 -0
- package/src/core/code-splitter/plugins/react-refresh-route-components.ts +68 -39
- package/src/core/code-splitter/plugins.ts +4 -0
- package/src/core/route-hmr-statement.ts +141 -25
- package/src/core/router-code-splitter-plugin.ts +2 -2
- package/src/core/router-hmr-plugin.ts +7 -6
- package/src/core/utils.ts +18 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import * as template from '@babel/template'
|
|
2
|
+
import * as t from '@babel/types'
|
|
3
|
+
import { getUniqueProgramIdentifier } from '../../utils'
|
|
4
|
+
import type { ReferenceRouteCompilerPlugin } from '../plugins'
|
|
5
|
+
|
|
6
|
+
const buildReactRefreshIgnoredRouteExportsStatement = template.statement(
|
|
7
|
+
`
|
|
8
|
+
if (import.meta.hot && typeof window !== 'undefined') {
|
|
9
|
+
const tsrReactRefresh = window.__TSR_REACT_REFRESH__ ??= (() => {
|
|
10
|
+
const ignoredExportsById = new Map()
|
|
11
|
+
const previousGetIgnoredExports = window.__getReactRefreshIgnoredExports
|
|
12
|
+
|
|
13
|
+
window.__getReactRefreshIgnoredExports = (ctx) => {
|
|
14
|
+
const ignoredExports = previousGetIgnoredExports?.(ctx) ?? []
|
|
15
|
+
const moduleIgnored = ignoredExportsById.get(ctx.id) ?? []
|
|
16
|
+
return [...ignoredExports, ...moduleIgnored]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
ignoredExportsById,
|
|
21
|
+
}
|
|
22
|
+
})()
|
|
23
|
+
|
|
24
|
+
tsrReactRefresh.ignoredExportsById.set(%%moduleId%%, ['Route'])
|
|
25
|
+
}
|
|
26
|
+
`,
|
|
27
|
+
{ syntacticPlaceholders: true },
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* A trivial component-shaped export that gives `@vitejs/plugin-react` a valid
|
|
32
|
+
* Fast Refresh boundary. Without at least one non-ignored component export,
|
|
33
|
+
* the module would be invalidated (full page reload) on every update even
|
|
34
|
+
* though our custom route HMR handler already manages the update.
|
|
35
|
+
*/
|
|
36
|
+
const buildRefreshAnchorStatement = template.statement(
|
|
37
|
+
`export function %%anchorName%%() { return null }`,
|
|
38
|
+
{ syntacticPlaceholders: true },
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
export function createReactRefreshIgnoredRouteExportsPlugin(): ReferenceRouteCompilerPlugin {
|
|
42
|
+
return {
|
|
43
|
+
name: 'react-refresh-ignored-route-exports',
|
|
44
|
+
onAddHmr(ctx) {
|
|
45
|
+
const anchorName = getUniqueProgramIdentifier(
|
|
46
|
+
ctx.programPath,
|
|
47
|
+
'TSRFastRefreshAnchor',
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
ctx.programPath.pushContainer(
|
|
51
|
+
'body',
|
|
52
|
+
buildReactRefreshIgnoredRouteExportsStatement({
|
|
53
|
+
moduleId: t.stringLiteral(ctx.opts.id),
|
|
54
|
+
}),
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
ctx.programPath.pushContainer(
|
|
58
|
+
'body',
|
|
59
|
+
buildRefreshAnchorStatement({ anchorName }),
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
return { modified: true }
|
|
63
|
+
},
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -1,63 +1,92 @@
|
|
|
1
1
|
import * as t from '@babel/types'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
getObjectPropertyKeyName,
|
|
4
|
+
getUniqueProgramIdentifier,
|
|
5
|
+
} from '../../utils'
|
|
3
6
|
import type { ReferenceRouteCompilerPlugin } from '../plugins'
|
|
4
7
|
|
|
5
8
|
const REACT_REFRESH_ROUTE_COMPONENT_IDENTS = new Set([
|
|
6
9
|
'component',
|
|
10
|
+
'shellComponent',
|
|
7
11
|
'pendingComponent',
|
|
8
12
|
'errorComponent',
|
|
9
13
|
'notFoundComponent',
|
|
10
14
|
])
|
|
11
15
|
|
|
16
|
+
function hoistInlineRouteComponents(ctx: {
|
|
17
|
+
programPath: Parameters<typeof getUniqueProgramIdentifier>[0]
|
|
18
|
+
insertionPath: { insertBefore: (nodes: Array<t.VariableDeclaration>) => void }
|
|
19
|
+
routeOptions: t.ObjectExpression
|
|
20
|
+
}) {
|
|
21
|
+
const hoistedDeclarations: Array<t.VariableDeclaration> = []
|
|
22
|
+
|
|
23
|
+
ctx.routeOptions.properties.forEach((prop) => {
|
|
24
|
+
if (!t.isObjectProperty(prop)) {
|
|
25
|
+
return
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const key = getObjectPropertyKeyName(prop)
|
|
29
|
+
|
|
30
|
+
if (!key || !REACT_REFRESH_ROUTE_COMPONENT_IDENTS.has(key)) {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (
|
|
35
|
+
!t.isArrowFunctionExpression(prop.value) &&
|
|
36
|
+
!t.isFunctionExpression(prop.value)
|
|
37
|
+
) {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const hoistedIdentifier = getUniqueProgramIdentifier(
|
|
42
|
+
ctx.programPath,
|
|
43
|
+
`TSR${key[0]!.toUpperCase()}${key.slice(1)}`,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
hoistedDeclarations.push(
|
|
47
|
+
t.variableDeclaration('const', [
|
|
48
|
+
t.variableDeclarator(hoistedIdentifier, t.cloneNode(prop.value, true)),
|
|
49
|
+
]),
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
prop.value = t.cloneNode(hoistedIdentifier)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
if (hoistedDeclarations.length === 0) {
|
|
56
|
+
return false
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
ctx.insertionPath.insertBefore(hoistedDeclarations)
|
|
60
|
+
return true
|
|
61
|
+
}
|
|
62
|
+
|
|
12
63
|
export function createReactRefreshRouteComponentsPlugin(): ReferenceRouteCompilerPlugin {
|
|
13
64
|
return {
|
|
14
65
|
name: 'react-refresh-route-components',
|
|
66
|
+
getStableRouteOptionKeys() {
|
|
67
|
+
return [...REACT_REFRESH_ROUTE_COMPONENT_IDENTS]
|
|
68
|
+
},
|
|
15
69
|
onUnsplittableRoute(ctx) {
|
|
16
70
|
if (!ctx.opts.addHmr) {
|
|
17
71
|
return
|
|
18
72
|
}
|
|
19
73
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (
|
|
32
|
-
!t.isArrowFunctionExpression(prop.value) &&
|
|
33
|
-
!t.isFunctionExpression(prop.value)
|
|
34
|
-
) {
|
|
35
|
-
return
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const hoistedIdentifier = getUniqueProgramIdentifier(
|
|
39
|
-
ctx.programPath,
|
|
40
|
-
`TSR${prop.key.name[0]!.toUpperCase()}${prop.key.name.slice(1)}`,
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
hoistedDeclarations.push(
|
|
44
|
-
t.variableDeclaration('const', [
|
|
45
|
-
t.variableDeclarator(
|
|
46
|
-
hoistedIdentifier,
|
|
47
|
-
t.cloneNode(prop.value, true),
|
|
48
|
-
),
|
|
49
|
-
]),
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
prop.value = t.cloneNode(hoistedIdentifier)
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
if (hoistedDeclarations.length === 0) {
|
|
74
|
+
if (hoistInlineRouteComponents(ctx)) {
|
|
75
|
+
return { modified: true }
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return
|
|
79
|
+
},
|
|
80
|
+
onAddHmr(ctx) {
|
|
81
|
+
if (!ctx.opts.addHmr) {
|
|
56
82
|
return
|
|
57
83
|
}
|
|
58
84
|
|
|
59
|
-
ctx
|
|
60
|
-
|
|
85
|
+
if (hoistInlineRouteComponents(ctx)) {
|
|
86
|
+
return { modified: true }
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return
|
|
61
90
|
},
|
|
62
91
|
}
|
|
63
92
|
}
|
|
@@ -39,6 +39,10 @@ export type ReferenceRouteCompilerPluginResult = {
|
|
|
39
39
|
|
|
40
40
|
export type ReferenceRouteCompilerPlugin = {
|
|
41
41
|
name: string
|
|
42
|
+
getStableRouteOptionKeys?: () => Array<string>
|
|
43
|
+
onAddHmr?: (
|
|
44
|
+
ctx: ReferenceRouteCompilerPluginContext,
|
|
45
|
+
) => void | ReferenceRouteCompilerPluginResult
|
|
42
46
|
onUnsplittableRoute?: (
|
|
43
47
|
ctx: ReferenceRouteCompilerPluginContext,
|
|
44
48
|
) => void | ReferenceRouteCompilerPluginResult
|
|
@@ -2,39 +2,145 @@ import * as template from '@babel/template'
|
|
|
2
2
|
import type { AnyRoute, AnyRouteMatch, AnyRouter } from '@tanstack/router-core'
|
|
3
3
|
|
|
4
4
|
type AnyRouteWithPrivateProps = AnyRoute & {
|
|
5
|
+
options: Record<string, unknown>
|
|
6
|
+
_componentsPromise?: Promise<void>
|
|
7
|
+
_lazyPromise?: Promise<void>
|
|
8
|
+
update: (options: Record<string, unknown>) => unknown
|
|
5
9
|
_path: string
|
|
6
10
|
_id: string
|
|
7
11
|
_fullPath: string
|
|
8
12
|
_to: string
|
|
9
13
|
}
|
|
10
14
|
|
|
15
|
+
type AnyRouterWithPrivateMaps = AnyRouter & {
|
|
16
|
+
routesById: Record<string, AnyRoute>
|
|
17
|
+
routesByPath: Record<string, AnyRoute>
|
|
18
|
+
stores: AnyRouter['stores'] & {
|
|
19
|
+
cachedMatchStoresById: Map<
|
|
20
|
+
string,
|
|
21
|
+
{
|
|
22
|
+
setState: (updater: (prev: AnyRouteMatch) => AnyRouteMatch) => void
|
|
23
|
+
}
|
|
24
|
+
>
|
|
25
|
+
pendingMatchStoresById: Map<
|
|
26
|
+
string,
|
|
27
|
+
{
|
|
28
|
+
setState: (updater: (prev: AnyRouteMatch) => AnyRouteMatch) => void
|
|
29
|
+
}
|
|
30
|
+
>
|
|
31
|
+
activeMatchStoresById: Map<
|
|
32
|
+
string,
|
|
33
|
+
{
|
|
34
|
+
setState: (updater: (prev: AnyRouteMatch) => AnyRouteMatch) => void
|
|
35
|
+
}
|
|
36
|
+
>
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
type AnyRouteMatchWithPrivateProps = AnyRouteMatch & {
|
|
41
|
+
__beforeLoadContext?: unknown
|
|
42
|
+
}
|
|
43
|
+
|
|
11
44
|
function handleRouteUpdate(
|
|
12
|
-
|
|
45
|
+
routeId: string,
|
|
13
46
|
newRoute: AnyRouteWithPrivateProps,
|
|
14
47
|
) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
48
|
+
const router = window.__TSR_ROUTER__ as AnyRouterWithPrivateMaps
|
|
49
|
+
const oldRoute = router.routesById[routeId] as
|
|
50
|
+
| AnyRouteWithPrivateProps
|
|
51
|
+
| undefined
|
|
52
|
+
|
|
53
|
+
if (!oldRoute) {
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Keys whose identity must remain stable to prevent React from
|
|
58
|
+
// unmounting/remounting the component tree. React Fast Refresh already
|
|
59
|
+
// handles hot-updating the function bodies of these components — our job
|
|
60
|
+
// is only to update non-component route options (loader, head, etc.).
|
|
61
|
+
// For code-split (splittable) routes, the lazyRouteComponent wrapper is
|
|
62
|
+
// already cached in import.meta.hot.data so its identity is stable.
|
|
63
|
+
// For unsplittable routes (e.g. root routes), the component is a plain
|
|
64
|
+
// function reference that gets recreated on every module re-execution,
|
|
65
|
+
// so we must explicitly preserve the old reference.
|
|
66
|
+
const removedKeys = new Set<string>()
|
|
67
|
+
Object.keys(oldRoute.options).forEach((key) => {
|
|
68
|
+
if (!(key in newRoute.options)) {
|
|
69
|
+
removedKeys.add(key)
|
|
70
|
+
delete oldRoute.options[key]
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
// Preserve component identity so React doesn't remount.
|
|
75
|
+
// React Fast Refresh patches the function bodies in-place.
|
|
76
|
+
const componentKeys = '__TSR_COMPONENT_TYPES__' as unknown as Array<string>
|
|
77
|
+
componentKeys.forEach((key) => {
|
|
78
|
+
if (key in oldRoute.options && key in newRoute.options) {
|
|
79
|
+
newRoute.options[key] = oldRoute.options[key]
|
|
80
|
+
}
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
oldRoute.options = newRoute.options
|
|
84
|
+
oldRoute.update(newRoute.options)
|
|
85
|
+
oldRoute._componentsPromise = undefined
|
|
86
|
+
oldRoute._lazyPromise = undefined
|
|
87
|
+
|
|
88
|
+
router.routesById[oldRoute.id] = oldRoute
|
|
89
|
+
router.routesByPath[oldRoute.fullPath] = oldRoute
|
|
90
|
+
|
|
25
91
|
router.processedTree.matchCache.clear()
|
|
26
92
|
router.processedTree.flatCache?.clear()
|
|
27
93
|
router.processedTree.singleCache.clear()
|
|
28
94
|
router.resolvePathCache.clear()
|
|
29
|
-
|
|
30
|
-
|
|
95
|
+
walkReplaceSegmentTree(oldRoute, router.processedTree.segmentTree)
|
|
96
|
+
|
|
31
97
|
const filter = (m: AnyRouteMatch) => m.routeId === oldRoute.id
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
98
|
+
const activeMatch = router.stores.activeMatchesSnapshot.state.find(filter)
|
|
99
|
+
const pendingMatch = router.stores.pendingMatchesSnapshot.state.find(filter)
|
|
100
|
+
const cachedMatches = router.stores.cachedMatchesSnapshot.state.filter(filter)
|
|
101
|
+
|
|
102
|
+
if (activeMatch || pendingMatch || cachedMatches.length > 0) {
|
|
103
|
+
// Clear stale match data for removed route options BEFORE invalidating.
|
|
104
|
+
// Without this, router.invalidate() -> matchRoutes() reuses the existing
|
|
105
|
+
// match from the store (via ...existingMatch spread) and the stale
|
|
106
|
+
// loaderData / __beforeLoadContext survives the reload cycle.
|
|
107
|
+
//
|
|
108
|
+
// We must update the store directly (not via router.updateMatch) because
|
|
109
|
+
// updateMatch wraps in startTransition which may defer the state update,
|
|
110
|
+
// and we need the clear to be visible before invalidate reads the store.
|
|
111
|
+
if (removedKeys.has('loader') || removedKeys.has('beforeLoad')) {
|
|
112
|
+
const matchIds = [
|
|
113
|
+
activeMatch?.id,
|
|
114
|
+
pendingMatch?.id,
|
|
115
|
+
...cachedMatches.map((match) => match.id),
|
|
116
|
+
].filter(Boolean) as Array<string>
|
|
117
|
+
router.batch(() => {
|
|
118
|
+
for (const matchId of matchIds) {
|
|
119
|
+
const store =
|
|
120
|
+
router.stores.pendingMatchStoresById.get(matchId) ||
|
|
121
|
+
router.stores.activeMatchStoresById.get(matchId) ||
|
|
122
|
+
router.stores.cachedMatchStoresById.get(matchId)
|
|
123
|
+
if (store) {
|
|
124
|
+
store.setState((prev) => {
|
|
125
|
+
const next: AnyRouteMatchWithPrivateProps = { ...prev }
|
|
126
|
+
|
|
127
|
+
if (removedKeys.has('loader')) {
|
|
128
|
+
next.loaderData = undefined
|
|
129
|
+
}
|
|
130
|
+
if (removedKeys.has('beforeLoad')) {
|
|
131
|
+
next.__beforeLoadContext = undefined
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return next
|
|
135
|
+
})
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
})
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
router.invalidate({ filter, sync: true })
|
|
37
142
|
}
|
|
143
|
+
|
|
38
144
|
function walkReplaceSegmentTree(
|
|
39
145
|
route: AnyRouteWithPrivateProps,
|
|
40
146
|
node: AnyRouter['processedTree']['segmentTree'],
|
|
@@ -51,16 +157,26 @@ function handleRouteUpdate(
|
|
|
51
157
|
}
|
|
52
158
|
}
|
|
53
159
|
|
|
54
|
-
|
|
55
|
-
|
|
160
|
+
const handleRouteUpdateStr = handleRouteUpdate.toString()
|
|
161
|
+
|
|
162
|
+
export function createRouteHmrStatement(stableRouteOptionKeys: Array<string>) {
|
|
163
|
+
return template.statement(
|
|
164
|
+
`
|
|
56
165
|
if (import.meta.hot) {
|
|
57
166
|
import.meta.hot.accept((newModule) => {
|
|
58
167
|
if (Route && newModule && newModule.Route) {
|
|
59
|
-
|
|
168
|
+
const routeId = import.meta.hot.data['tsr-route-id'] ?? Route.id
|
|
169
|
+
if (routeId) {
|
|
170
|
+
import.meta.hot.data['tsr-route-id'] = routeId
|
|
171
|
+
}
|
|
172
|
+
(${handleRouteUpdateStr.replace(
|
|
173
|
+
/['"]__TSR_COMPONENT_TYPES__['"]/,
|
|
174
|
+
JSON.stringify(stableRouteOptionKeys),
|
|
175
|
+
)})(routeId, newModule.Route)
|
|
60
176
|
}
|
|
61
|
-
|
|
177
|
+
})
|
|
62
178
|
}
|
|
63
179
|
`,
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
180
|
+
{ placeholderPattern: false },
|
|
181
|
+
)()
|
|
182
|
+
}
|
|
@@ -116,7 +116,7 @@ export const unpluginRouterCodeSplitterFactory: UnpluginFactory<
|
|
|
116
116
|
code,
|
|
117
117
|
})
|
|
118
118
|
|
|
119
|
-
if (fromCode.groupings) {
|
|
119
|
+
if (fromCode.groupings !== undefined) {
|
|
120
120
|
const res = splitGroupingsSchema.safeParse(fromCode.groupings)
|
|
121
121
|
if (!res.success) {
|
|
122
122
|
const message = res.error.errors.map((e) => e.message).join('. ')
|
|
@@ -143,7 +143,7 @@ export const unpluginRouterCodeSplitterFactory: UnpluginFactory<
|
|
|
143
143
|
}
|
|
144
144
|
|
|
145
145
|
const splitGroupings: CodeSplitGroupings =
|
|
146
|
-
fromCode.groupings
|
|
146
|
+
fromCode.groupings ?? pluginSplitBehavior ?? getGlobalCodeSplitGroupings()
|
|
147
147
|
|
|
148
148
|
// Compute shared bindings before compiling the reference route
|
|
149
149
|
const sharedBindings = computeSharedBindings({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { generateFromAst, logDiff, parseAst } from '@tanstack/router-utils'
|
|
2
2
|
import { compileCodeSplitReferenceRoute } from './code-splitter/compilers'
|
|
3
3
|
import { getReferenceRouteCompilerPlugins } from './code-splitter/plugins/framework-plugins'
|
|
4
|
-
import {
|
|
4
|
+
import { createRouteHmrStatement } from './route-hmr-statement'
|
|
5
5
|
import { debug, normalizePath } from './utils'
|
|
6
6
|
import { getConfig } from './config'
|
|
7
7
|
import type { UnpluginFactory } from 'unplugin'
|
|
@@ -44,6 +44,10 @@ export const unpluginRouterHmrFactory: UnpluginFactory<
|
|
|
44
44
|
if (debug) console.info('Adding HMR handling to route ', normalizedId)
|
|
45
45
|
|
|
46
46
|
if (userConfig.target === 'react') {
|
|
47
|
+
const compilerPlugins = getReferenceRouteCompilerPlugins({
|
|
48
|
+
targetFramework: 'react',
|
|
49
|
+
addHmr: true,
|
|
50
|
+
})
|
|
47
51
|
const compiled = compileCodeSplitReferenceRoute({
|
|
48
52
|
code,
|
|
49
53
|
filename: normalizedId,
|
|
@@ -51,10 +55,7 @@ export const unpluginRouterHmrFactory: UnpluginFactory<
|
|
|
51
55
|
addHmr: true,
|
|
52
56
|
codeSplitGroupings: [],
|
|
53
57
|
targetFramework: 'react',
|
|
54
|
-
compilerPlugins
|
|
55
|
-
targetFramework: 'react',
|
|
56
|
-
addHmr: true,
|
|
57
|
-
}),
|
|
58
|
+
compilerPlugins,
|
|
58
59
|
})
|
|
59
60
|
|
|
60
61
|
if (compiled) {
|
|
@@ -68,7 +69,7 @@ export const unpluginRouterHmrFactory: UnpluginFactory<
|
|
|
68
69
|
}
|
|
69
70
|
|
|
70
71
|
const ast = parseAst({ code })
|
|
71
|
-
ast.program.body.push(
|
|
72
|
+
ast.program.body.push(createRouteHmrStatement([]))
|
|
72
73
|
const result = generateFromAst(ast, {
|
|
73
74
|
sourceMaps: true,
|
|
74
75
|
filename: normalizedId,
|
package/src/core/utils.ts
CHANGED
|
@@ -16,6 +16,24 @@ export function normalizePath(path: string): string {
|
|
|
16
16
|
return path.replace(/\\/g, '/')
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
export function getObjectPropertyKeyName(
|
|
20
|
+
prop: t.ObjectProperty,
|
|
21
|
+
): string | undefined {
|
|
22
|
+
if (prop.computed) {
|
|
23
|
+
return undefined
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (t.isIdentifier(prop.key)) {
|
|
27
|
+
return prop.key.name
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (t.isStringLiteral(prop.key)) {
|
|
31
|
+
return prop.key.value
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return undefined
|
|
35
|
+
}
|
|
36
|
+
|
|
19
37
|
export function getUniqueProgramIdentifier(
|
|
20
38
|
programPath: babel.NodePath<t.Program>,
|
|
21
39
|
baseName: string,
|