From 818ad209ea7de4b7dcdf574dd5e622f3495d584d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Horv=C3=A1th?= Date: Sun, 5 May 2024 21:26:15 +0200 Subject: [PATCH] vite 6 --- examples/vike/package.json | 2 +- package.json | 5 +- packages/vike-node/package.json | 2 +- .../plugins/devServer/devServerPlugin.ts | 180 +++++++++++++----- .../src/plugin/plugins/devServer/types.ts | 6 +- .../src/plugin/plugins/devServer/worker.ts | 40 ++-- pnpm-lock.yaml | 31 +-- 7 files changed, 188 insertions(+), 78 deletions(-) diff --git a/examples/vike/package.json b/examples/vike/package.json index aadb7aa..2eb0111 100644 --- a/examples/vike/package.json +++ b/examples/vike/package.json @@ -28,7 +28,7 @@ "typescript": "^5.3.3", "vike": "0.4.161", "vike-node": "^0.0.1", - "vite": "6.0.0-alpha.0" + "vite": "6.0.0-alpha.11" }, "type": "module" } \ No newline at end of file diff --git a/package.json b/package.json index 96a2897..9f035bc 100644 --- a/package.json +++ b/package.json @@ -22,10 +22,11 @@ }, "pnpm": { "overrides": { - "vike-node": "link:./packages/vike-node/" + "vike-node": "link:./packages/vike-node/", + "vite": "6.0.0-alpha.11" }, "patchedDependencies": { "vike@0.4.161": "patches/vike@0.4.161.patch" } } -} +} \ No newline at end of file diff --git a/packages/vike-node/package.json b/packages/vike-node/package.json index 8e9f8e0..d0f3e33 100644 --- a/packages/vike-node/package.json +++ b/packages/vike-node/package.json @@ -32,7 +32,7 @@ "fastify": "^4.26.1", "typescript": "^5.3.3", "vike": "0.4.161", - "vite": "6.0.0-alpha.0" + "vite": "6.0.0-alpha.11" }, "typesVersions": { "*": { diff --git a/packages/vike-node/src/plugin/plugins/devServer/devServerPlugin.ts b/packages/vike-node/src/plugin/plugins/devServer/devServerPlugin.ts index 836c664..f46efb2 100644 --- a/packages/vike-node/src/plugin/plugins/devServer/devServerPlugin.ts +++ b/packages/vike-node/src/plugin/plugins/devServer/devServerPlugin.ts @@ -3,7 +3,14 @@ export { devServerPlugin } import pc from '@brillout/picocolors' import { BirpcReturn, createBirpc } from 'birpc' import { ChildProcess, fork } from 'child_process' -import { EnvironmentModuleNode, HMRChannel, ModuleNode, Plugin, ViteDevServer } from 'vite' +import { + DevEnvironment, + EnvironmentModuleNode, + HMRChannel, + Plugin, + RemoteEnvironmentTransport, + ViteDevServer +} from 'vite' import { ConfigVikeNodeResolved } from '../../../types.js' import { assert } from '../../../utils/assert.js' import { getConfigVikeNode } from '../../utils/getConfigVikeNode.js' @@ -19,6 +26,8 @@ let vite: ViteDevServer let rpc: BirpcReturn let cp: ChildProcess | undefined let entryAbs: string +let onMessageHandler: (data: any) => void +let hmrHandler: ((data: any) => void) | undefined function devServerPlugin(): Plugin { let resolvedConfig: ConfigVikeNodeResolved @@ -34,6 +43,40 @@ function devServerPlugin(): Plugin { // this needs to be exposed in containers port: viteHmrPort } + }, + environments: { + ssr: { + dev: { + createEnvironment(name, config) { + const hot = createSimpleHMRChannel({ + name, + post: (data) => rpc.onHmrReceive(data), + on: (listener) => { + hmrHandler = listener + return () => { + hmrHandler = undefined + } + }, + async onRestartWorker() { + await restartWorker() + vite.environments.client.hot.send({ type: 'full-reload' }) + } + }) + + return new DevEnvironment('ssr', config, { + runner: { + transport: new RemoteEnvironmentTransport({ + send: (data) => rpc.onViteTransportMessage(data), + onMessage: (handler) => { + onMessageHandler = handler + } + }) + }, + hot + }) + } + } + } } } }, @@ -42,7 +85,7 @@ function devServerPlugin(): Plugin { assert(resolvedConfig.server) }, async hotUpdate(ctx) { - console.log(ctx.environment.name, ctx.modules, ctx.type) + // console.log(ctx.environment.name, ctx.modules, ctx.type) if (ctx.environment.name !== 'ssr') { return } @@ -52,29 +95,6 @@ function devServerPlugin(): Plugin { ctx.server.environments.client.hot.send({ type: 'full-reload' }) return [] } - - if (!ctx.modules.length) return [] - const mods = ctx.modules.map((m) => m.id).filter(Boolean) as string[] - await rpc.invalidateDepTree(mods) - const modules = new Set(ctx.modules) - let shouldRestart = false - for (const module of modules) { - if (module.file === entryAbs) { - shouldRestart = true - break - } - - for (const importerInner of module.importers) { - modules.add(importerInner) - } - } - - if (shouldRestart) { - await restartWorker() - ctx.server.environments.client.hot.send({ type: 'full-reload' }) - } - - return [] }, // called on start & vite.config.js changes configureServer(vite_) { @@ -90,6 +110,7 @@ function devServerPlugin(): Plugin { } } }) + vite.printUrls = () => {} restartWorker() } @@ -106,16 +127,7 @@ function devServerPlugin(): Plugin { assert(resolvedConfig.server) const index = resolvedConfig.server.entry.index - const originalInvalidateModule = vite.moduleGraph.invalidateModule.bind(vite.moduleGraph) - vite.moduleGraph.invalidateModule = (mod, ...rest) => { - if (mod.id) { - // timeout error - rpc.deleteByModuleId(mod.id).catch(() => {}) - } - return originalInvalidateModule(mod, ...rest) - } - - const indexResolved = await vite.pluginContainer.resolveId(index, undefined) + const indexResolved = await vite.environments.ssr.pluginContainer.resolveId(index, undefined) assert(indexResolved?.id) entryAbs = indexResolved.id @@ -134,16 +146,11 @@ function devServerPlugin(): Plugin { rpc = createBirpc( { - async fetchModule(id, importer) { - const result = await vite.environments.ssr.fetchModule(id, importer) - if (resolvedConfig.server.native.includes(id)) { - // sharp needs to load the .node file on this thread for some reason - // maybe it's the case for other natives as well - // update: maybe it's fixed - // await import(id) - } - return result + onViteTransportMessage(data) { + return onMessageHandler(data) }, + + // These are used by Vike on the other side moduleGraphResolveUrl(url: string) { return vite.environments.ssr.moduleGraph.resolveUrl(url) }, @@ -184,7 +191,7 @@ function devServerPlugin(): Plugin { // This is the minimal representation the Vike runtime needs function convertToMinimalModuleNode( - node: EnvironmentModuleNode , + node: EnvironmentModuleNode, cache: Map = new Map() ): MinimalModuleNode { // If the node is in the cache, return the cached version @@ -210,3 +217,86 @@ function convertToMinimalModuleNode( return minimalNode } + +function createSimpleHMRChannel(options: { + name: string + post: (data: any) => any + on: (listener: (data: any) => void) => () => void + onRestartWorker: () => void +}): HMRChannel { + const listerMap = new DefaultMap>(() => new Set()) + let dispose: (() => void) | undefined + + return { + name: options.name, + listen() { + dispose = options.on((payload) => { + for (const f of listerMap.get(payload.event)) { + f(payload.data) + } + }) + }, + close() { + dispose?.() + dispose = undefined + }, + on(event: string, listener: (...args: any[]) => any) { + listerMap.get(event).add(listener) + }, + off(event: string, listener: (...args: any[]) => any) { + listerMap.get(event).delete(listener) + }, + send(...args: any[]) { + let payload: any + if (typeof args[0] === 'string') { + payload = { + type: 'custom', + event: args[0], + data: args[1] + } + } else { + payload = args[0] + } + + if (payload.triggeredBy && isImported(payload.triggeredBy)) { + options.onRestartWorker() + return + } + + options.post(payload) + } + } +} + +class DefaultMap extends Map { + constructor( + private defaultFn: (key: K) => V, + entries?: Iterable + ) { + super(entries) + } + + override get(key: K): V { + if (!this.has(key)) { + this.set(key, this.defaultFn(key)) + } + return super.get(key)! + } +} + +function isImported(id: string) { + const moduleNode = vite.environments.ssr.moduleGraph.getModuleById(id) + assert(moduleNode) + const modules = new Set([moduleNode]) + for (const module of modules) { + if (module.file === entryAbs) { + return true + } + + for (const importerInner of module.importers) { + modules.add(importerInner) + } + } + + return false +} diff --git a/packages/vike-node/src/plugin/plugins/devServer/types.ts b/packages/vike-node/src/plugin/plugins/devServer/types.ts index 5a4ee02..2403ada 100644 --- a/packages/vike-node/src/plugin/plugins/devServer/types.ts +++ b/packages/vike-node/src/plugin/plugins/devServer/types.ts @@ -12,8 +12,8 @@ type WorkerData = { type ClientFunctions = { start(workerData: WorkerData): void - deleteByModuleId(modulePath: string): boolean - invalidateDepTree(ids: string[]): void + onViteTransportMessage(data: any): void + onHmrReceive: (data: any) => void } type MinimalModuleNode = Pick & { @@ -21,8 +21,8 @@ type MinimalModuleNode = Pick & { } type ServerFunctions = { - fetchModule(id: string, importer?: string): Promise moduleGraphResolveUrl(url: string): Promise moduleGraphGetModuleById(id: string): MinimalModuleNode | undefined transformIndexHtml(url: string, html: string, originalUrl?: string): Promise + onViteTransportMessage(data: any): void } diff --git a/packages/vike-node/src/plugin/plugins/devServer/worker.ts b/packages/vike-node/src/plugin/plugins/devServer/worker.ts index 2adab2f..d2974d7 100644 --- a/packages/vike-node/src/plugin/plugins/devServer/worker.ts +++ b/packages/vike-node/src/plugin/plugins/devServer/worker.ts @@ -1,17 +1,22 @@ import { createBirpc } from 'birpc' -import { ESModulesEvaluator, ModuleRunner } from 'vite/module-runner' +import { ESModulesEvaluator, ModuleRunner, RemoteRunnerTransport } from 'vite/module-runner' import { setIsWorkerEnv } from '../../../runtime/env.js' import { logViteInfo } from '../../utils/logVite.js' import type { ClientFunctions, ServerFunctions, WorkerData } from './types.js' let runner: ModuleRunner -let entry_: string - +let hmrHandler: (data: any) => void +let viteTransportHandler: (data: any) => void const rpc = createBirpc( { + onHmrReceive(data) { + hmrHandler(data) + }, + onViteTransportMessage(data) { + viteTransportHandler(data) + }, async start(workerData: WorkerData) { const { entry, viteConfig } = workerData - entry_ = entry // This is the minimal required object for vike + telefunc to function const globalObject = { viteConfig, @@ -48,18 +53,31 @@ const rpc = createBirpc( runner = new ModuleRunner( { root: viteConfig.root, - transport: { fetchModule: rpc.fetchModule }, - hmr: false + transport: new RemoteRunnerTransport({ + send(data) { + rpc.onViteTransportMessage(data) + }, + onMessage(handler) { + viteTransportHandler = handler + } + }), + hmr: { + connection: { + onUpdate(callback) { + hmrHandler = callback + }, + isReady() { + return true + }, + send(messages) {} + } + } }, new ESModulesEvaluator() ) logViteInfo('Loading server entry') await runner.import(entry) - }, - async invalidateDepTree(mods) { - await runner.moduleCache.invalidateDepTree(mods) - }, - deleteByModuleId: (mod) => runner.moduleCache.deleteByModuleId(mod) + } }, { post: (data) => { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f2e0c0e..4ede049 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,6 +6,7 @@ settings: overrides: vike-node: link:./packages/vike-node/ + vite: 6.0.0-alpha.11 patchedDependencies: vike@0.4.161: @@ -51,7 +52,7 @@ importers: version: 18.2.22 '@vitejs/plugin-react': specifier: ^4.2.1 - version: 4.2.1(vite@6.0.0-alpha.0) + version: 4.2.1(vite@6.0.0-alpha.11) cross-env: specifier: ^7.0.3 version: 7.0.3 @@ -84,13 +85,13 @@ importers: version: 5.4.3 vike: specifier: 0.4.161 - version: 0.4.161(patch_hash=4x6h4gn45u3smxaalew7bffdpm)(vite@6.0.0-alpha.0) + version: 0.4.161(patch_hash=4x6h4gn45u3smxaalew7bffdpm)(vite@6.0.0-alpha.11) vike-node: specifier: link:../../packages/vike-node version: link:../../packages/vike-node vite: - specifier: 6.0.0-alpha.0 - version: 6.0.0-alpha.0(@types/node@20.11.30) + specifier: 6.0.0-alpha.11 + version: 6.0.0-alpha.11(@types/node@20.11.30) packages/vike-node: dependencies: @@ -127,10 +128,10 @@ importers: version: 5.4.3 vike: specifier: 0.4.161 - version: 0.4.161(patch_hash=4x6h4gn45u3smxaalew7bffdpm)(vite@6.0.0-alpha.0) + version: 0.4.161(patch_hash=4x6h4gn45u3smxaalew7bffdpm)(vite@6.0.0-alpha.11) vite: - specifier: 6.0.0-alpha.0 - version: 6.0.0-alpha.0(@types/node@20.11.30) + specifier: 6.0.0-alpha.11 + version: 6.0.0-alpha.11(@types/node@20.11.30) packages: @@ -1596,18 +1597,18 @@ packages: - supports-color dev: false - /@vitejs/plugin-react@4.2.1(vite@6.0.0-alpha.0): + /@vitejs/plugin-react@4.2.1(vite@6.0.0-alpha.11): resolution: {integrity: sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: - vite: ^4.2.0 || ^5.0.0 + vite: 6.0.0-alpha.11 dependencies: '@babel/core': 7.24.3 '@babel/plugin-transform-react-jsx-self': 7.24.1(@babel/core@7.24.3) '@babel/plugin-transform-react-jsx-source': 7.24.1(@babel/core@7.24.3) '@types/babel__core': 7.20.5 react-refresh: 0.14.0 - vite: 6.0.0-alpha.0(@types/node@20.11.30) + vite: 6.0.0-alpha.11(@types/node@20.11.30) transitivePeerDependencies: - supports-color dev: false @@ -3830,13 +3831,13 @@ packages: engines: {node: '>= 0.8'} dev: false - /vike@0.4.161(patch_hash=4x6h4gn45u3smxaalew7bffdpm)(vite@6.0.0-alpha.0): + /vike@0.4.161(patch_hash=4x6h4gn45u3smxaalew7bffdpm)(vite@6.0.0-alpha.11): resolution: {integrity: sha512-APiNZS9AuK9JpoJNvxXFxQ6arj3frJzx1kp+gzmXztq8QHa1Sbl5EDUqEGEz3waqO/Q4H0ebRx/W+/UwDk38iQ==} engines: {node: '>=16.0.0'} hasBin: true peerDependencies: react-streaming: '>=0.3.5' - vite: '>=3.1.0' + vite: 6.0.0-alpha.11 peerDependenciesMeta: react-streaming: optional: true @@ -3853,11 +3854,11 @@ packages: fast-glob: 3.3.2 sirv: 2.0.4 source-map-support: 0.5.21 - vite: 6.0.0-alpha.0(@types/node@20.11.30) + vite: 6.0.0-alpha.11(@types/node@20.11.30) patched: true - /vite@6.0.0-alpha.0(@types/node@20.11.30): - resolution: {integrity: sha512-NBYF7KOkASr2SRgknZD4hjSrpkJ9IpP5XMWBSidw66TTtKR5oplE/ONIRd8HKH07QwYVbKadXhP6/jQZfab9xA==} + /vite@6.0.0-alpha.11(@types/node@20.11.30): + resolution: {integrity: sha512-Pc0tgTWqdO4HzHpfnHxhVPj85gjrmoC+hEMLvI9vA8jTdSnjm4p6WUmvVfDYguBMCfnNXf1ThnxzS9GUwKxqpg==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: