vite-plugin-vue icon indicating copy to clipboard operation
vite-plugin-vue copied to clipboard

tilde alias not working in `img.src`

Open BryanAdamss opened this issue 3 years ago • 7 comments

Describe the bug

use npm init vue and them chage the alias from @ to ~,then get this error!

// vite.config.ts
...
{
    resolve:{
        alias: {
            '~': fileURLToPath(new URL('../src', import.meta.url)),
        }
    }
}
...

// App.vue
<script setup lang="ts">
import { RouterLink, RouterView } from 'vue-router'

// working!
import HelloWorld from '~/components/HelloWorld.vue'
</script>

<template>
   // not working; [vite] Internal server error: Failed to resolve import "assets/logo.svg" from "src\App.vue". Does the file exist?
    <img alt="Vue logo" class="logo" src="~/assets/logo.svg" width="125" height="125">
</template>

<style>
    // working!
    @import '~/assets/base.css';
</style>

use @ its all working!

Reproduction

1、use npm init vue 2、chage the alias from @ to ~,then get this error!

System Info

System:
    OS: Windows 10 10.0.18363
    CPU: (8) x64 Intel(R) Core(TM) i5-10210U CPU @ 1.60GHz
    Memory: 3.60 GB / 15.74 GB
  Binaries:
    Node: 16.16.0 - C:\Program Files\nodejs\node.EXE
    npm: 8.11.0 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Chrome: 103.0.5060.114
    Edge: Spartan (44.18362.449.0)
    Internet Explorer: 11.0.18362.1
  npmPackages:
    @vitejs/plugin-vue: ^2.3.3 => 2.3.3
    @vitejs/plugin-vue-jsx: ^1.3.10 => 1.3.10
    vite: ^2.9.12 => 2.9.14

Used Package Manager

pnpm

Logs

Click to expand!
// paste the log text here
vite:config using resolved config: {
  vite:config   root: 'D:/ReposSave/vue-awesome-template',
  vite:config   base: '/',
  vite:config   publicDir: 'D:\\ReposSave\\vue-awesome-template\\public',
  vite:config   cacheDir: 'D:\\ReposSave\\vue-awesome-template\\node_modules\\.vite',
  vite:config   plugins: [
  vite:config     'vite:pre-alias',
  vite:config     'alias',
  vite:config     'vite:modulepreload-polyfill',
  vite:config     'vite:resolve',
  vite:config     'vite:optimized-deps',
  vite:config     'vite:html-inline-proxy',
  vite:config     'vite:css',
  vite:config     'vite:esbuild',
  vite:config     'vite:json',
  vite:config     'vite:wasm',
  vite:config     'vite:worker',
  vite:config     'vite:asset',
  vite:config     'vite:vue',
  vite:config     'vite:vue-jsx',
  vite:config     'vite:define',
  vite:config     'vite:css-post',
  vite:config     'vite:worker-import-meta-url',
  vite:config     'vite:client-inject',
  vite:config     'vite:import-analysis'
  vite:config   ],
  vite:config   resolve: {
  vite:config     dedupe: undefined,
  vite:config     alias: [ [Object], [Object], [Object] ],
  vite:config     mainFields: [ 'module', 'jsnext:main', 'jsnext' ],
  vite:config     extensions: [ '.mjs', '.js', '.ts', '.jsx', '.tsx', '.json' ]
  vite:config   },
  vite:config   css: { devSourcemap: false },
  vite:config   json: { namedExports: true, stringify: false },
  vite:config   logLevel: 'info',
  vite:config   clearScreen: true,
  vite:config   envDir: 'root',
  vite:config   envPrefix: 'VITE_',
  vite:config   server: {
  vite:config     preTransformRequests: true,
  vite:config     host: 'localhost',
  vite:config     port: 3000,
  vite:config     strictPort: false,
  vite:config     open: false,
  vite:config     fs: { strict: true, allow: [Array], deny: [Array] }
  vite:config   },
  vite:config   define: { __VUE_OPTIONS_API__: true, __VUE_PROD_DEVTOOLS__: false },
  vite:config   ssr: { external: [ 'vue', '@vue/server-renderer' ] },
  vite:config   esbuild: { include: /\.ts$/ },
  vite:config   configFile: 'D:/ReposSave/vue-awesome-template/vite.config.ts',
  vite:config   configFileDependencies: [
  vite:config     'D:/ReposSave/vue-awesome-template/.vite-config/shared.conf.ts',
  vite:config     'D:/ReposSave/vue-awesome-template/.vite-config/dev.conf.ts',
  vite:config     'D:/ReposSave/vue-awesome-template/.vite-config/prod.conf.ts',
  vite:config     'D:/ReposSave/vue-awesome-template/.vite-config/index.ts',
  vite:config     'D:/ReposSave/vue-awesome-template/vite.config.ts'
  vite:config   ],
  vite:config   inlineConfig: {
  vite:config     root: undefined,
  vite:config     base: undefined,
  vite:config     mode: undefined,
  vite:config     configFile: undefined,
  vite:config     logLevel: undefined,
  vite:config     clearScreen: undefined,
  vite:config     server: {}
  vite:config   },
  vite:config   command: 'serve',
  vite:config   mode: 'development',
  vite:config   isWorker: false,
  vite:config   isProduction: false,
  vite:config   build: {
  vite:config     target: [ 'es2019', 'edge88', 'firefox78', 'chrome87', 'safari13.1' ],
  vite:config     polyfillModulePreload: true,
  vite:config     outDir: 'dist',
  vite:config     assetsDir: 'assets',
  vite:config     assetsInlineLimit: 4096,
  vite:config     cssCodeSplit: true,
  vite:config     cssTarget: [ 'es2019', 'edge88', 'firefox78', 'chrome87', 'safari13.1' ],
  vite:config     sourcemap: false,
  vite:config     rollupOptions: {},
  vite:config     minify: 'esbuild',
  vite:config     terserOptions: {},
  vite:config     write: true,
  vite:config     emptyOutDir: null,
  vite:config     manifest: false,
  vite:config     lib: false,
  vite:config     ssr: false,
  vite:config     ssrManifest: false,
  vite:config     reportCompressedSize: true,
  vite:config     chunkSizeWarningLimit: 500,
  vite:config     watch: null,
  vite:config     commonjsOptions: { include: [Array], extensions: [Array] },
  vite:config     dynamicImportVarsOptions: { warnOnError: true, exclude: [Array] }
  vite:config   },
  vite:config   preview: {
  vite:config     port: undefined,
  vite:config     strictPort: false,
  vite:config     host: 'localhost',
  vite:config     https: undefined,
  vite:config     open: false,
  vite:config     proxy: undefined,
  vite:config     cors: undefined,
  vite:config     headers: undefined
  vite:config   },
  vite:config   env: { BASE_URL: '/', MODE: 'development', DEV: true, PROD: false },
  vite:config   assetsInclude: [Function: assetsInclude],
  vite:config   logger: {
  vite:config     hasWarned: false,
  vite:config     info: [Function: info],
  vite:config     warn: [Function: warn],
  vite:config     warnOnce: [Function: warnOnce],
  vite:config     error: [Function: error],
  vite:config     clearScreen: [Function: clearScreen],
  vite:config     hasErrorLogged: [Function: hasErrorLogged]
  vite:config   },
  vite:config   packageCache: Map(0) {},
  vite:config   createResolver: [Function: createResolver],
  vite:config   optimizeDeps: {
  vite:config     esbuildOptions: { keepNames: undefined, preserveSymlinks: undefined }
  vite:config   },
  vite:config   worker: {
  vite:config     format: 'iife',
  vite:config     plugins: [
  vite:config       [Object], [Object],
  vite:config       [Object], [Object],
  vite:config       [Object], [Object],
  vite:config       [Object], [Object],
  vite:config       [Object], [Object],
  vite:config       [Object], [Object],
  vite:config       [Object], [Object],
  vite:config       [Object], [Object],
  vite:config       [Object]
  vite:config     ],
  vite:config     rollupOptions: {}
  vite:config   }
  vite:config }

