vuejs / vue-cli

🛠️ webpack-based tooling for Vue.js Development
https://cli.vuejs.org/
MIT License
29.75k stars 6.33k forks source link

cli-plugin-typescript: use tsconfig-paths-webpack-plugin #3123

Open IlyaSemenov opened 5 years ago

IlyaSemenov commented 5 years ago

What problem does this feature solve?

Currently, cli-plugin-typescript creates tsconfig.json with aliases setup that repeats vue-cli's webpack aliases, namely:

    "baseUrl": ".",
    "paths": {
      "@/*": [
        "src/*"
      ]
    }

If a developer changes or extends this setup, the code will fail to compile with webpack (because webpack ignores tsconfig.json and uses its own resolve.aliases setup).

Changing the defaults is not the edge case, but rather a probable scenario because the default setup is far from ideal for real use: "baseUrl": "." pollutes the root Node.js module namespace with everything that happens to reside in the project root. For example, in my project I switch it to this:

    "baseUrl": "./src",
    "paths": {
      "@/*": [
        "myproject/*"
      ]
    },

To complete that setup, the developer is forced to put alias updates in two files: tsconfig.json and vue.config.js under chainWebpack and keep them synchronised.

Misleading tsconfig.json setup that can't really be changed without changing its webpack counterpart, and having to support two aliases setups is the problem that I propose to solve.


https://github.com/dividab/tsconfig-paths-webpack-plugin allows webpack to pull aliases setup from tsconfig.json and make it the single source of truth. It can be enabled like this in vue.config.js:

module.exports = {
  chainWebpack(config) {
    config.resolve.alias.delete("@")
    config.resolve
      .plugin("tsconfig-paths")
      .use(require("tsconfig-paths-webpack-plugin"))
  },
}

I propose to make this the default setup when cli-plugin-typescript is used. At the very least, this recipe should be added to the documentation in a new chapter that explains that changing tsconfig paths is not possible without updating webpack setup.

What does the proposed API look like?

From the end-user point of view, nothing will change. The defaults will be the same. However, should user modify tsconfig baseUrl/paths, everything will transparently continue to work in webpack.

LinusBorg commented 5 years ago

Nice Suggestion.

But I have a few doubts:

  1. This only works for typescript, obviously. So in a Babel project, webpack is defining the aliases, while in a typescript project, tsconfig is. Could be confusing.
  2. This doesn't solve the problem of maintaining aliases I multiple places completely, as we also have the alias in the jest config file.
IlyaSemenov commented 5 years ago

Honestly, both are fair points and I can't really argue. So I'll understand if you just wontfix this issue.

Still, my observations on the above:

  1. I believe Typescript folks are get used to using tsconfig, so if it's clearly documented it's not going to be a problem. After all, tsconfig can be considered a first class language-native setup, and webpack becoming dependent on it is nothing unusual. But, again, I agree that it's backwards incompatible and somewhat confusing.

  2. ts-jest provides the built-in moduleNameMapper helper for this case: https://kulshekhar.github.io/ts-jest/user/config/#paths-mapping — I'm not sure if it can be easily enabled with vue-cli or not. (Personally, I hate Jest in particular because it introduces one more babel bundler, and because of its other injected magic. I switched to node-tap which is language-agnostic and free of any kind of magic and I couldn't be more happy.)

dsebastien commented 5 years ago

+1 for at least documenting the situation clearly. As a TS developer, I was bitten by this. Actually as far as I can see the default paths property set in tsconfig.json does not seem to work at all, unless I add tsconfig-paths-webpack-plugin as described by @IlyaSemenov.

LinusBorg commented 5 years ago

Actually as far as I can see the default paths property set in tsconfig.json does not seem to work at all

What happens thatmakes you say that?

In mine it works fine.

prodrammer commented 5 years ago

After running vue create, I added my own paths to tsconfig.json. npm run serve resulted in an import error that should have been resolved by the new paths. Adding tsconfig-paths-webpack-plugin and @IlyaSemenov's vue.config.js example worked for me.

I assume plugins can present installation options? Maybe this should be an installation option?

sformisano commented 5 years ago

Just my 0,02: also bitten by this with TS, spent hours today trying to figure out why tsconfig paths were being ignored and only figured out there was a problem with trial and error (ultimately scaffolding a new project and seeing the same issue).

This requires documentation.

sformisano commented 5 years ago

Also thanks @IlyaSemenov you saved me from a useless all-nighter.

gormonn commented 3 years ago

@IlyaSemenov Be attention that it works only for one record in tsconfig.json paths.

matt-snider commented 3 years ago

Don't mean to spam everyone, but I wanted to chime in that I also ran into this. I spent the better part of the day trying to get to the bottom of import errors after splitting a project into multiple Yarn workspaces. I had set up a few different paths in tsconfig.json, since @/ was no longer sufficient with multiple workspaces. I couldn't figure out why the aliases weren't working. Eventually, I realized that when the aliases in tsconfig.json were correct, then the Typescript import errors would disappear, but the webpack errors remained. Then I found this issue. @IlyaSemenov Thank you for the workaround - you saved me a lot of time!

I'm not familiar enough with the project to comment on whether the proposed solution can be implemented directly in the project, but I think an easy win would be to add a comment to the generated tsconfig.json file, warning the user not to naively change paths.

lpj145 commented 3 years ago

i had to add more weight on this issue, i'm in trouble with aliases on vue-cli, i made a lot of changes, search for around internet, and frustate with this problem, please consider resolve this problem with plugin or maybe we can help on some solutions...

People what want to go monorepo solutions enter in trouble because a simple aliases don't work. thank you to save my rest of week @IlyaSemenov .

vasilyevd commented 2 years ago

I spent the better part of the day trying to get to the bottom of import errors

Similarly. Started learning Vue from the big Angular project. And of course, some step in the study was the transition to TS. I spent 4 hours trying to understand the cause and determined that the tsconfig file setup did absolutely nothing and additional configuration was required. Although I was expecting vue-cli to take over.

It would be nice to solve this problem (at least with TS ) at the vue-cli level. This will not "scare" those who start using vue and are faced with non-obvious things that are poorly described in the documentation (I searched for a long time until I got here and confirmed my guesses)

IlyaSemenov commented 2 years ago

Guys, in 2022 it's safe to drop vue-cli and switch to vite.

Mettbrot commented 2 years ago

Thank you, this is working well! Why do we do config.resolve.alias.delete("@") though? With it require.context("@/assets/"... does not work for me anymore. I have the path "@/*": ["src/*"] in tsconfig.json so it should pick up the files.

MartinX3 commented 2 years ago

even using "~/*": ["./*"] doesn't work. only @/* is usable with cli 5.0.8

Switching to vite is not safe, since vuetify 2.6.7 doesn't work with it (without many complicated workarounds).