diff --git a/.github/workflows/test-nuxt3.yml b/.github/workflows/test-nuxt3.yml index 6f4536bf..29665f89 100644 --- a/.github/workflows/test-nuxt3.yml +++ b/.github/workflows/test-nuxt3.yml @@ -38,7 +38,7 @@ jobs: echo "::set-output name=pnpm_cache_dir::$(pnpm store path)" - name: Cache pnpm modules - uses: actions/cache@v4 + uses: actions/cache@v2 with: path: | ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} diff --git a/.github/workflows/test-svelte4.yml b/.github/workflows/test-svelte4.yml index 6b4cdb70..50a72eb1 100644 --- a/.github/workflows/test-svelte4.yml +++ b/.github/workflows/test-svelte4.yml @@ -38,7 +38,7 @@ jobs: echo "::set-output name=pnpm_cache_dir::$(pnpm store path)" - name: Cache pnpm modules - uses: actions/cache@v4 + uses: actions/cache@v2 with: path: | ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} diff --git a/.github/workflows/test-vue3.yml b/.github/workflows/test-vue3.yml index 8e0e7b95..68442521 100644 --- a/.github/workflows/test-vue3.yml +++ b/.github/workflows/test-vue3.yml @@ -38,7 +38,7 @@ jobs: # echo "::set-output name=pnpm_cache_dir::$(pnpm store path)" # - name: Cache pnpm modules - # uses: actions/cache@v4 + # uses: actions/cache@v2 # with: # path: | # ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} @@ -94,7 +94,7 @@ jobs: echo "::set-output name=pnpm_cache_dir::$(pnpm store path)" - name: Cache pnpm modules - uses: actions/cache@v4 + uses: actions/cache@v2 with: path: | ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a846a8af..540d09b3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -34,7 +34,7 @@ jobs: echo "::set-output name=pnpm_cache_dir::$(pnpm store path)" - name: Cache pnpm modules - uses: actions/cache@v4 + uses: actions/cache@v2 with: path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} key: pnpm-v1-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} diff --git a/packages/histoire/package.json b/packages/histoire/package.json index 2fb04d31..b0df2df3 100644 --- a/packages/histoire/package.json +++ b/packages/histoire/package.json @@ -75,7 +75,8 @@ "picocolors": "^1.1.1", "sade": "^1.8.1", "shiki-es": "^0.14.0", - "sirv": "^3.0.0" + "sirv": "^3.0.0", + "vite-node": "3.0.0-beta.1" }, "devDependencies": { "@types/fs-extra": "^11.0.4", diff --git a/packages/histoire/src/node/build.ts b/packages/histoire/src/node/build.ts index 855d6648..8419188c 100644 --- a/packages/histoire/src/node/build.ts +++ b/packages/histoire/src/node/build.ts @@ -50,15 +50,10 @@ export async function build(ctx: Context) { } const { viteConfig } = await getViteConfigWithPlugins(true, ctx) - const server = await createViteServer({ - ...mergeViteConfig(viteConfig, { + const server = await createViteServer( + mergeViteConfig(viteConfig, { optimizeDeps: { include: [], noDiscovery: true }, }), - environments: { - worker: { - }, - }, - }, ) await server.pluginContainer.buildStart({}) diff --git a/packages/histoire/src/node/collect/index.ts b/packages/histoire/src/node/collect/index.ts index 58503096..b475f736 100644 --- a/packages/histoire/src/node/collect/index.ts +++ b/packages/histoire/src/node/collect/index.ts @@ -1,5 +1,6 @@ import type { ServerStoryFile } from '@histoire/shared' import type { ViteDevServer } from 'vite' +import type { FetchFunction, ResolveIdFunction } from 'vite-node' import type { Context } from '../context.js' import type { Payload, ReturnData } from './worker.js' import { cpus } from 'node:os' @@ -8,6 +9,7 @@ import Tinypool from '@akryum/tinypool' import { createBirpc } from 'birpc' import { relative } from 'pathe' import pc from 'picocolors' +import { ViteNodeServer } from 'vite-node/server' import { createPath } from '../tree.js' import { slash } from '../util/fs.js' @@ -20,6 +22,24 @@ export interface UseCollectStoriesOptions { export function useCollectStories(options: UseCollectStoriesOptions, ctx: Context) { const { server, mainServer } = options + const node = new ViteNodeServer(server, { + deps: { + inline: [ + /histoire\/dist/, + /histoire\/client/, + /@histoire\/[\w-]+\/dist/, + /histoire-[\w-]+\/dist/, + /@vue\/devtools-api/, + /vuetify/, + // @TODO temporary fix for https://github.com/histoire-dev/histoire/issues/409 + /vite\w*\/dist\/client\/(client|env).mjs/, + ...ctx.config.viteNodeInlineDeps ?? [], + ], + fallbackCJS: true, + }, + transformMode: ctx.config.viteNodeTransformMode, + }) + const maxThreads = ctx.config.collectMaxThreads ?? cpus().length const threadsCount = ctx.mode === 'dev' @@ -37,6 +57,7 @@ export function useCollectStories(options: UseCollectStoriesOptions, ctx: Contex function clearCache() { server.moduleGraph.invalidateAll() + node.fetchCache.clear() } function createChannel() { @@ -45,17 +66,15 @@ export function useCollectStories(options: UseCollectStoriesOptions, ctx: Contex const workerPort = channel.port1 createBirpc, { - invoke: (payload: any) => Promise + fetchModule: FetchFunction + resolveId: ResolveIdFunction }>({ - invoke: async (payload) => { - if (payload.type === 'custom' && payload.data.name === 'fetchModule') { - return await server.environments.worker.fetchModule(payload.data.data[0]) - } - }, - }, { - post: data => port.postMessage(data), - on: data => port.on('message', data), - }) + fetchModule: id => node.fetchModule(id), + resolveId: (id, importer) => node.resolveId(id, importer), + }, { + post: data => port.postMessage(data), + on: data => port.on('message', data), + }) return { port, diff --git a/packages/histoire/src/node/collect/worker.ts b/packages/histoire/src/node/collect/worker.ts index 0dd8fbd6..e50f01d3 100644 --- a/packages/histoire/src/node/collect/worker.ts +++ b/packages/histoire/src/node/collect/worker.ts @@ -1,13 +1,13 @@ import type { ServerRunPayload, ServerStory, ServerStoryFile } from '@histoire/shared' import type { MessagePort } from 'node:worker_threads' +import type { FetchFunction, ResolveIdFunction } from 'vite-node' import { performance } from 'node:perf_hooks' import { fileURLToPath } from 'node:url' import { parentPort } from 'node:worker_threads' import { createBirpc } from 'birpc' import { dirname, resolve } from 'pathe' import pc from 'picocolors' -import { ModuleCacheMap } from 'vite-node/client' -import { ESModulesEvaluator, ModuleRunner } from 'vite/module-runner' +import { ModuleCacheMap, ViteNodeRunner } from 'vite-node/client' import { createDomEnv } from '../dom/env.js' const __dirname = dirname(fileURLToPath(import.meta.url)) @@ -24,15 +24,16 @@ export interface ReturnData { } const _moduleCache = new ModuleCacheMap() -let _runner: ModuleRunner +let _runner: ViteNodeRunner let _rpc: ReturnType Promise + fetchModule: FetchFunction + resolveId: ResolveIdFunction }>> // Cleanup module cache parentPort.on('message', (message) => { if (message?.kind === 'hst:invalidate') { - _moduleCache.delete(message.file) // TODO: Do we need that with the new module runner? + _moduleCache.delete(message.file) } }) @@ -41,22 +42,24 @@ export default async (payload: Payload): Promise => { process.env.HST_COLLECT = 'true' _rpc = createBirpc<{ - invoke: (payload: any) => Promise + fetchModule: FetchFunction + resolveId: ResolveIdFunction }>({}, { - post: data => payload.port.postMessage(data), - on: data => payload.port.on('message', data), - }) + post: data => payload.port.postMessage(data), + on: data => payload.port.on('message', data), + }) - const runner = _runner ?? (_runner = new ModuleRunner({ + const runner = _runner ?? (_runner = new ViteNodeRunner({ root: payload.root, - sourcemapInterceptor: false, - transport: { - invoke: async (payload) => { - return { result: await _rpc.invoke(payload) } - }, + base: payload.base, + moduleCache: _moduleCache, + fetchModule(id) { + return _rpc.fetchModule(id) + }, + resolveId(id, importer) { + return _rpc.resolveId(id, importer) }, - hmr: false, - }, new ESModulesEvaluator())) + })) const { destroy: destroyDomEnv } = createDomEnv() @@ -64,7 +67,7 @@ export default async (payload: Payload): Promise => { const beforeExecuteTime = performance.now() // Mount app to collect stories/variants - const { run } = (await runner.import(resolve(__dirname, './run.js'))) as { run: (payload: ServerRunPayload) => Promise } + const { run } = (await runner.executeFile(resolve(__dirname, './run.js'))) as { run: (payload: ServerRunPayload) => Promise } const afterExecuteTime = performance.now() const storyData: ServerStory[] = [] await run({ diff --git a/packages/histoire/src/node/virtual/vite-plugin.ts b/packages/histoire/src/node/virtual/vite-plugin.ts index 49abd94c..38e8a1aa 100644 --- a/packages/histoire/src/node/virtual/vite-plugin.ts +++ b/packages/histoire/src/node/virtual/vite-plugin.ts @@ -10,10 +10,6 @@ export function createVirtualFilesPlugin(ctx: Context, isServer: boolean) { name: 'histoire-virtual-files', async resolveId(id, importer) { - if (id.startsWith('/@id/__x00__')) { - id = id.slice(12) - } - if (id.startsWith(VirtualFiles.STORIES_ID)) { return VirtualFiles.RESOLVED_STORIES_ID }