Search code examples
typescriptsveltevite

Svelte: Import by absolute path does not work


I'm trying to import enums, objects, functions, and svelte components by using absolute paths to files, but the compiler can't find them.

This is how i do the imports:

<script lang=ts>
    import { MyEnum } from "src/lib/enums";
    ... code ...
<script/>

The VS Code compiler does not complain about the path.

I get the following error message on the window when running the app:

[plugin:vite:import-analysis] Failed to resolve import "src/lib/enums" from "src\lib\GUI\ObjectOnBoard.svelte". Does the file exist?
35 |  
36 |  const { Object: Object_1 } = globals;
37 |  import { MyEnum } from "src/lib/enums";
   |                              ^

I have done some research, and i've found out that there might be some issues regarding my config files, but i don't know how to configure these files in order to make the referencing work. These are the config files (the ones i think are relevant?) in my project:

vite.config.ts:

import { defineConfig } from 'vite'
import { svelte } from '@sveltejs/vite-plugin-svelte'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [svelte()],
})

svelte.config.js:

import sveltePreprocess from 'svelte-preprocess'

export default {
  // Consult https://github.com/sveltejs/svelte-preprocess
  // for more information about preprocessors
  preprocess: sveltePreprocess(),
}

tsconfig.json:

{
  "extends": "@tsconfig/svelte/tsconfig.json",
  "compilerOptions": {
    "target": "esnext",
    "useDefineForClassFields": true,
    "module": "esnext",
    "resolveJsonModule": true,
    "baseUrl": ".",
    /**
     * Typecheck JS in `.svelte` and `.js` files by default.
     * Disable checkJs if you'd like to use dynamic types in JS.
     * Note that setting allowJs false does not prevent the use
     * of JS in `.svelte` files.
     */
    "allowJs": true,
    "checkJs": true,
    "isolatedModules": true,
  },
  "include": ["src/**/*.d.ts", "src/**/*.{svelte,ts,js}"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

The answer given below works for compiling the code, so now it actually runs which is awesome! But there are still some problem regarding VS Code autocompletion and error messages (red wiggly lines).

Specifying absolute paths works flawless inside of .svelte files, but in .ts files, typescript keeps alerting the error, eventhough the code compiles and works:

"Cannot find module 'src/lib/objects/outlet' or its corresponding type declarations."

This error statements appears within the file "src/lib/MainDataStructure".

I've tried "Restart TS Server", but it does not help. I've looked at this question which has alot of suggestions on how to solve this, but none works for me.

This is my current tsconfig.json file:

{
  "extends": "@tsconfig/svelte/tsconfig.json",
  "compilerOptions": {
    "moduleResolution": "node",
    "target": "esnext",
    "useDefineForClassFields": true,
    "module": "esnext",
    "resolveJsonModule": true,
    "allowSyntheticDefaultImports": true,
    /**
     * Typecheck JS in `.svelte` and `.js` files by default.
     * Disable checkJs if you'd like to use dynamic types in JS.
     * Note that setting allowJs false does not prevent the use
     * of JS in `.svelte` files.
     */
    "allowJs": true,
    "checkJs": true,
    "isolatedModules": true,
    "baseUrl": ".",
    "paths": {
      "src/*": [
        "src/*"
      ],
    }
  },
  "include": ["src/**/*.d.ts", "src/**/*.{svelte,ts,js}"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

This is an image of my directory in the project:

enter image description here


Solution

  • Under Node module resolution (set by tsconfig/svelte) those are not absolute file paths. They will be interpreted as relative to a Node module, in this case src.

    If you want to refer to a local file, you might have to define a path alias first via the tsconfig.json:

    {
        "compilerOptions": {
            "paths": {
                "src/*": [
                    "src/*"
                ],
            },
            // ...
    }
    

    (If your baseUrl is '.', then the src folder has to be at the same level as the configuration.)

    When using Vite, you may also have to make its build system aware of the path mapping, there exists e.g. the package vite-tsconfig-paths which provides a plugin for that.

    If you do not want the extra dependency or this does not work, you can specify the alias yourself in the vite.config.js:

    // ...
    import path from 'path';
    
    export default defineConfig({
        // ...
        resolve: {
            alias: {
                src: path.resolve('src/'),
            },
        }
    });
    

    The Vite config step is important for the build to work, the tsconfig may be necessary to make editor tooling work (e.g. code completion and navigation in VS Code).


    Note: SvelteKit has its own configuration for adding additional aliases.