跳到內容

Vite Runtime API

底層 API

此 API 在 Vite 5.1 中作為實驗性功能推出。它被加入以 收集回饋。可能會發生重大變更,因此在使用時務必將 Vite 版本固定為 ~5.1.0。這是專為函式庫和框架作者設計的底層 API。如果您的目標是建立應用程式,請務必先查看 Awesome Vite SSR 中的高階 SSR 外掛程式和工具。

目前,此 API 正在作為 環境 API 進行修改,並在 ^6.0.0-alpha.0 中發布。

「Vite Runtime」是一個工具,允許透過先使用 Vite 外掛程式處理任何程式碼來執行該程式碼。它不同於 server.ssrLoadModule,因為執行時間實作與伺服器分離。這允許函式庫和框架作者實作伺服器和執行時間之間自己的通訊層。

此功能的目標之一是提供一個可自訂的 API 來處理和執行程式碼。Vite 提供了足夠的工具來開箱即用 Vite Runtime,但如果使用者的需求與 Vite 的內建實作不符,他們可以進一步建構。

除非另有說明,否則所有 API 都可以從 vite/runtime 匯入。

ViteRuntime

類型簽章

ts
export class ViteRuntime {
  constructor(
    public options: ViteRuntimeOptions,
    public runner: ViteModuleRunner,
    private debug?: ViteRuntimeDebugger,
  ) {}
  /**
   * URL to execute. Accepts file path, server path, or id relative to the root.
   */
  public async executeUrl<T = any>(url: string): Promise<T>
  /**
   * Entry point URL to execute. Accepts file path, server path or id relative to the root.
   * In the case of a full reload triggered by HMR, this is the module that will be reloaded.
   * If this method is called multiple times, all entry points will be reloaded one at a time.
   */
  public async executeEntrypoint<T = any>(url: string): Promise<T>
  /**
   * Clear all caches including HMR listeners.
   */
  public clearCache(): void
  /**
   * Clears all caches, removes all HMR listeners, and resets source map support.
   * This method doesn't stop the HMR connection.
   */
  public async destroy(): Promise<void>
  /**
   * Returns `true` if the runtime has been destroyed by calling `destroy()` method.
   */
  public isDestroyed(): boolean
}

進階用法

如果您只是從 server.ssrLoadModule 進行遷移,並想要支援 HMR,請考慮改用 createViteRuntime

初始化 ViteRuntime 類別時需要 rootfetchModule 選項。Vite 在 server 實例上公開 ssrFetchModule,以更輕鬆地與 Vite SSR 整合。Vite 也從其主要進入點匯出 fetchModule - 與 ssrFetchModule 不同,它不會對程式碼的執行方式做出任何假設,後者預期程式碼會使用 new Function 執行。這可以在這些函式傳回的原始碼對應中看到。

ViteRuntime 中的執行器負責執行程式碼。Vite 開箱即用地匯出 ESModulesRunner,它使用 new AsyncFunction 來執行程式碼。如果您使用的 JavaScript 執行時間不支援不安全的評估,您可以提供自己的實作。

執行時間公開的兩個主要方法是 executeUrlexecuteEntrypoint。它們之間唯一的差別是,如果 HMR 觸發 full-reload 事件,那麼由 executeEntrypoint 執行的所有模組都將重新執行。請注意,當發生這種情況時,Vite Runtime 不會更新 exports 物件(它會覆寫它),如果你依賴於擁有最新的 exports 物件,則需要再次執行 executeUrl 或從 moduleCache 取得模組。

範例用法

js
import { ViteRuntime, ESModulesRunner } from 'vite/runtime'
import { root, fetchModule } from './rpc-implementation.js'

const runtime = new ViteRuntime(
  {
    root,
    fetchModule,
    // you can also provide hmr.connection to support HMR
  },
  new ESModulesRunner(),
)

await runtime.executeEntrypoint('/src/entry-point.js')

ViteRuntimeOptions

