Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

alias '@' to path.resolve(__dirname, './src') is not working #279

Closed
hronro opened this issue May 27, 2020 · 49 comments
Closed

alias '@' to path.resolve(__dirname, './src') is not working #279

hronro opened this issue May 27, 2020 · 49 comments

Comments

@hronro
Copy link
Contributor

hronro commented May 27, 2020

Describe the bug

Alias { '@': path.resolve(__dirname, './src') } is not working.

Reproduction

project structure:

vite.config.js
src
├── app.js
├── index.js

vite.config.js:

const path = require('path');

module.exports = {
  alias: {
    '@': path.resolve(__dirname, './src'),
  }
};

src/index.js

import { Foo } from '@/app';

Got error in vite:

[vite] Failed to resolve module import "@/app"

System Info

  • required vite version: 0.17.0
  • required Operating System: Linux
  • required Node version: 14.3.0
@remyz17
Copy link

remyz17 commented May 27, 2020

Vite alias don't work like webpack does.
You need to use resolvers to do what you want to do.

@hronro
Copy link
Contributor Author

hronro commented May 27, 2020

@remyz17
I tried this code, but it doesn't work either:

const path = require('path');
const srcPath = path.resolve(__dirname, './src');

module.exports = {
  resolvers: [{
    alias (id) {
      if (id.startsWith('@/')) {
        return path.join(srcPath, id.slice(2));
      }
    }
  }],
};

@remyz17
Copy link

remyz17 commented May 27, 2020

I guess you need to implement this 2 functions.
requestToFile and fileToRequest

Take a look at this code
https://github.com/vuejs/vitepress/blob/master/src/node/resolver.ts#L19

@remyz17
Copy link

remyz17 commented May 27, 2020

i tried to do it and it's not fully working.
For exemple it don't work inside vue template: <img src="/@/..." />