Validations

BryanAdamss avatar Jul 13 '22 10:07 BryanAdamss

vue/compiler-sfc seems to remove the first ~ here. https://github.com/vuejs/core/blob/8dcb6c7bbdd2905469e2bb11dfff27b58cc784b2/packages/compiler-sfc/src/templateTransformAssetUrl.ts#L116 https://github.com/vuejs/core/blob/8dcb6c7bbdd2905469e2bb11dfff27b58cc784b2/packages/compiler-sfc/src/templateUtils.ts#L22-L29

I'm not sure why this is done.

sapphi-red avatar Jul 13 '22 11:07 sapphi-red

https://vue-loader.vuejs.org/guide/asset-url.html#transform-rules Don't configure ~ as an alias.

haoqunjiang avatar Jul 13 '22 15:07 haoqunjiang

We need to document it in the Vite plugin too.

haoqunjiang avatar Jul 13 '22 15:07 haoqunjiang

https://vue-loader.vuejs.org/guide/asset-url.html#transform-rules Don't configure ~ as an alias.

It looks like both @ and ~ are treated as module request. Why @ working and ~ not?

I try configure other symbol like & , the path &/assets/logo.svg returned as is.(https://vitejs.dev/config/shared-options.html#resolve-alias)

So, best practices its keep @ as alias?😂

BryanAdamss avatar Jul 14 '22 02:07 BryanAdamss

https://vue-loader.vuejs.org/guide/asset-url.html#transform-rules Don't configure ~ as an alias.

It looks like both @ and ~ are treated as module request. Why @ working and ~ not?

I try configure other symbol like & , the path &/assets/logo.svg returned as is.(https://vitejs.dev/config/shared-options.html#resolve-alias)

So, best practices its keep @ as alias?😂

But @antfu 's vite template vitesse does set '~' alias

doooooit avatar May 11 '23 06:05 doooooit