diff --git a/packages/vite/src/node/plugins/optimizedDeps.ts b/packages/vite/src/node/plugins/optimizedDeps.ts index cdde20891b836b..6d6a8d22eb9468 100644 --- a/packages/vite/src/node/plugins/optimizedDeps.ts +++ b/packages/vite/src/node/plugins/optimizedDeps.ts @@ -10,6 +10,8 @@ import { cleanUrl } from '../../shared/utils' export const ERR_OPTIMIZE_DEPS_PROCESSING_ERROR = 'ERR_OPTIMIZE_DEPS_PROCESSING_ERROR' export const ERR_OUTDATED_OPTIMIZED_DEP = 'ERR_OUTDATED_OPTIMIZED_DEP' +export const ERR_FILE_NOT_FOUND_IN_OPTIMIZED_DEP_DIR = + 'ERR_FILE_NOT_FOUND_IN_OPTIMIZED_DEP_DIR' const debug = createDebugger('vite:optimize-deps') @@ -68,8 +70,12 @@ export function optimizedDepsPlugin(config: ResolvedConfig): Plugin { try { return await fsp.readFile(file, 'utf-8') } catch (e) { - // Outdated non-entry points (CHUNK), loaded after a rerun - throwOutdatedRequest(id) + const newMetadata = depsOptimizer.metadata + if (optimizedDepInfoFromFile(newMetadata, file)) { + // Outdated non-entry points (CHUNK), loaded after a rerun + throwOutdatedRequest(id) + } + throwFileNotFoundInOptimizedDep(id) } } }, @@ -97,3 +103,15 @@ export function throwOutdatedRequest(id: string): never { // send a 504 status code request timeout throw err } + +export function throwFileNotFoundInOptimizedDep(id: string): never { + const err: any = new Error( + `The file does not exist at "${id}" which is in the optimize deps directory. ` + + `The dependency might be incompatible with the dep optimizer. ` + + `Try adding it to \`optimizeDeps.exclude\`.`, + ) + err.code = ERR_FILE_NOT_FOUND_IN_OPTIMIZED_DEP_DIR + // This error will be caught by the transform middleware that will + // send a 404 status code not found + throw err +} diff --git a/packages/vite/src/node/server/middlewares/transform.ts b/packages/vite/src/node/server/middlewares/transform.ts index a0239aab7fcb4e..12a440d4c10774 100644 --- a/packages/vite/src/node/server/middlewares/transform.ts +++ b/packages/vite/src/node/server/middlewares/transform.ts @@ -27,6 +27,7 @@ import { isDirectRequest, } from '../../plugins/css' import { + ERR_FILE_NOT_FOUND_IN_OPTIMIZED_DEP_DIR, ERR_OPTIMIZE_DEPS_PROCESSING_ERROR, ERR_OUTDATED_OPTIMIZED_DEP, } from '../../plugins/optimizedDeps' @@ -253,6 +254,15 @@ export function transformMiddleware( // error but a normal part of the missing deps discovery flow return } + if (e?.code === ERR_FILE_NOT_FOUND_IN_OPTIMIZED_DEP_DIR) { + // Skip if response has already been sent + if (!res.writableEnded) { + res.statusCode = 404 + res.end() + } + server.config.logger.warn(colors.yellow(e.message)) + return + } if (e?.code === ERR_LOAD_URL) { // Let other middleware handle if we can't load the url via transformRequest return next() diff --git a/playground/optimize-deps/__tests__/optimize-deps.spec.ts b/playground/optimize-deps/__tests__/optimize-deps.spec.ts index f2ad3680cdac47..b07e5f8fe59a2a 100644 --- a/playground/optimize-deps/__tests__/optimize-deps.spec.ts +++ b/playground/optimize-deps/__tests__/optimize-deps.spec.ts @@ -319,3 +319,11 @@ test('long file name should work', async () => { `hello world`, ) }) + +test.runIf(isServe)('warn on incompatible dependency', () => { + expect(serverLogs).toContainEqual( + expect.stringContaining( + 'The dependency might be incompatible with the dep optimizer.', + ), + ) +}) diff --git a/playground/optimize-deps/dep-incompatible/index.js b/playground/optimize-deps/dep-incompatible/index.js new file mode 100644 index 00000000000000..6d67368a1d4df7 --- /dev/null +++ b/playground/optimize-deps/dep-incompatible/index.js @@ -0,0 +1,3 @@ +const subUrl = new URL('./sub.js', import.meta.url) + +export default () => import(subUrl) diff --git a/playground/optimize-deps/dep-incompatible/package.json b/playground/optimize-deps/dep-incompatible/package.json new file mode 100644 index 00000000000000..1d67c51eb4cbcc --- /dev/null +++ b/playground/optimize-deps/dep-incompatible/package.json @@ -0,0 +1,7 @@ +{ + "name": "@vitejs/test-dep-incompatible", + "private": true, + "version": "0.0.0", + "type": "module", + "main": "index.js" +} diff --git a/playground/optimize-deps/dep-incompatible/sub.js b/playground/optimize-deps/dep-incompatible/sub.js new file mode 100644 index 00000000000000..26f9a8a9430bf8 --- /dev/null +++ b/playground/optimize-deps/dep-incompatible/sub.js @@ -0,0 +1 @@ +export default 'sub' diff --git a/playground/optimize-deps/index.html b/playground/optimize-deps/index.html index 3839a4aa9951d0..9b992b7dd4892a 100644 --- a/playground/optimize-deps/index.html +++ b/playground/optimize-deps/index.html @@ -263,3 +263,8 @@

Long file name import works

text('.clonedeep-slash', cloneDeepSlash({ name: 'clonedeep-slash' }).name) text('.clonedeep-dot', cloneDeepDot({ name: 'clonedeep-dot' }).name) + + diff --git a/playground/optimize-deps/package.json b/playground/optimize-deps/package.json index a1cf32ebc73a22..99be592eb4972f 100644 --- a/playground/optimize-deps/package.json +++ b/playground/optimize-deps/package.json @@ -20,6 +20,7 @@ "@vitejs/test-dep-cjs-with-assets": "file:./dep-cjs-with-assets", "@vitejs/test-dep-css-require": "file:./dep-css-require", "@vitejs/test-dep-esbuild-plugin-transform": "file:./dep-esbuild-plugin-transform", + "@vitejs/test-dep-incompatible": "file:./dep-incompatible", "@vitejs/test-dep-linked": "link:./dep-linked", "@vitejs/test-dep-linked-include": "link:./dep-linked-include", "@vitejs/test-dep-node-env": "file:./dep-node-env", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 03b925b3a34c11..929c39d3b8ce48 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -906,6 +906,9 @@ importers: '@vitejs/test-dep-esbuild-plugin-transform': specifier: file:./dep-esbuild-plugin-transform version: file:playground/optimize-deps/dep-esbuild-plugin-transform + '@vitejs/test-dep-incompatible': + specifier: file:./dep-incompatible + version: file:playground/optimize-deps/dep-incompatible '@vitejs/test-dep-linked': specifier: link:./dep-linked version: link:dep-linked @@ -1019,6 +1022,8 @@ importers: playground/optimize-deps/dep-esbuild-plugin-transform: {} + playground/optimize-deps/dep-incompatible: {} + playground/optimize-deps/dep-linked: dependencies: lodash-es: @@ -9901,6 +9906,11 @@ packages: name: '@vitejs/test-dep-esbuild-plugin-transform' dev: false + file:playground/optimize-deps/dep-incompatible: + resolution: {directory: playground/optimize-deps/dep-incompatible, type: directory} + name: '@vitejs/test-dep-incompatible' + dev: false + file:playground/optimize-deps/dep-node-env: resolution: {directory: playground/optimize-deps/dep-node-env, type: directory} name: '@vitejs/test-dep-node-env'