Importação do ES6 usando o caminho de entrada em ('@') em um projeto vue.js usando o Webpack

273

Estou iniciando um novo projeto vue.js, então usei a ferramenta vue-cli para criar um novo projeto de webpack (por exemplo vue init webpack).

Enquanto eu andava pelos arquivos gerados, notei as seguintes importações no src/router/index.jsarquivo:

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
        }
    ]
})

Eu nunca vi o sinal de arroba ( @) em um caminho antes. Eu suspeito que ele permita caminhos relativos (talvez?), Mas eu queria ter certeza de que entendi o que ele realmente faz.

Tentei pesquisar on-line, mas não consegui encontrar uma explicação (provavelmente porque pesquisar por "arroba" ou usar o caractere literal @não ajuda como critério de pesquisa).

O que @faz nesse caminho (o link para a documentação seria fantástico) e isso é uma coisa es6? Uma coisa do webpack? Uma coisa vue-loader?

ATUALIZAR

Obrigado Felix Kling por me apontar para outra pergunta / resposta duplicada sobre o stackoverflow sobre essa mesma pergunta.

Embora o comentário na outra postagem do stackoverflow não seja a resposta exata para essa pergunta (não era um plugin babel no meu caso), ele me apontou na direção correta para encontrar o que era.

Nos andaimes que o vue-cli cria para você, parte da configuração básica do webpack define um alias para os arquivos .vue:

Localização do alias no projeto

Isso faz sentido, pois fornece um caminho relativo a partir do arquivo src e remove o requisito do .vueno final do caminho de importação (que normalmente você precisa).

Obrigado pela ajuda!

Chris Schmitz
fonte
3
Veja meu comentário .
Felix Kling 12/03
1
@FelixKling Não é uma cópia exata, porque não responde a toda a pergunta, isso é uma coisa es6? Uma coisa do webpack? Uma coisa vue-loader?
Estus Flask
Sim, acho que a pergunta era semelhante, mas não duplicada. Independentemente disso, descobri de onde vinha e atualizei a pergunta com uma explicação, pois não posso adicioná-la como resposta.
22417 Chris Schmitz
@estus: a resposta deixa bem claro que não faz parte do ES6, mas uma coisa de configuração do webpack, você não acha? E esse é exatamente o caso aqui também, apenas que a natureza da configuração é um pouco diferente.
Felix Kling 12/03
@FelixKling Acredito que quando estus apontou que ainda havia uma dúvida sobre que tipo de coisa é que eu ainda não havia adicionado a atualização (eu vi o comentário dele entrando enquanto eu estava digitando a atualização). Estou pronto e há uma explicação detalhada sobre minha instância específica, então estou pronto para ir. Obrigado rapazes.
22417 Chris

Respostas:

243

Isso é feito com a resolve.aliasopção de configuração do Webpack e não é específico do Vue.

No modelo Vue Webpack , o Webpack está configurado para substituir @/pelo srccaminho :

  const path = require('path');

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

O alias é usado como:

import '@/<path inside src folder>';
Estus Flask
fonte
171
JavaScript simplesmente não é mais JavaScript. O Babel / webpack nos fornece essa linguagem Frankenstein e, de alguma forma, os novos desenvolvedores devem saber onde termina a especificação do ECMAScript e os plugins / transformações da terra do usuário começam. É realmente triste, imo.
Obrigado
3
@naomik Cabe ao usuário introduzir esses truques na configuração ou não. Não é grande coisa para o Vue, uma vez que depende do formato de arquivo .vue personalizado.
Estus Flask
15
Pessoalmente, acho que a capacidade de adicionar flexibilidade, se você quiser, é uma coisa boa. Eu o vejo menos como frankenstein e mais como voltron; você pode fazer coisas como um leão ou combinar diferentes leões para ter um robô maior. Sim, às vezes você recebe perguntas como essa, mas não é como se as respostas não fossem encontradas. Realmente, você pode ter a visão de frankenstein ou voltron com qualquer projeto de qualquer tamanho, é apenas "usando e entendendo dependências".
22717 Chris Schmitz
1
@ChrisSchmitz Depende do contexto e da perspectiva. Fazer algo assim restringirá o projeto ao uso do Webpack. Pode não ser uma boa coisa se o projeto pretender usar módulos ES6 nativos quando eles chegarem, ou é o Nó onde o CommonJS pode ser usado para módulos. Caminhos relativos longos podem ser mais difíceis de manter e refatorar, por outro lado.
Estus Flask
3
Ao usar o vue-cliv3 +, você deve usar ~@para fazer referência à srcpasta. Por exemplo:$font-path: '~@/assets/fonts/';
Consta Gorgan
9

Lembre-se também de que você pode criar variáveis ​​no tsconfig:

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

Isso pode ser utilizado para fins de convenção de nomenclatura:

import { componentHeader } from '@components/header';
Tyler Canton
fonte
Mas esse tipo de alias será deixado nu no JS de origem e, em tempo de execução, você precisará ter um wrapper intercedido para que o alias funcione. Talvez exista uma maneira via babel para essa sintaxe TS ser convertida no momento da construção? Com Typcript's tscis does e, portanto, você precisará de algo como module-aliasou tsconfig-paths.
ken
3

Eu acabo com a seguinte combinação

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

O IDE deixará de avisar a interface do usuário, mas isso causará uma interface inválida ao compilar, em "build \ webpack.base.conf.js"

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

Bingoo!

Luân Trương
fonte
1

resolve ('src') não funciona para mim, mas path.resolve ('src') funciona

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

Talvez tente adicionar no webpack. mix.webpackConfig referencia o laravel mix .

mix.webpackConfig({

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

E então no uso vue.

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