-1

I started working recently on a Vue 3 application which runs with vite and I am trying to restructure the directories so that I can group components and related sub-components in folders.

I am currently using /path/to/MyComponent/index.vue to import the higher-hierarchy component, and I would like to write the import statement without specifying the file name, so that I could do something like this:

import MyComponent from `@/path/to/MyComponent`

where the files structure looks like the following:

path
│   
└───to
    │   
    └───MyComponent
        │   index.vue
        │   SubComponent.vue
        │   ...

I tried to play with the resolve.alias property in the vite.config.ts file, but I wasn't successful. Anyone managed to achieve this?

This is one of the attempts:

export default defineConfig({
...
resolve: {
    alias: [
        {
            find: "@",
            replacement: fileURLToPath(new URL("./src", import.meta.url)),
        },
        {
            find: /(^(?!.*[.](ts|js|tsx|jsx|vue|)$))/,
            replacement: "$1/index.vue",
        },
    ],
},
...
kissu
  • 40,416
  • 14
  • 65
  • 133
InCodice
  • 1
  • 2
  • 1
    You can also use that one: https://github.com/antfu/unplugin-vue-components Will be faster overall and is already done + optimized for you. – kissu Dec 29 '22 at 15:44
  • Thank you @kissu, it seems like a very good workaround. I can see that there is not yet typescript [support for imported components](https://github.com/antfu/unplugin-vue-components#typescript), but a PR is already made, and it should be available soon. I did find a solution with vite alias, which I will share shortlu, but I have issues to make it work with the ts linter. – InCodice Dec 30 '22 at 10:30
  • I'm not using TS so I cannot really help there, unfortunately. – kissu Dec 30 '22 at 13:49

1 Answers1

-1

After trying various things I found a solution in line with my original post involvin modifying the vite.config.ts file resolve.alias property.

In addition I had to modify the tsconfig.json file to make sure that typescript compiler is also able to resolve the path to the index.vue file.

This is how I achieved importing a index.vue component only referencing the parent folder name:

1. Vite configuration

// vite.config.ts

export default defineConfig({
    resolve: {
        alias: [
            {
                find: /@\/components\/((?!.*[.](ts|js|tsx|jsx|vue)$).*$)/,
                replacement: fileURLToPath(
                    new URL("./src/components/$1/index.vue", import.meta.url)
                ),
            },
            {
                find: "@",
                replacement: fileURLToPath(new URL("./src", import.meta.url)),
            },
            // ...

The above configuration code will tell vite to check if the import statement contains with @/components and does NOT end with any of the following extensions: ts|js|tsx|jsx|vue. E.g. @/components/MyComponent.

When these criteria are met the find path will be replaced with the path to the index.vue file within the src/components folder. E.g. @/components/MyComponent/index.vue.

The only limitations of the above solution is that it targets a specific folder (in this case the components folder). However we can add more alias objects to match any other folder where we want to implement this import pattern.

2. Typescript configuration

If using typescript ESLint will throws two errors: Missing file extension and Unable to resolve path to module. This because the typescript compiler is agnostic of the above vite configuration.

For this reason I also had to modify the tsconfig.json file as following:

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

The above code will leverage Typescript module resolution path mapping to map everything that matches @/components/* to ./src/components/*, where * represents the path within the ./src/components. This path is relative to where the tsconfig.json file reside (as defined by the baseUrl parameter).

If a component is not found, Typescript compiler will look inside ./src/components/*/index.vue.

InCodice
  • 1
  • 2