Skip to content

Commit f46540b

Browse files
committed
feat: using vite hmr runtime
1 parent 05a2be6 commit f46540b

File tree

6 files changed

+86
-12
lines changed

6 files changed

+86
-12
lines changed

packages/vite/src/client/client.ts

+11-10
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import {
77
normalizeModuleRunnerTransport,
88
} from '../shared/moduleRunnerTransport'
99
import { ErrorOverlay, overlayId } from './overlay'
10-
import '@vite/env'
10+
import './hmrModuleRunner'
11+
// import '@vite/env'
1112

1213
// injected by the hmr plugin when served
1314
declare const __BASE__: string
@@ -140,19 +141,16 @@ const hmrClient = new HMRClient(
140141
},
141142
transport,
142143
async function importUpdatedModule({
144+
url,
143145
acceptedPath,
144-
timestamp,
145-
explicitImportRequired,
146+
// timestamp,
147+
// explicitImportRequired,
146148
isWithinCircularImport,
147149
}) {
148-
const [acceptedPathWithoutQuery, query] = acceptedPath.split(`?`)
150+
// const [acceptedPathWithoutQuery, query] = acceptedPath.split(`?`)
149151
const importPromise = import(
150152
/* @vite-ignore */
151-
base +
152-
acceptedPathWithoutQuery.slice(1) +
153-
`?${explicitImportRequired ? 'import&' : ''}t=${timestamp}${
154-
query ? `&${query}` : ''
155-
}`
153+
base + url
156154
)
157155
if (isWithinCircularImport) {
158156
importPromise.catch(() => {
@@ -163,7 +161,10 @@ const hmrClient = new HMRClient(
163161
pageReload()
164162
})
165163
}
166-
return await importPromise
164+
// @ts-expect-error globalThis.__rolldown_runtime__
165+
return await importPromise.then(() =>
166+
globalThis.__rolldown_runtime__.loadExports(acceptedPath),
167+
)
167168
},
168169
)
169170
transport.connect!(handleMessage)

packages/vite/src/node/build.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ import type { MinimalPluginContext, Plugin, PluginContext } from './plugin'
8787
import type { RollupPluginHooks } from './typeUtils'
8888
import { buildOxcPlugin } from './plugins/oxc'
8989
import type { ViteDevServer } from './server'
90+
import { getHmrImplement } from './plugins/clientInjections'
9091