ts
export interface ViteRuntimeOptions {
  /**
   * Root of the project
   */
  root: string
  /**
   * A method to get the information about the module.
   * For SSR, Vite exposes `server.ssrFetchModule` function that you can use here.
   * For other runtime use cases, Vite also exposes `fetchModule` from its main entry point.
   */
  fetchModule: FetchFunction
  /**
   * Configure how source maps are resolved. Prefers `node` if `process.setSourceMapsEnabled` is available.
   * Otherwise it will use `prepareStackTrace` by default which overrides `Error.prepareStackTrace` method.
   * You can provide an object to configure how file contents and source maps are resolved for files that were not processed by Vite.
   */
  sourcemapInterceptor?:
    | false
    | 'node'
    | 'prepareStackTrace'
    | InterceptorOptions
  /**
   * Disable HMR or configure HMR options.
   */
  hmr?:
    | false
    | {
        /**
         * Configure how HMR communicates between the client and the server.
         */
        connection: HMRRuntimeConnection
        /**
         * Configure HMR logger.
         */
        logger?: false | HMRLogger
      }
  /**
   * Custom module cache. If not provided, it creates a separate module cache for each ViteRuntime instance.
   */
  moduleCache?: ModuleCacheMap
}

ViteModuleRunner

類型簽章

ts
export interface ViteModuleRunner {
  /**
   * Run code that was transformed by Vite.
   * @param context Function context
   * @param code Transformed code
   * @param id ID that was used to fetch the module
   */
  runViteModule(
    context: ViteRuntimeModuleContext,
    code: string,
    id: string,
  ): Promise<any>
  /**
   * Run externalized module.
   * @param file File URL to the external module
   */
  runExternalModule(file: string): Promise<any>
}

Vite 匯出預設實作此介面的 ESModulesRunner。它使用 new AsyncFunction 來執行程式碼,因此如果程式碼已內嵌來源程式碼對應,它應包含 2 行偏移量 以容納新增的新行。這是由 server.ssrFetchModule 自動完成的。如果你的執行器實作沒有此限制,你應直接使用從 vite 匯出的 fetchModule

HMRRuntimeConnection

類型簽章

ts
export interface HMRRuntimeConnection {
  /**
   * Checked before sending messages to the client.
   */
  isReady(): boolean
  /**
   * Send message to the client.
   */
  send(message: string): void
  /**
   * Configure how HMR is handled when this connection triggers an update.
   * This method expects that connection will start listening for HMR updates and call this callback when it's received.
   */
  onUpdate(callback: (payload: HMRPayload) => void): void
}

此介面定義如何建立 HMR 通訊。Vite 從主要進入點匯出 ServerHMRConnector 以支援 Vite SSR 期間的 HMR。通常在觸發自訂事件(例如,import.meta.hot.send("my-event"))時會呼叫 isReadysend 方法。

僅在初始化新的執行時間時會呼叫 onUpdate。它傳遞一個方法,該方法應在連線觸發 HMR 事件時呼叫。實作取決於連線類型(例如,它可以是 WebSocket/EventEmitter/MessageChannel),但通常看起來像這樣

js
function onUpdate(callback) {
  this.connection.on('hmr', (event) => callback(event.data))
}

會排隊處理回呼,它會等到目前更新已解決後才會處理下一個更新。與瀏覽器實作不同,Vite Runtime 中的 HMR 更新會等到所有監聽器(例如,vite:beforeUpdate/vite:beforeFullReload)都完成後才會更新模組。

createViteRuntime

類型簽章

ts
async function createViteRuntime(
  server: ViteDevServer,
  options?: MainThreadRuntimeOptions,
): Promise<ViteRuntime>

範例用法

js
import { createServer } from 'vite'

const __dirname = fileURLToPath(new URL('.', import.meta.url))

;(async () => {
  const server = await createServer({
    root: __dirname,
  })
  await server.listen()

  const runtime = await createViteRuntime(server)
  await runtime.executeEntrypoint('/src/entry-point.js')
})()

此方法可輕鬆取代 server.ssrLoadModule。與 ssrLoadModule 不同,createViteRuntime 提供開箱即用的 HMR 支援。你可以傳遞 options 來自訂 SSR 執行時間的行為以符合你的需求。

MainThreadRuntimeOptions

ts
export interface MainThreadRuntimeOptions
  extends Omit<ViteRuntimeOptions, 'root' | 'fetchModule' | 'hmr'> {
  /**
   * Disable HMR or configure HMR logger.
   */
  hmr?:
    | false
    | {
        logger?: false | HMRLogger
      }
  /**
   * Provide a custom module runner. This controls how the code is executed.
   */
  runner?: ViteModuleRunner
}