Fix Vite 8 resolve.alias customResolver Removal

A code comparison showing resolve.alias customResolver, removed in Vite 8, replaced by a plugin using a resolveId hook with enforce: 'pre'
On this page

Why customResolver stopped working

Vite’s resolve.alias option has always supported two shapes: a plain string/RegExp find and replacement pair (still fully supported in Vite 8), and a version that supplies its own customResolver function to override how Vite resolved that specific aliased path. Vite’s migration guide lists the second form under “Deprecated Options,” removed outright: “resolve.alias[].customResolver: use a custom plugin with resolveId hook and enforce: 'pre' instead.”

Alias resolution is no longer an extension point in Vite 8. Any config or plugin that supplied a customResolver function silently stops taking effect. Vite doesn’t error on the unrecognized option, it just never calls it, so the alias quietly resolves to nothing or falls through to a different resolution path.

Astro’s own core hit this directly. Its tsconfig path-alias logic for CSS @import statements used customResolver internally. PR #17090, “Fix Vite and Rolldown build warnings in Astro 7”, merged 2026-06-18, replaced it with two separate plugins using resolveId/transform hooks instead, and shipped already-fixed in Astro 7.0.0 stable.

Fix it: replace customResolver with a resolveId plugin

Before: the removed pattern

vite.config.ts - Vite 7 pattern
export default defineConfig({
  resolve: {
    alias: [
      {
        find: /^~(.+)/,
        replacement: "$1",
        customResolver(source) {
          // BROKEN in Vite 8: customResolver is no longer called
          return resolveTsconfigPath(source);
        },
      },
    ],
  },
});

After: the same resolution logic, as a real plugin

vite.config.ts - Vite 8 pattern
export default defineConfig({
  plugins: [
    {
      name: "tsconfig-alias",
      enforce: "pre",
      resolveId(source) {
        // FIXED: resolveId + enforce: 'pre' replaces the removed
        // resolve.alias[].customResolver hook, running before
        // Vite's own default resolution
        if (source.startsWith("~")) {
          return resolveTsconfigPath(source.slice(1));
        }
        return null;
      },
    },
  ],
});

enforce: "pre" matters here. Without it, your plugin’s resolveId runs after Vite’s built-in resolvers, by which point the aliased path may have already resolved (or failed to resolve) the wrong way, the same ordering guarantee customResolver used to provide implicitly.

Confirmed version range

Verified against Astro’s own real fix: PR #17090 merged 2026-06-18, shipped in Astro 7.0.0 stable, replacing the exact customResolver pattern shown above with a resolveId-based plugin for the same tsconfig-path-alias logic. If you’re on Astro 7.0.0 or later, Astro’s own core already handles this. This fix applies to your own project’s Vite config or any third-party Vite plugin that still supplies a customResolver function. Browse more posts like this in the Guides & Fixes archive.

Frequently asked

Does this affect me if I don't use resolve.alias at all?

No. The plain string or RegExp form of resolve.alias (find and replacement, with no customResolver function) is unaffected and works the same in Vite 8. Only an alias entry that supplies its own customResolver function hits this removal.

Is this already fixed if I'm on Astro 7?

Yes, if you're on Astro 7.0.0 or later. Astro's own core used to rely on customResolver for its tsconfig path-alias-in-CSS-imports logic and already migrated to the resolveId-based pattern shown in this post, shipped in 7.0.0 stable. This post is for your own config or a third-party plugin still using the old hook.

Emitted as FAQPage JSON-LD from the same frontmatter — one source, no duplicated prose.

Recent posts

Full-text search via Pagefind · ↑↓ to navigate · ↵ to open