vitejs / vite

Next generation frontend tooling. It's fast!
http://vite.dev
MIT License
68.04k stars 6.13k forks source link

Import module mapping / custom path resolution #88

Closed micene09 closed 4 years ago

micene09 commented 4 years ago

Taking inspiration from the following:

...would be nice to have a custom path mapping, just to have a sexier import paths, ex:

// example.ts
import { Store, GlobalModule, AppModule } from "@app-utils/store-manager";
import { ICenter } from "@app-rest/centers";
import { ICompany } from "@app-rest/companies";
import MyModal from "@app-components/my-modal/my-modal.vue";

...instead of relative paths like:

import { Store, GlobalModule, AppModule } from "../../store-manager";
import { ICenter } from "../../../centers";
...

Currently on Vue CLI 3 (Webpack), to achieve this feature, i'm using tsconfig-paths-webpack-plugin ...but for a non-typescript related builder like vite i suggest to go for a config file (and maybe an API to extend this behaviour?).

yyx990803 commented 4 years ago

Internally there is already a resolver that does this (see vitepress' resolver for example)

But we probably will provide an easier to use format in the config.

bates64 commented 4 years ago

I propose supporting import maps rather than using special vite-specific config.

ais-one commented 4 years ago

For using import maps please consider also the discussions below...

nestarz commented 4 years ago

Don't know if it can help but I just made a package manager (here) that use import maps spec resolver.

yyx990803 commented 4 years ago

alias option is now supported via the config file. Will consider supporting import maps if it gets closer to being standardized.

aleclarson commented 4 years ago

I've published vite-tsconfig-paths to solve this problem: https://github.com/aleclarson/vite-tsconfig-paths

Also, retweet this if you'd like: https://twitter.com/alecdotbiz/status/1291095881262010371

spikyjt commented 4 years ago

For anyone finding this and wondering how to set up Typescript paths in a Vite project:

axetroy commented 4 years ago

For anyone finding this and wondering how to set up Typescript paths in a Vite project:

  • You must set up your paths with leading slashes, e.g.
      "paths": {
        "/@/*": [
          "src/*"
        ]
      }
  • Add your paths to the alias property in vite.config.js in the root of your project, e.g.

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

ham.... This did not work for me. 😥

import { defineComponent } from "vue";
import { api } from "@/api"; // error here
ynte commented 4 years ago

ham.... This did not work for me. disappointed_relieved

import { defineComponent } from "vue";
import { api } from "@/api"; // error here

You need to start with the forward slash in your import statement as well

import { api } from "/@/api";

As an addition the comment by @spikyjt: I needed to set the baseUrl option in my tsconfig.json to make the alias be recognized by typescript. So I think the minimal config to get started with this is:

{
    "compilerOptions": {
        ..
        "baseUrl": ".",
        "paths": {
            "/@/*": [
                "src/*"
            ]
        }
    },
}
spikyjt commented 4 years ago

@ynte thanks for filling in the gaps. @axetroy I'd written this from the point of view of someone who already used paths with typescript and therefore would know that baseUrl is a requirement to use paths. I wasn't being thorough enough to give a complete example for someone starting from scratch and unfamiliar with paths!

FYI, the @ isn't required, it is just a convention for starting path aliases, to help distinguish from absolute paths. It would be ideal if Vite could support a custom prefix for aliases or at least support @ as well as /, to fit with the convention.

adapap commented 4 years ago

To those who may still be looking for a solution to this problem, I have found a way to use customizable aliases with little complication.

vite.config.ts

const pathAliasMap = {
  '@/': '/src/',
  '@components/': '/src/components/',
  '@views/': '/src/views/',
}

export default {
  resolvers: [
    {
      alias(path: string) {
        for (const [slug, res] of Object.entries(pathAliasMap)) {
          if (path.startsWith(slug)) {
            return path.replace(slug, res)
          }
        }
      },
    },
  ],
}
NWRichmond commented 3 years ago

After trying most of the above recommendations, this is the only configuration that allowed me to map ~ to ./src:

  1. vite.config.ts:
    
    import { defineConfig } from "vite";
    import { resolve } from "path";

export default defineConfig({ resolve: { alias: { "~": resolve(__dirname, "src"), }, }, // ...other config, });


2. `tsconfig.json`:
```json
{
  "compilerOptions": {
    "baseUrl": "./src",
    "paths": {
      "~/*": ["./*"]
    }
  },
}

[June 21, 2021] updated vite.config.ts to agree with the new resolve.alias convention discussed in the next comment.

jonjanisch commented 3 years ago

@NWRichmond thanks that worked for me.

However, I see this warning when starting vite dev mode (vite 2.0.1):

(!) "alias" option is deprecated. Use "resolve.alias" instead.

Changing it to the following removed the warning:

import { defineConfig } from "vite";
import { resolve } from "path";

export default defineConfig({
  resolve: {
    alias: {
      "~": resolve(__dirname, "src"),
    },
  },
  // ...other config,
});
hungdoansy commented 3 years ago

I'm not using TypeScript, but Javascript absolute imports instead. No alias configured. I just have "baseUrl": "./src/" in jsconfig.json and I do things like import {someComponent} from "components/SomeComponent";

Does anyone have ideas how to make paths work automatically?

I can do like this

import { defineConfig } from "vite";
import { resolve } from "path";

export default defineConfig({
  resolve: {
    alias: {
      "components/": resolve(__dirname, "src/components/"),
      "utils/": resolve(__dirname, "src/utils/"),
      "actions/": resolve(__dirname, "src/actions/"),
    },
  },
  // ...other config,
});

But it doesn't look so good to me

patak-dev commented 3 years ago

@hungdoansy comments on closed issues are probably going to get ignored. Please start a GitHub Discussion or join the chat at Vite Land to ask questions. Thanks!

TotomInc commented 3 years ago

@hungdoansy something like this will probably help you:

// vite.config.ts
import path from 'path';
import { readdirSync } from 'fs';

const absolutePathAliases: { [key: string]: string } = {};

const srcPath = path.resolve('./src');
// Don't forget to adjust the regex here so it can include .vue, .js, .jsx, etc... files from the src/ folder.
// In my case, I'm writing React + TypeScript so the regex find files with .ts?(x) extensions only.
const srcRootContent = readdirSync(srcPath, { withFileTypes: true }).map((dirent) => dirent.name.replace(/(\.ts){1}(x?)/, ''));

srcRootContent.forEach((directory) => {
  absolutePathAliases[directory] = path.join(srcPath, directory);
});

export default defineConfig({
  resolve: {
    alias: { ...absolutePathAliases },
  },
});
stefumies commented 3 years ago

With Vue3 Typescript and Viite 2.3.7 I still have not got any of these solutions to work

kfurfles commented 3 years ago

I'm using with react + TS. that works for me

{
 "compilerOptions": {
  "baseUrl": ".",
  "paths": {
      "~/*": ["./src/*"],
      "@core/*": ["./src/core/*"],
      "@authentication/*": ["./src/modules/authentication/*"]
    }
 }

import {
  compilerOptions
} from './tsconfig.json'

import { defineConfig } from 'vite'
import reactRefresh from '@vitejs/plugin-react-refresh'
import { resolve } from 'path';

const alias = Object.entries(compilerOptions.paths)
  .reduce((acc,[key, [value]]) => {
  const aliasKey = key.substring(0, key.length - 2)
  const path = value.substring(0, value.length - 2)
  return {
    ...acc,
    [aliasKey]: resolve(__dirname, path)
  }
}, {})

export default defineConfig({
  plugins: [reactRefresh()],
  resolve: {
    alias
  }
})
JesusTheHun commented 3 years ago

There is a plugin for that now : https://github.com/aleclarson/vite-tsconfig-paths . No more workaround :) the default config works just fine.

mecograph commented 3 years ago

Unfortunately the plugin @JesusTheHun mentioned didn't work for me but the solution @kfurfles did with slight modifications. I had to change the compilerOptions a bit:

import config from './tsconfig.json'

const alias = Object.entries(config.compilerOptions.paths)
  .reduce((acc,[key, [value]]) => {
  ...