9192
export interface BuildEnvironmentOptions {
9293
/**
@@ -655,7 +656,12 @@ async function buildEnvironment(
655656
'.css': 'js',
656657
},
657658
experimental: {
658-
hmr: true,
659+
hmr: server
660+
? {
661+
implement: await getHmrImplement(environment.config),
662+
}
663+
: false,
664+
// hmr: true,
659665
// hmr: server ? {
660666
// host: server._currentServerHost!,
661667
// port: server._currentServerPort!,

packages/vite/src/node/plugins/clientInjections.ts

+63
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import path from 'node:path'
2+
import fs from 'node:fs'
23
import type { Plugin } from '../plugin'
34
import type { ResolvedConfig } from '../config'
45
import { CLIENT_ENTRY, ENV_ENTRY } from '../constants'
@@ -121,3 +122,65 @@ function escapeReplacement(value: string | number | boolean | null) {
121122
const jsonValue = JSON.stringify(value)
122123
return () => jsonValue
123124
}
125+
126+
export async function getHmrImplement(config: ResolvedConfig): Promise<string> {
127+
const content = fs.readFileSync(normalizedClientEntry, 'utf-8')
128+
const resolvedServerHostname = (await resolveHostname(config.server.host))
129+
.name
130+
const resolvedServerPort = config.server.port!
131+
const devBase = config.base
132+
133+
const serverHost = `${resolvedServerHostname}:${resolvedServerPort}${devBase}`
134+
135+
let hmrConfig = config.server.hmr
136+
hmrConfig = isObject(hmrConfig) ? hmrConfig : undefined
137+
const host = hmrConfig?.host || null
138+
const protocol = hmrConfig?.protocol || null
139+
const timeout = hmrConfig?.timeout || 30000
140+
const overlay = hmrConfig?.overlay !== false
141+
const isHmrServerSpecified = !!hmrConfig?.server
142+
const hmrConfigName = path.basename(config.configFile || 'vite.config.js')
143+
144+
// hmr.clientPort -> hmr.port
145+
// -> (24678 if middleware mode and HMR server is not specified) -> new URL(import.meta.url).port
146+
let port = hmrConfig?.clientPort || hmrConfig?.port || null
147+
if (config.server.middlewareMode && !isHmrServerSpecified) {
148+
port ||= 24678
149+
}
150+
151+
let directTarget = hmrConfig?.host || resolvedServerHostname
152+
directTarget += `:${hmrConfig?.port || resolvedServerPort}`
153+
directTarget += devBase
154+
155+
let hmrBase = devBase
156+
if (hmrConfig?.path) {
157+
hmrBase = path.posix.join(hmrBase, hmrConfig.path)
158+
}
159+
160+
const modeReplacement = escapeReplacement(config.mode)
161+
const baseReplacement = escapeReplacement(devBase)
162+
const serverHostReplacement = escapeReplacement(serverHost)
163+
const hmrProtocolReplacement = escapeReplacement(protocol)
164+
const hmrHostnameReplacement = escapeReplacement(host)
165+
const hmrPortReplacement = escapeReplacement(port)
166+
const hmrDirectTargetReplacement = escapeReplacement(directTarget)
167+
const hmrBaseReplacement = escapeReplacement(hmrBase)
168+
const hmrTimeoutReplacement = escapeReplacement(timeout)
169+
const hmrEnableOverlayReplacement = escapeReplacement(overlay)
170+
const hmrConfigNameReplacement = escapeReplacement(hmrConfigName)
171+
const wsTokenReplacement = escapeReplacement(config.webSocketToken)
172+
173+
return content
174+
.replace(`__MODE__`, modeReplacement)
175+
.replace(/__BASE__/g, baseReplacement)
176+
.replace(`__SERVER_HOST__`, serverHostReplacement)
177+
.replace(`__HMR_PROTOCOL__`, hmrProtocolReplacement)
178+
.replace(`__HMR_HOSTNAME__`, hmrHostnameReplacement)
179+
.replace(`__HMR_PORT__`, hmrPortReplacement)
180+
.replace(`__HMR_DIRECT_TARGET__`, hmrDirectTargetReplacement)
181+
.replace(`__HMR_BASE__`, hmrBaseReplacement)
182+
.replace(`__HMR_TIMEOUT__`, hmrTimeoutReplacement)
183+
.replace(`__HMR_ENABLE_OVERLAY__`, hmrEnableOverlayReplacement)
184+
.replace(`__HMR_CONFIG_NAME__`, hmrConfigNameReplacement)
185+
.replace(`__WS_TOKEN__`, wsTokenReplacement)
186+
}

packages/vite/src/node/plugins/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ export async function resolvePlugins(
131131
: oxcPlugin(config)
132132
: null,
133133
enableNativePlugin === true
134-
? nativeJsonPlugin({ ...config.json, isBuild })
134+
? nativeJsonPlugin({ ...config.json, minify: isBuild })
135135
: jsonPlugin(config.json, isBuild),
136136
enableNativePlugin === true ? nativeWasmHelperPlugin() : wasmHelperPlugin(),
137137
webWorkerPlugin(config),

packages/vite/types/hmrPayload.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export interface UpdatePayload {
2424

2525
export interface Update {
2626
type: 'js-update' | 'css-update'
27+
url?: string // the hmr chunk url
2728
path: string
2829
acceptedPath: string
2930
timestamp: number

vitest.config.e2e.ts

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ export default defineConfig({
1414
test: {
1515
include: ['./playground/**/*.spec.[tj]s'],
1616
exclude: [
17+
'./playground/hmr/**/*.spec.[tj]s',
18+
'./playground/ssr/**/*.spec.[tj]s',
19+
'./playground/ssr*/**/*.spec.[tj]s',
1720
'./playground/legacy/**/*.spec.[tj]s', // system format
1821
...(isBuild
1922
? [

0 commit comments

Comments
 (0)