14

I use Vue 3 on Vite.js with Eslint + Airbnb config. Airbnb config has a rule eslint(import/no-unresolved), which is good, but Eslint doesn't know how to resolve alias path.

I want to use aliases for paths — example: import TableComponent from '@/components/table/TableComponent.vue'˙

Environment is in plain JavaScript.

I managed to set up my vite.config.js so that the app can resolve paths like this:

import path from 'path';
import { defineConfig } from 'vite';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: [{
        find: "@", replacement: path.resolve(__dirname, 'src')
      },],
  },
});

Vue app works like that and resolves the import path correctly, but Eslint keeps reporting the error: Unable to resolve path to module eslint(import/no-unresolved)

How and where can I tell Eslint how to resolve aliases?

I have tried: install eslint-plugin-import eslint-import-resolver-alias --save-dev

// .eslintrc.js

// ...
extends: [
    'eslint:recommended',
    'plugin:import/recommended',
    'airbnb-base',
    'plugin:vue/vue3-strongly-recommended',
],

settings: {
    'import/resolver': {
      alias: {
        map: [
          ['@', 'src'],
        ],
      },
    },
  },

But that doesn't work.


EDIT:
Solved the issue, see the accepted answer if you're using plain JavaScript like I do.

If you're using TypeScript, see if Seyd's answer can help you.

Riza Khan
  • 2,712
  • 4
  • 18
  • 42
Delicious Bacon
  • 435
  • 1
  • 4
  • 12

7 Answers7

16

this solves the issue in my TypeScript project.

npm install eslint-import-resolver-typescript

After eslint-import-resolver-typescript installation

{
  // other configuration are omitted for brevity
  settings: {
    "import/resolver": {
      typescript: {} // this loads <rootdir>/tsconfig.json to eslint
    },
  },
}

should be added to .eslintrc.js.

my tsconfig.json (remove unwanted settings)

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "strict": false,
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "lib": ["esnext", "dom"],
    "types": ["vite/client", "node"],
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    },
    "allowJs": true
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  "exclude": ["node_modules"]
}

Check the discussion here:

Syed
  • 15,657
  • 13
  • 120
  • 154
3

In case someone runs into this problem, this works in my case*:

settings: {
    'import/resolver': {
      alias: {
        map: [
          ['@', './src'],
        ],
      },
    },
  },

*In my case, Vue's root is 'src' directory, while Eslint's is one level higher, so it needs the './src' path.

Huge thanks to @https://github.com/aladdin-add for the answer through the github question!

Delicious Bacon
  • 435
  • 1
  • 4
  • 12
  • This didn't work for me, I have no idea what I'm doing wrong – JCraine Nov 07 '22 at 08:22
  • @JCraine check your project's folder structure. I've put a note (asterisk, *) on that issue. It could also be your OS reading path differently, but it's beyond my knowledge if that could affect it. If you're looking for TypeScript solution, check Syed's answer. – Delicious Bacon Nov 08 '22 at 13:31
3

I can't for the life of me get this to work, I've tried everything above. Is there something else wrong with my file?

// .eslintrc.cjs
/* eslint-env node */
require("@rushstack/eslint-patch/modern-module-resolution");

module.exports = {
  root: true,
  extends: [
    "airbnb",
    "plugin:vue/vue3-essential",
    "eslint:recommended",
    "@vue/eslint-config-prettier",
  ],
  parserOptions: {
    ecmaVersion: "latest",
  },

  // Using the accepted answer
  settings: {
    "import/resolver": {
      alias: {
        map: [["@", "./src"]],
      },
    },
  },
};

** UPDATE **

The only way I was able to get this to work was using this: eslint-config-airbnb link here, the readme was particularly helpful.

npm add --dev @vue/eslint-config-airbnb @rushstack/eslint-patch

My .eslintrc.js is now:

/* eslint-env node */
require("@rushstack/eslint-patch/modern-module-resolution");

const path = require("node:path");
const createAliasSetting = require("@vue/eslint-config-airbnb/createAliasSetting");

module.exports = {
  root: true,
  extends: [
    "plugin:vue/vue3-essential",
    "@vue/eslint-config-airbnb", // <-- added
    "eslint:recommended",
    "@vue/eslint-config-prettier",
  ],
  parserOptions: {
    ecmaVersion: "latest",
  },

  rules: {
    "import/no-unresolved": "error",
  },
  settings: {
    ...createAliasSetting({
      "@": `${path.resolve(__dirname, "./src")}`,
    }),
  },
};

Huzzah!

JCraine
  • 1,159
  • 2
  • 20
  • 38
1

I had the same problem, and even I fixed the src path it still hat the issue. It did not work until I added extensions:

  "settings": {
    "import/resolver": {
      "alias": {
        "map": [
          ["@", "./src"]
        ],

        "extensions": [".js",".jsx"] <--- HERE
      }
    }
  },
bukso
  • 1,108
  • 12
  • 23
1

1. Use & export aliases in vite.config.js

// vite.config.js

import { resolve } from 'path';

import { defineConfig } from 'vite';

export const aliases = {
    '@': resolve(__dirname, './src'),
    '@u': resolve(__dirname, './src/utils'),
};

export default () => defineConfig({
  // ...
  resolve: {
      alias: aliases,
  },
})

2. Create .eslintrc with ES Modules support. (Thanks to Morgan's answer)

2.1 npm i esm -D

2.2 Create sibling to .eslintrc.js.eslintrc.esm.js.

2.3 Put your your ESLint config into .eslintrc.esm.js.

// .eslintrc.esm.js

export default {
  root: true,
  extends: ['@vue/airbnb', 'plugin:vue/recommended'],
  // ...
}

2.4 Inside .eslintrc.js include this code:

const _require = require('esm')(module)
module.exports = _require('./.eslintrc.esm.js').default

3. Import, map & use aliases from vite.config.js in .eslintrc.esm.js

3.1 npm i eslint-import-resolver-alias -D

3.2 Inside .eslintrc.esm.js include following code:

// .eslintrc.esm.js

import { aliases } from './vite.config';

const mappedAliases = Object.entries(aliases).map((entry) => entry); // [[alias, path], [alias, path], ...]

export default {
  // ...
  settings: {
      'import/resolver': {
          alias: {
              map: mappedAliases,
          },
      },
  },
}
Georgiy Bukharov
  • 356
  • 3
  • 10
1

In the README.md of eslint-plugin-import it is said:

Currently Node and webpack resolution have been implemented, but the resolvers are just npm packages, so third party packages are supported (and encouraged!).

Here you can see the list of the third party resolvers.

One that worked for me was this: eslint-import-resolver-custom-alias, and this is how I used it:

settings:
  import/resolver:
    eslint-import-resolver-custom-alias:
      alias:
        '@': './app/javascript'
      extensions:
        - '.js'
        - '.vue'

For me the @ had been set as an alias for app/javascript inside vite.config.ts, you should change this based on your project configurations.

Ershad Qaderi
  • 441
  • 4
  • 11
0

in .eslintrc.js add

settings: {
'import/resolver': {
  alias: {
    map: [['@', './src/']],
    extensions: ['.js', '.vue'],
  },
},

},

pabloRN
  • 866
  • 10
  • 19