From e91a10f91653ebb9e37f6f98a5d34e08afa25ac1 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Fri, 9 Feb 2024 10:06:03 +0900 Subject: [PATCH] refactor(vite-node-miniflare): use `ssr.optimizeDeps` for vite-node (#152) --- .../examples/react-router/vite.config.ts | 9 ++---- .../examples/react/README.md | 8 +---- .../examples/react/vite.config.ts | 14 +++++---- .../examples/remix/vite.config.ts | 18 +++++------- .../vite-node-miniflare/src/server/plugin.ts | 29 +++++++++++++------ .../src/server/pre-bundle/utils.ts | 2 ++ 6 files changed, 42 insertions(+), 38 deletions(-) diff --git a/packages/vite-node-miniflare/examples/react-router/vite.config.ts b/packages/vite-node-miniflare/examples/react-router/vite.config.ts index 795b5daa1..065f9b29a 100644 --- a/packages/vite-node-miniflare/examples/react-router/vite.config.ts +++ b/packages/vite-node-miniflare/examples/react-router/vite.config.ts @@ -6,9 +6,10 @@ import { defineConfig } from "vite"; export default defineConfig({ clearScreen: false, - appType: "custom", ssr: { - noExternal: true, + optimizeDeps: { + include: ["react", "react/jsx-dev-runtime", "react-dom/server"], + }, }, plugins: [ globRoutesPlugin({ root: "/src/routes" }), @@ -18,10 +19,6 @@ export default defineConfig({ miniflareOptions(options) { options.log = new Log(); }, - preBundle: { - include: ["react", "react/jsx-dev-runtime", "react-dom/server"], - force: true, - }, }), react(), ], diff --git a/packages/vite-node-miniflare/examples/react/README.md b/packages/vite-node-miniflare/examples/react/README.md index 839260a3d..9e7786129 100644 --- a/packages/vite-node-miniflare/examples/react/README.md +++ b/packages/vite-node-miniflare/examples/react/README.md @@ -1,9 +1,3 @@ React port of [demo](../demo) -Since React provides only CJS, it doesn't seem to work out-of-the-box on Vite + Vite-Node on Workerd with `ssr.optimizeDeps` etc... - -To workaround this, I created `vitePluginPreBundle` to pre-bundle known CJS dependencies into ESM and then setup custom `resolveId` to swap out CJS version into ESM version. - -```sh -pnpm dev-react -``` +Since React provides only CJS, it requires `ssr.optimizeDeps` with Vite >= 5.1. diff --git a/packages/vite-node-miniflare/examples/react/vite.config.ts b/packages/vite-node-miniflare/examples/react/vite.config.ts index 065078419..64fd8c7e4 100644 --- a/packages/vite-node-miniflare/examples/react/vite.config.ts +++ b/packages/vite-node-miniflare/examples/react/vite.config.ts @@ -5,9 +5,15 @@ import { defineConfig } from "vite"; export default defineConfig({ clearScreen: false, - appType: "custom", + optimizeDeps: { + // for debugging + // DEBUG=vite:deps pnpm -C examples/react dev + // force: true, + }, ssr: { - noExternal: true, + optimizeDeps: { + include: ["react", "react/jsx-dev-runtime", "react-dom/server"], + }, }, plugins: [ vitePluginViteNodeMiniflare({ @@ -16,10 +22,6 @@ export default defineConfig({ miniflareOptions(options) { options.log = new Log(); }, - preBundle: { - include: ["react", "react/jsx-dev-runtime", "react-dom/server"], - force: true, - }, }), react(), ], diff --git a/packages/vite-node-miniflare/examples/remix/vite.config.ts b/packages/vite-node-miniflare/examples/remix/vite.config.ts index f5be9f69b..92df6e014 100644 --- a/packages/vite-node-miniflare/examples/remix/vite.config.ts +++ b/packages/vite-node-miniflare/examples/remix/vite.config.ts @@ -5,9 +5,15 @@ import { defineConfig } from "vite"; export default defineConfig({ clearScreen: false, - appType: "custom", ssr: { - noExternal: true, + optimizeDeps: { + include: [ + "react", + "react/jsx-dev-runtime", + "react-dom", + "react-dom/server.browser", + ], + }, }, plugins: [ vitePluginViteNodeMiniflare({ @@ -19,14 +25,6 @@ export default defineConfig({ options.kvNamespaces = { kv: "0".repeat(32) }; options.kvPersist = ".wrangler/state/v3/kv"; }, - preBundle: { - include: [ - "react", - "react/jsx-dev-runtime", - "react-dom", - "react-dom/server.browser", - ], - }, customRpc: { // DevServerHook is implemented via custom rpc // https://github.com/remix-run/remix/blob/db4471d2e32a175abdcb907b877f9a510c735d8b/packages/remix-server-runtime/dev.ts#L37-L48 diff --git a/packages/vite-node-miniflare/src/server/plugin.ts b/packages/vite-node-miniflare/src/server/plugin.ts index 25dc3e418..36cf3b173 100644 --- a/packages/vite-node-miniflare/src/server/plugin.ts +++ b/packages/vite-node-miniflare/src/server/plugin.ts @@ -1,6 +1,5 @@ import * as httipAdapterNode from "@hattip/adapter-node/native-fetch"; import * as httipCompose from "@hattip/compose"; -import { typedBoolean } from "@hiogawa/utils"; import { Miniflare, type MiniflareOptions, @@ -9,7 +8,6 @@ import { import type { Plugin } from "vite"; import type { ViteNodeRunnerOptions, ViteNodeServerOptions } from "vite-node"; import { ViteNodeServer } from "vite-node/server"; -import { vitePluginPreBundle } from ".."; import { name as packageName } from "../../package.json"; import { setupViteNodeServerRpc } from "./vite-node"; @@ -25,14 +23,25 @@ export function vitePluginViteNodeMiniflare(pluginOptions: { force?: boolean; }; customRpc?: Record; -}): Plugin[] { +}): Plugin { // initialize miniflare lazily on first request and // dispose on server close (e.g. server restart on user vite config change) let miniflare: Miniflare | undefined; - const middlewarePlugin: Plugin = { + return { name: packageName, apply: "serve", + config(_config, _env) { + return { + appType: "custom", + ssr: { + // force "webworker" since Vite injects "require" banner if `target: "node"` + // https://github.com/vitejs/vite/blob/a3008671de5b44ced2952f796219c0c4576125ac/packages/vite/src/node/optimizer/index.ts#L824-L830 + target: "webworker", + noExternal: true, + }, + }; + }, async configureServer(server) { // setup vite-node with rpc const viteNodeServerOptions: ViteNodeServerOptions = { @@ -44,6 +53,13 @@ export function vitePluginViteNodeMiniflare(pluginOptions: { transformMode: { ssr: [/.*/], }, + deps: { + // vite-node tries to externalize pre-bundled deps by default. + // by putting non-existing cacheDir, we disable this heuristics. + // https://github.com/vitest-dev/vitest/blob/043b78f3257b266302cdd68849a76b8ed343bba1/packages/vite-node/src/externalize.ts#L104-L106 + cacheDir: "__disable_externalizing_vite_deps", + moduleDirectories: [], + }, }; pluginOptions.viteNodeServerOptions?.(viteNodeServerOptions); const viteNodeServer = new ViteNodeServer(server, viteNodeServerOptions); @@ -102,9 +118,4 @@ export function vitePluginViteNodeMiniflare(pluginOptions: { } }, }; - - return [ - middlewarePlugin, - pluginOptions.preBundle && vitePluginPreBundle(pluginOptions.preBundle), - ].filter(typedBoolean); } diff --git a/packages/vite-node-miniflare/src/server/pre-bundle/utils.ts b/packages/vite-node-miniflare/src/server/pre-bundle/utils.ts index 03039ce28..3a54fedf3 100644 --- a/packages/vite-node-miniflare/src/server/pre-bundle/utils.ts +++ b/packages/vite-node-miniflare/src/server/pre-bundle/utils.ts @@ -3,6 +3,8 @@ import fs from "node:fs"; import path from "node:path"; import { createManualPromise, wrapError } from "@hiogawa/utils"; +// TODO: this is not necessary since https://github.com/hi-ogawa/vite-plugins/pull/152 + // quick-and-dirty CJS pre-bundling // since `ssr.optimizeDeps` doesn't seem to work when running vite-node client on workered