ChatGPT解决这个技术问题 Extra ChatGPT

What does the @ mean inside an import path?

I'm starting out a new vue.js project so I used the vue-cli tool to scaffold out a new webpack project (i.e. vue init webpack).

As I was walking through the generated files I noticed the following imports in the src/router/index.js file:

import Vue from 'vue'
import Router from 'vue-router'
import Hello from '@/components/Hello' // <- this one is what my qusestion is about

Vue.use(Router)

export default new Router({
    routes: [
        {
            path: '/',
            name: 'Hello',
            component: Hello
        }
    ]
})

I've not seen the at sign (@) in a path before. I suspect it allows for relative paths (maybe?) but I wanted to be sure I understand what it truly does.

I tried searching around online but wasn't able to find an explanation (prob because searching for "at sign" or using the literal character @ doesn't help as search criteria).

What does the @ do in this path (link to documentation would be fantastic) and is this an es6 thing? A webpack thing? A vue-loader thing?

UPDATE

Thanks Felix Kling for pointing me to another duplicate stackoverflow question/answer about this same question.

While the comment on the other stackoverflow post isn't the exact answer to this question (it wasn't a babel plugin in my case) it did point me in the correct direction to find what it was.

In in the scaffolding that vue-cli cranks out for you, part of the base webpack config sets up an alias for .vue files:

https://i.stack.imgur.com/Nz1TS.png

This makes sense both in the fact that it gives you a relative path from the src file and it removes the requirement of the .vue at the end of the import path (which you normally need).

Thanks for the help!

@FelixKling It is not an exact duplicate because it doesn't answer the whole question, is this an es6 thing? A webpack thing? A vue-loader thing?
Yeah, I think the question was similar but not a duplicate. Regardless I figured out where it was coming from and updated the question with an explanation since I can't add it as an answer.
@estus: the answer makes it pretty clear that it isn't part of ES6 but a webpack configuration thing, don't you think? And that's exactly the case here as well, only that the nature of the configuration is a bit different.
@FelixKling It depends. But since the question you've linked doesn't have detailed answer that explains what's up with Webpack, it may probably deserve an answer. Usually having 'Possible duplicate of ...' comment is enough to designate the link between the questions, and vox populi does the rest. I've seen the questions being over-duped on SO too often.

E
Estus Flask

This is done with Webpack resolve.alias configuration option and isn't specific to Vue.

In Vue Webpack template, Webpack is configured to replace @/ with src path:

  const path = require('path');

  ...
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      ...
      '@': path.resolve('src'),
    }
  },
  ...

The alias is used as:

import '@/<path inside src folder>';

JavaScript just isn't JavaScript anymore. Babel/webpack gives us this Frankenstein language and somehow new developers are meant to know where ECMAScript spec ends and userland plugins/transforms begin. It's really sad, imo.
@naomik It's up to user to introduce such tricks into the setup or not. It's not a big deal for Vue since it relies on its custom .vue file format anyway.
Personally I think the ability to add flexibility if you want it is a good thing. I see it less as frankenstein and more like voltron; you can do stuff as a lion or combine different lions together to have a bigger robot. Yeah, sometimes you get questions like this one, but it's not like the answers can't be found. Really, you can take the frankenstein or voltron view with any project of any size, it's just "using and understanding dependencies".
@ChrisSchmitz It depends on the context and the perspective. Doing something like this will restrict the project to use Webpack. May be not a good thing if the project intends to use native ES6 modules when they will arrive, or it's Node where CommonJS can be used for modules. Long relative paths can be harder to maintain and refactor, on the other hand.
When using vue-cli v3+ you should use ~@ to reference src folder. E.g.: $font-path: '~@/assets/fonts/';
T
Tyler Canton

Also keep in mind you can create variables in tsconfig as well:

"paths": {
  "@components": ["src/components"],
  "@scss": ["src/styles/scss"],
  "@img": ["src/assests/images"],
  "@": ["src"],
}

This can be utilized for naming convention purposes:

import { componentHeader } from '@components/header';

But this kind of alias will be left bare in the source JS and then at run-time you'll need to have a wrapper intercede to make the alias work. Maybe there's a way via babel for this TS syntax to get converted at build time? With Typescript's tsc is does not and therefore you'll need something like module-alias or tsconfig-paths.
after I add this settings, vs code can not reslove path and cannot go into the file when click the impored module.
L
Luân Trương

I get over with following combination

import HelloWorld from '@/components/HelloWorld'
=>
import HelloWorld from 'src/components/HelloWorld'

IDE will stop warning the uri, but this causes invalid uri when compile, in "build\webpack.base.conf.js"

resolve: { extensions: ['.js', '.vue', '.json'], alias: { 'src': resolve('src'), } },

Bingoo!


M
Marcelo Assis

resolve('src') no works for me but path.resolve('src') works

resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': path.resolve('src')
    },
    extensions: ['*', '.js', '.vue', '.json']
  },

P
Paul

Maybe try adding in webpack. mix.webpackConfig references laravel mix.

mix.webpackConfig({

    resolve: {
        alias: {
            '@imgSrc': path.resolve('resources/assets/img')
        }
    }
});

And then in vue use.

<img src="@imgSrc/logo.png" />

D
Dean Schulze

Something must have changed. The answer given here is no longer correct. This project in Chapter09 uses the @ sign in its import statements but the webpack.config.js file doesn't have a path resolve statement:

let service = process.VUE_CLI_SERVICE

if (!service || process.env.VUE_CLI_API_MODE) {
  const Service = require('./lib/Service')
  service = new Service(process.env.VUE_CLI_CONTEXT || process.cwd())
  service.init(process.env.VUE_CLI_MODE || process.env.NODE_ENV)
}

module.exports = service.resolveWebpackConfig()

S
Sanders Gutierrez

An example to apply in Next.js would be to use the file next.config.js to add the next content.

const path = require('path');

module.exports = {
  webpack: (config, options) => {
    config.resolve.alias = {
      '@': path.resolve(process.cwd(), 'src'),
    };
    return config;
  }
};