376 words • 2 minute(s) to read

Using path aliases within Astro config

Posted on

When you use Astro and try to refer to another file with path aliases like @/lib/plugins/rehype-class-names, you may encounter something like this:

$ astro dev
12:11:52 PM [vite] (ssr) Error when evaluating SSR module /data/Dev/omni/astro.config.ts:
|- Error: Cannot find module '@/lib/plugins/rehype-class-names' imported from '/data/Dev/omni/astro.config.ts'
    at fetchModule (file:///data/Dev/omni/node_modules/vite/dist/node/chunks/dep-M1IYMR16.js:51641:19)
    at RunnableDevEnvironment.fetchModule (file:///data/Dev/omni/node_modules/vite/dist/node/chunks/dep-M1IYMR16.js:52735:12)
    at fetchModule (file:///data/Dev/omni/node_modules/vite/dist/node/chunks/dep-M1IYMR16.js:52693:21)
    at handleInvoke (file:///data/Dev/omni/node_modules/vite/dist/node/chunks/dep-M1IYMR16.js:44342:28)
    at EventEmitter.listenerForInvokeHandler (file:///data/Dev/omni/node_modules/vite/dist/node/chunks/dep-M1IYMR16.js:44415:25)
    at EventEmitter.emit (node:events:513:28)
    at Object.send (file:///data/Dev/omni/node_modules/vite/dist/node/chunks/dep-M1IYMR16.js:30733:40)
    at Object.invoke (file:///data/Dev/omni/node_modules/vite/dist/node/module-runner.js:610:34)
    at Object.invoke (file:///data/Dev/omni/node_modules/vite/dist/node/module-runner.js:671:34)
    at SSRCompatModuleRunner.getModuleInformation (file:///data/Dev/omni/node_modules/vite/dist/node/module-runner.js:1192:94)
 
[astro] Unable to load your Astro config
 
Cannot find module '@/lib/plugins/rehype-class-names' imported from '/data/Dev/omni/astro.config.ts'
  Location:
    /data/Dev/omni/node_modules/vite/dist/node/chunks/dep-M1IYMR16.js:51641:19
  Stack trace:
    at fetchModule (file:///data/Dev/omni/node_modules/vite/dist/node/chunks/dep-M1IYMR16.js:51641:19)
    at fetchModule (file:///data/Dev/omni/node_modules/vite/dist/node/chunks/dep-M1IYMR16.js:52693:21)
    at EventEmitter.listenerForInvokeHandler (file:///data/Dev/omni/node_modules/vite/dist/node/chunks/dep-M1IYMR16.js:44415:25)
    at Object.send (file:///data/Dev/omni/node_modules/vite/dist/node/chunks/dep-M1IYMR16.js:30733:40)
    at Object.invoke (file:///data/Dev/omni/node_modules/vite/dist/node/module-runner.js:671:34)
error: script "dev" exited with code 1

This is a known bug and won’t be fixed. So we’ll need to patch it ourselves. This procedure is pretty simple and imma show you step-by-step in this article.

Install patch-package

bun add -D patch-package

Depending on which package manager you use, replace bun with your own choice. Also, remember to set up postinstall hook for patch-package.

Patch astro

  • Open node_modules/astro/dist/core/config/vite-load.js with your editor
  • Add these two imports at the beginning of the file
import configAliasPlugin from '../../vite-plugin-config-alias/index.js';
import { loadTSConfig } from './tsconfig.js';
  • Load the config inside createViteServer
const {tsconfigFile: tsConfigPath, tsconfig: tsConfig} = await loadTSConfig(root);
  • Add configAliasPlugin to plugins array
-    plugins: [loadFallbackPlugin({ fs, root: pathToFileURL(root) })]
+    plugins: [configAliasPlugin({ settings: { tsConfig, tsConfigPath } }), loadFallbackPlugin({ fs, root: pathToFileURL(root) })]

Make the change persistent

bun patch-package astro

It will create a file named patches/astro+<version>, add that file to your Git repository, and you are good to go. Now re-run astro dev and enjoy the convenience of using path aliases.


DiffFull .patch file in case you wonder
--- a/node_modules/astro/dist/core/config/vite-load.js
+++ b/node_modules/astro/dist/core/config/vite-load.js
@@ -2,7 +2,10 @@ import { pathToFileURL } from "node:url";
 import { createServer } from "vite";
 import loadFallbackPlugin from "../../vite-plugin-load-fallback/index.js";
 import { debug } from "../logger/core.js";
+import configAliasPlugin from '../../vite-plugin-config-alias/index.js';
+import { loadTSConfig } from './tsconfig.js';
 async function createViteServer(root, fs) {
+  const {tsconfigFile: tsConfigPath, tsconfig: tsConfig} = await loadTSConfig(root);
   const viteServer = await createServer({
     configFile: false,
     server: { middlewareMode: true, hmr: false, watch: null, ws: false },
@@ -10,7 +13,7 @@ async function createViteServer(root, fs) {
     clearScreen: false,
     appType: "custom",
     ssr: { external: true },
-    plugins: [loadFallbackPlugin({ fs, root: pathToFileURL(root) })]
+    plugins: [configAliasPlugin({ settings: { tsConfig, tsConfigPath } }), loadFallbackPlugin({ fs, root: pathToFileURL(root) })]
   });
   return viteServer;
 }