module.exports = {
  outDir: '../app/static',
  resolvers: [{
    requestToFile: publicPath => {
      if (publicPath.match(/^\/@\//)) {
        return path.join(srcPath, publicPath.replace(/^\/@\//, ''))
      }
    },
    fileToRequest: filePath => {
      if (filePath.startsWith('/src')) {
        return `/@/${path.relative(srcPath, filePath)}`
      }
    }
  }]
}

I noticed that we can not use @/ because it’s recognised as a node module so I used /@/

@hronro
Copy link
Contributor Author

hronro commented May 27, 2020

@remyz17
This not works for me. In my case, the function fileToRequest is not even be called, and I'm still figuring out why.

@remyz17
Copy link

remyz17 commented May 27, 2020

@remyz17

This not works for me. In my case, the function fileToRequest is not even be called, and I'm still figuring out why.

Send your vite config so i can take a look

@hronro
Copy link
Contributor Author

hronro commented May 27, 2020

@remyz17
OK, here is my config:

// vite.config.ts
import * as path from 'path';

import * as reactPlugin from 'vite-plugin-react';

import type { UserConfig } from 'vite';

const srcPath = path.resolve(__dirname, './src');

const config: UserConfig = {
  jsx: 'react',
  alias: {
    'exenv': 'exenv-esm',
    'prop-types': 'es-react/prop-types.js',
  },
  resolvers: [{
    fileToRequest (filePath) {
      console.log('@@@', filePath);
      if (filePath.startsWith(srcPath)) {
        return `/@/${path.relative(srcPath, filePath)}`;
      }
    },
    requestToFile (publicPath) {
      if (publicPath.startsWith('/@/')) {
        return path.join(srcPath, publicPath.replace(/^\/@\//, ''));
      }
    },
  }],
  root: './src',
  plugins: [reactPlugin],
};

export default config;

@yyx990803
Copy link
Member

I think we probably will eventually provide an easier way to alias src directories. If your resolver is not working, it's better to provide a full reproduction instead of a single config file.

@hronro
Copy link
Contributor Author

hronro commented May 28, 2020

@yyx990803
Copy link
Member

btw you don't need an alias like that... you can just do /main.js because that's the server root.

@hronro
Copy link
Contributor Author

hronro commented May 28, 2020

@yyx990803
that should work, but I personally don't like to do that, because a path starts with / make me thought it's a file under the / folder of my file system.
And could you review my code of the resolver, am I doing something wrong or it's a bug of vite?

@yyx990803
Copy link
Member

It's a bug. It's fixed in 801951e but it also adds an easier way to alias a directory so you can just do

// vite.config.js
module.exports = {
  alias: {
    '/@/': path.resolve(__dirname, './src')
  }
}

@hronro
Copy link
Contributor Author

hronro commented May 29, 2020

@yyx990803
Still doesn't work for after I upgrade vite to v0.18.0.
https://codesandbox.io/s/vite-src-alias-demo2-lzpm0

@yyx990803
Copy link
Member

yyx990803 commented May 29, 2020

You have to import as /@/xxx, it cannot start with @ because that's considered a package.

Note Vite is not a bundler - it's a dev server. Any request not starting with / or . is considered a module dependency request. All other requests must be valid HTTP requests (start with / or .).

This also means you can NOT directly import from fs paths like in webpack:

import foo from '/some/fs/path/foo.js'

This doesn't make sense in Vite. So anything starting with / is a request from the root where the server is serving.

@delaneyj
Copy link

Heads up I was porting an app and /@/xxx aliasing working for all code but the assets did not work.

@mgagna
Copy link

mgagna commented Jan 17, 2021

Hi, has this been solved?
I'm using Vite 2.0.0-beta.30 and it's not working.

I'm using Vue v3.
I have a template with
<img :src="urlLogo" />

and
computed: { urlLogo() { return this.collapsed ? '@/assets/logoSmall.png' : '/@/assets/logo.png'; } }
And I keep getting
GET http://localhost:3000/@/assets/logo.png 404 (Not Found)

I've tried the alias in the vite.config.js, added the resolvers, nothing works.
I've tried using:

  • /@/assets/logo.png
  • @/assets/logo.png
  • /@assets/logo.png
  • @assets/logo.png
  • ~/assets/logo.png

The only path that works is './src/assets/logo.png', but when I build for production I don't have the /src folder.
Any suggestion?

@jsmith
Copy link

jsmith commented Jan 17, 2021

The Asset Handling section of the vite documentation is probably what you're looking for. Your logic is flawed (I think) since vite doesn't get the chance to transform /@/assets/logoSmall.png or /@/assets/logo.png. I haven't used vite in a few months but I think something like this might work:

import logo from '/@/assets/logo.png'
import logoSmall from '/@/assets/logoSmall.png'

// ...
computed: { urlLogo() { return this.collapsed ? smallLogo : logo; } }
// ...

This solution assumes that you have the alias correctly configured. Make sure to read through Alias Behavior Change.

@mgagna
Copy link

mgagna commented Jan 18, 2021

Thanks @jsmith,

Your solution worked well and I learnt something new.

Thanks

@AlexeyZelenko
Copy link

AlexeyZelenko commented Feb 4, 2021

import vue from '@vitejs/plugin-vue'

export default {
  alias: {
    '/@': path.resolve(__dirname, './src')
  },
  plugins: [vue()]
}

does not work

@theovier
Copy link

theovier commented Feb 4, 2021

import vue from '@vitejs/plugin-vue'

export default {
  alias: {
    '/@': path.resolve(__dirname, './src')
  },
  plugins: [vue()]
}

does not work

I think you are just missing the const path = require('path'); part. Make sure to also add the leading "/" when importing components in the Vue script section, i.e.: import Container from "/@/views/Container.vue";

Edit: I also used path.resolve(__dirname, 'src') instead of path.resolve(__dirname, './src') but that should not matter.

Edit2: You could also use the find and replace option to alias the @, i.e.:

const path = require('path');
import vue from '@vitejs/plugin-vue'

export default {
    alias: [
        {find: "@", replacement: path.resolve(__dirname, 'src')}
    ],
    optimizeDeps: {
        include: [
            "javascript-time-ago/locale/de"
        ],
    },
    plugins: [vue()]
};

then again you don't need the leading slash when importing.

Edit 3: Since vite 2.0.1 introduces the resolve syntax, use:

const path = require('path');
import vue from '@vitejs/plugin-vue'

export default {
    resolve: {
        alias: [
            {find: "@", replacement: path.resolve(__dirname, 'src')}
        ],
        optimizeDeps: {
            include: [
                "javascript-time-ago/locale/de"
            ],
        },
    },
    plugins: [vue()]
};

@AlexeyZelenko
Copy link

Thanks @theovier

@qiushiyan
Copy link

qiushiyan commented Feb 21, 2021

With the resolve.alias config in 2.0.1, you can use @/ directy instead of /@/

@ndom91
Copy link

ndom91 commented Feb 21, 2021

Having trouble with aliases here after upgrading to 2.0.1.

vite.config.ts

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

export default defineConfig({
  resolve: {
    alias: [
      {
        find: '@/',
        replacement: path.resolve(__dirname, './src')
      }
    ]
  },
  optimizeDeps: {
    include: ['lodash']
  }
})

And then it errors in places such as:

import Nav from '@/components/Nav.vue', component: () => import('@/views/About.vue')

The error message says the plugin "vite:dep-scan" didn't set a resolve directory, but I can't find anything related to vite:dep-scan anywhere on the internet.. 🤔

I've tried the various @rollup/plugin-alias config options syntax from (here) as well as with and without the defineConfig() wrapper - all no luck and generating the same error message.

@qiushiyan
Copy link

@ndom91 Does it work when you delete the / from find: '@/'?

@ndom91
Copy link

ndom91 commented Feb 21, 2021

@Enixam yes that did the trick!

@qiushiyan
Copy link

@ndom91 Standard settings without the extensions key works for me though, and vite-aliases seems another option.

@yxw007
Copy link

yxw007 commented Mar 13, 2021

@ndom91 Does it work when you delete the / from find: '@/'?

2.0.5 is not work

@yxw007
Copy link

yxw007 commented Mar 13, 2021

source config
image

image
I use vite v2.0.5, change to this run is ok

@patak-dev
Copy link
Member

@aa4790139 @ginzatron, please do not comment on closed issues.
You can start a GitHub Discussion or join the chat at Vite Land to ask questions.

@gustawdaniel
Copy link

@patak-js I think that there should be comments because of developers that have problem with migration of vite landing on this page. I wold be great if there will be published solution of this problem or direct link to other place with solution.

@patak-dev
Copy link
Member

It makes sense to post a comment with a clear solution for others to find, that is not a problem 👍🏼

But asking questions against a closed bug report is not helpful because the context refers to an older version of Vite, and it doesn't allow proper tracking of concrete bugs in newer versions. Issues are not intended to be used for discussions, we have better platforms for that with GitHub Discussion and Vite Land. If a good solution to something that is not clear in this issue is identified there, it is a good idea to link it from here for later reference.

@jinan5694
Copy link

// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  // 路径代理
  resolve: {
    alias: [
      { find: '@', replacement: '/src' },
      { find: 'views', replacement: '/src/views' },
      { find: 'components', replacement: '/src/components' },
    ]
  }
})

@csulit
Copy link

csulit commented Apr 14, 2021

@ndom91 Does it work when you delete the / from find: '@/'?

It's working but TS flag this as an error.

image

@yxw007
Copy link

yxw007 commented Apr 15, 2021

It's working but TS flag this as an error.
import AppLayout from '/@/components/AppLayout.vue'
Try to change it to this

@paynezhuang
Copy link

It's working but TS flag this as an error.
import AppLayout from '/@/components/AppLayout.vue'
Try to change it to this

resolve: { alias: [{ // /@/xxxx => src/xxx find: /^\/@/, replacement: path.resolve(__dirname, './src') }] },

import HelloWorld from '/@/components/HelloWorld.vue'

Cannot find module '/@/components/HelloWorld.vue' or its corresponding type declarations.

Use // @ts-ignore

@csulit
Copy link

csulit commented Apr 15, 2021

It's working but TS flag this as an error.
import AppLayout from '/@/components/AppLayout.vue'
Try to change it to this

TS is still flags the import. I don't know if this is the right way to do it, I already solve the issue by declaring this to tsconfig.json

    "baseUrl": "./src",
    "paths": {
      "@components/*": ["./components/*"]
    },

@nzhtrtlc
Copy link

Can't we just define a resolver that resolves src folder so we don't have to use aliases ?
import Button from components/Button;

MyViteProject > src > components > Button

how can resolve src folder in vite.config.js ?

@csulit
Copy link

csulit commented Apr 15, 2021

It's working but TS flag this as an error.
import AppLayout from '/@/components/AppLayout.vue'
Try to change it to this

resolve: { alias: [{ // /@/xxxx => src/xxx find: /^\/@/, replacement: path.resolve(__dirname, './src') }] },

import HelloWorld from '/@/components/HelloWorld.vue'

Cannot find module '/@/components/HelloWorld.vue' or its corresponding type declarations.

Use // @ts-ignore

I solve it by declaring this to tsconfig.json

    "baseUrl": "./src",
    "paths": {
      "@components/*": ["./components/*"]
    },

The error is gone and did not break any component in build.

image

@slumtrimpet
Copy link

slumtrimpet commented Apr 20, 2021

For what it's worth, adding the following to tsconfig.json makes typescript happy:

    "baseUrl": "./src",
    "paths": {
      "@components/*": ["./components/*"]
    },

BUT you still need to also add corresponding:

  resolve: {
    alias: [
      { find: '@components', replacement: '/src/components' },
    ]
  }

to vite.config.js to make vite happy. Maybe that's obvious to most, but it wasn't to me. ;-)

@jgermade
Copy link

jgermade commented Apr 24, 2021

Still no working for me with reactRefresh when npm run dev

It works when npm run build and in any case when using a --template vue (@vitejs/plugin-vue)

This is my vite.config.js:

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [reactRefresh()],
  resolve: {
    alias: [
      { find: /^@(?=\/)/, replacement: path.resolve(__dirname, './src') }
    ],
  },
})

@csulit
Copy link

csulit commented Apr 24, 2021

Still no working for me with reactRefresh when npm run dev

It works when npm run build and in any case when using a --template vue (@vitejs/plugin-vue)

This is my vite.config.js:

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [reactRefresh()],
  resolve: {
    alias: [
      { find: /^@(?=\/)/, replacement: path.resolve(__dirname, './src') }
    ],
  },
})

Mine is working fine with this config.

{
  "compilerOptions": {
    "target": "ESNext",
    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    "types": ["vite/client"],
    "baseUrl": "./src",
    "paths": {
      "@interfaces/*": ["./interfaces/*"],
      "@components/*": ["./components/*"],
      "@pages/*": ["./pages/*"],
      "@contexts/*": ["./contexts/*"],
      "@services/*": ["./services/*"],
      "@utilities/*": ["./utilities/*"]
    },
    "allowJs": false,
    "skipLibCheck": false,
    "esModuleInterop": false,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react"
  },
  "include": ["./src"]
}
import reactRefresh from '@vitejs/plugin-react-refresh';
import fs from 'fs';
import lessToJs from 'less-vars-to-js';
import path from 'path';
import { defineConfig } from 'vite';
import vitePluginImp from 'vite-plugin-imp';

const themeVariables = lessToJs(
  fs.readFileSync(
    path.resolve(__dirname, './src/styles/variables.less'),
    'utf8'
  )
);

export default defineConfig({
  plugins: [
    reactRefresh(),
    vitePluginImp({
      libList: [
        {
          libName: 'antd',
          style: (name) => `antd/es/${name}/style/index`,
        },
      ],
    }),
  ],
  css: {
    preprocessorOptions: {
      less: {
        javascriptEnabled: true,
        modifyVars: themeVariables,
      },
    },
  },
  resolve: {
    alias: [
      {
        find: '@',
        replacement: path.resolve(__dirname, './src'),
      },
      {
        find: '@interfaces',
        replacement: path.resolve(__dirname, './src/interfaces'),
      },
      {
        find: '@components',
        replacement: path.resolve(__dirname, './src/components'),
      },
      {
        find: '@pages',
        replacement: path.resolve(__dirname, './src/pages'),
      },
      {
        find: '@contexts',
        replacement: path.resolve(__dirname, './src/contexts'),
      },
      {
        find: '@services',
        replacement: path.resolve(__dirname, './src/services'),
      },
      {
        find: '@utilities',
        replacement: path.resolve(__dirname, './src/utilities'),
      },
    ],
  },
});

@jgermade
Copy link

Thanks @csulit for your reply!

Reviewing my code I've figured out that my scenario is a bit different... I mean:

I've tested that using the alias works like a charm when index.html is on the root of the project, but does not work when moving index.html into src (using vite serve src)

image

Also noticed that when moving the index.html into src folder, I can import files from root (p.e. import App from '/App') which is great. The bad point is that IntelliSense is not useful...

Using this jsconfig.json:

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

Gets folloging sugestions:

Captura de pantalla de 2021-04-26 13-42-56

But when using root slash:

Captura de pantalla de 2021-04-26 13-44-39

Any ideas how to use this alias moving index.html into src folder?

vite.config.js

export default defineConfig({
  plugins: [reactRefresh()],
  resolve: {
    alias: [
      { find: /^@(?=\/)/, replacement: path.resolve(__dirname, './src') },
    ],
  },
})

@SarcevicAntonio
Copy link

SarcevicAntonio commented May 2, 2021

For what it's worth, adding the following to tsconfig.json makes typescript happy:

    "baseUrl": "./src",
    "paths": {
      "@components/*": ["./components/*"]
    },

BUT you still need to also add corresponding:

  resolve: {
    alias: [
      { find: '@components', replacement: '/src/components' },
    ]
  }

to vite.config.js to make vite happy. Maybe that's obvious to most, but it wasn't to me. ;-)

This worked for me! Using vite with Svelte and Typescript and this setup works perfectly with VSCode importing my files automatically.

Thanks a bunch slumtrimpet

@ddzy
Copy link

ddzy commented May 11, 2021

// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  // 路径代理
  resolve: {
    alias: [
      { find: '@', replacement: '/src' },
      { find: 'views', replacement: '/src/views' },
      { find: 'components', replacement: '/src/components' },
    ]
  }
})

Working for me

@marialovesbeans
Copy link

marialovesbeans commented May 17, 2021

Is there a way of specifying src as root import path? ex: in create-react-app you can set a baseUrl, so instead of writing

import User from '~/src/components/User';

You can write:

import User from 'components/User';

This looks much cleaner. How to achieve the same in Vite?

@marxangels
Copy link

idea.config.js

System.config({
  paths: {
    '@/*': './src/*',
  }
})

@npearson72
Copy link

The following is working for me:

...
  resolve: {
    alias: {
      '@pages': path.resolve(__dirname, './src/pages')
    }
  },
...

@zhuchangfeng
Copy link

vite 1 verson
alias: { '@pages': path.resolve(__dirname, './src/pages') }
vite 2 verson
resolve:{ alias: [ { find: '@', replacement: resolve('src') , },] },
crucial step
yarn add @vitejs/plugin-vue
yarn upgrade vite@2.3.8

vite.config.js

import vue from '@vitejs/plugin-vue'
import { defineConfig } from 'vite'
export default defineConfig({
resolve:{
alias: [ {
find: '@',
replacement: resolve('src') ,
}]
}
})

@github-actions
Copy link

This issue has been locked since it has been closed for more than 14 days.

If you have found a concrete bug or regression related to it, please open a new bug report with a reproduction against the latest Vite version. If you have any other comments you should join the chat at Vite Land or create a new discussion.

@github-actions github-actions bot locked and limited conversation to collaborators Jul 14, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests