Skip to content

Commit faed7fa

Browse files
committed
feat(vue-jsx-vapor): support hmr for functional components
1 parent c1091da commit faed7fa

File tree

3 files changed

+21
-30
lines changed

3 files changed

+21
-30
lines changed

docs/index.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ features:
2828
title: Type Safe
2929
details: Provide Volar support by install TS Macro (VSCode plugin).
3030
- icon: ⚡️
31-
title: Performance
31+
title: High Performance
3232
details: It has the same performance with Vue Vapor!
33+
- icon: 🌈
34+
title: Hot Module Replacement
35+
details: Support functional components or defined by defineComponent.
3336
---
3437

packages/vue-jsx-vapor/src/core/hmr.ts

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
import { isFunctionalNode } from '@vue-jsx-vapor/macros/api'
12
import getHash from 'hash-sum'
2-
import { normalizePath } from 'unplugin-utils'
33
import type { BabelFileResult, types } from '@babel/core'
44

55
interface HotComponent {
@@ -11,19 +11,19 @@ interface HotComponent {
1111
export function registerHMR(
1212
result: BabelFileResult,
1313
id: string,
14-
defineComponentName = ['defineComponent', 'defineVaporComponent'],
14+
defineComponentNames = ['defineComponent', 'defineVaporComponent'],
1515
) {
1616
const { ast } = result
1717

1818
// check for hmr injection
1919
const declaredComponents: string[] = []
2020
const hotComponents: HotComponent[] = []
21-
let defaultName = ''
21+
let hasDefaultExport = false
2222
const ssr = false
2323

2424
for (const node of ast!.program.body) {
2525
if (node.type === 'VariableDeclaration') {
26-
const names = parseComponentDecls(node, defineComponentName)
26+
const names = parseComponentDecls(node, defineComponentNames)
2727
if (names.length) {
2828
declaredComponents.push(...names)
2929
}
@@ -32,7 +32,7 @@ export function registerHMR(
3232
if (node.type === 'ExportNamedDeclaration') {
3333
if (node.declaration && node.declaration.type === 'VariableDeclaration') {
3434
hotComponents.push(
35-
...parseComponentDecls(node.declaration, defineComponentName).map(
35+
...parseComponentDecls(node.declaration, defineComponentNames).map(
3636
(name) => ({
3737
local: name,
3838
exported: name,
@@ -72,8 +72,11 @@ export function registerHMR(
7272
id: getHash(`${id}default`),
7373
})
7474
}
75-
} else if (isDefineComponentCall(node.declaration, defineComponentName)) {
76-
defaultName = (node.declaration.callee as any).name
75+
} else if (
76+
isDefineComponentCall(node.declaration, defineComponentNames) ||
77+
isFunctionalNode(node.declaration)
78+
) {
79+
hasDefaultExport = true
7780
hotComponents.push({
7881
local: '__default__',
7982
exported: 'default',
@@ -84,10 +87,10 @@ export function registerHMR(
8487
}
8588

8689
if (hotComponents.length) {
87-
if (defaultName || ssr) {
90+
if (hasDefaultExport || ssr) {
8891
result.code = `${result.code!.replaceAll(
89-
`export default ${defaultName}`,
90-
`const __default__ = ${defaultName}`,
92+
`export default `,
93+
`const __default__ = `,
9194
)}\nexport default __default__`
9295
}
9396

@@ -99,19 +102,12 @@ export function registerHMR(
99102
`\n${local}.__hmrId = "${id}"` +
100103
`\n__VUE_HMR_RUNTIME__.createRecord("${id}", ${local})`
101104
callbackCode += `
102-
if (mod._rerender_only) {
103-
__VUE_HMR_RUNTIME__.rerender(mod['${exported}'].__hmrId, mod['${exported}'].setup)
104-
} else {
105-
__VUE_HMR_RUNTIME__.reload(mod['${exported}'].__hmrId, mod['${exported}'])
106-
}`
105+
__VUE_HMR_RUNTIME__.rerender(mod['${exported}'].__hmrId, mod['${exported}'].setup || mod['${exported}'])
106+
`
107107
}
108108

109-
code += `\nexport const _rerender_only = __VUE_HMR_RUNTIME__.CHANGED_FILE === ${JSON.stringify(normalizePath(id))}`
110109
code += `
111110
if (import.meta.hot) {
112-
import.meta.hot.on('file-changed', ({ file }) => {
113-
__VUE_HMR_RUNTIME__.CHANGED_FILE = file
114-
})
115111
import.meta.hot.accept((mod) => {${callbackCode}\n})
116112
}`
117113
result.code = code
@@ -138,10 +134,9 @@ function parseComponentDecls(
138134
for (const decl of node.declarations) {
139135
if (
140136
decl.id.type === 'Identifier' &&
141-
isDefineComponentCall(decl.init, fnNames)
142-
) {
137+
(isDefineComponentCall(decl.init, fnNames) || isFunctionalNode(decl.init))
138+
)
143139
names.push(decl.id.name)
144-
}
145140
}
146141
return names
147142
}

packages/vue-jsx-vapor/src/raw.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,6 @@ const plugin = (options: Options = {}): UnpluginOptions[] => {
3030
},
3131
}
3232
},
33-
handleHotUpdate(ctx) {
34-
ctx.server.ws.send({
35-
type: 'custom',
36-
event: 'file-changed',
37-
data: { file: normalizePath(ctx.file) },
38-
})
39-
},
4033
},
4134
resolveId(id) {
4235
if (normalizePath(id) === 'vue-jsx-vapor/runtime') return id

0 commit comments

Comments
 (0)