create-react-app icon indicating copy to clipboard operation
create-react-app copied to clipboard

Use "paths" in tsconfig.json and jsconfig.json

Open sheepsteak opened this issue 3 years ago • 27 comments

Adds support for compilerOptions.paths in both tsconfig.json and jsconfig.json so that path mapping can be used:

"compilerOptions": {
  "baseUrl": "src",
  "paths": {
    "base/*": ["./components/base/*"],
    "pages/*": ["./components/pages/*"],
    "actions/*": ["./state/actions/*"]
  }
}
  • [x] Parse paths and add to Jest aliases
  • [x] Parse paths and add to Webpack aliases
  • [x] Show error when paths is used without baseUrl for TypeScript before 4.1
  • [x] Show error when paths is used improperly (has to be like example above with only one possible location; no extra fallbacks as Webpack 4 can't handle it)
  • [x] Add docs

I've tried different combinations of paths in both JavaScript and TypeScript projects but no doubt there are still some bugs. I'd just like to get some early feedback and find out what the appropriate level of testing is.

Closes #5645 Closes #9406 Closes #9999

sheepsteak avatar Nov 04 '20 23:11 sheepsteak

This is a really useful change that would remove the need to use CRACO or React App Rewired in our application (and assumedly many apps). CRA-TS used to support this but that project is now deprecated so it would be great to get this into the main project.

Is there any movement on this functionality CRA team?

pd8 avatar Nov 26 '20 10:11 pd8

Just to note: if you're using Yarn 2 you can already do this using the link: protocol https://yarnpkg.com/features/protocols https://yarnpkg.com/features/protocols#why-is-the-link-protocol-recommended-over-aliases-for-path-mapping

merceyz avatar Dec 08 '20 17:12 merceyz

What's outstanding for this to be merged? I'd like to share a project of interfaces between an express app and a CRA frontend stored in the same directory.

pnewhook avatar Feb 07 '21 00:02 pnewhook

Hey, can someone move this forward? The more you leave it the harder it gets to merge

danielo515 avatar Apr 07 '21 05:04 danielo515

What's outstanding for this to be merged?

The checkboxes in the description are up to date. More importantly, I still need some guidance from the CRA team around whether we need to start verifying the jsconfig.json file like we do with the tsconfig.json and also on the overall approach; it just needs a review basically to see if they'll accept it and then I get some tests done.

The related issue for this (https://github.com/facebook/create-react-app/issues/5645) has been placed into the 4.x milestone and that seems really far away at the moment due to the amount of PRs in the other milestones. I'm not sure if this is a priority for the team at the moment.

sheepsteak avatar Apr 07 '21 08:04 sheepsteak

this would be a great addition

keremciu avatar Apr 07 '21 16:04 keremciu

We also wait for this to progress.

jayarjo avatar May 05 '21 12:05 jayarjo

I was very disheartened to discover how long this has taken to be fixed. Regardless, here's my patch. It's ugly, it requires craco, it may break with a later CRA update, and it assumes you are using aliases how I am (my usage is shown).

It does the following:

  • Grabs an original copy of tsconfig
  • Wraps verifyTypeScriptSetup using require.cache
  • After verifyTypeScriptSetup runs it restores the paths you configured
  • Injects your tsconfig paths into webpack so they are properly resolved

craco.config.js

const verifyTypeScriptSetup = require("react-scripts/scripts/utils/verifyTypeScriptSetup");
const fs = require("fs");
const os = require("os");
const path = require("path");

const mapObject = (obj, mapper) => Object.fromEntries(Object.entries(obj).map(mapper));

// original copy of tsconfig
const originalTSConfig = require("./tsconfig.json");

// generates a mapping of aliases that webpack can take
const webpackCompatibleAliases = mapObject(originalTSConfig.compilerOptions.paths, ([ k, [ v ] ]) => [
    k.slice(0, -2), path.resolve(__dirname, originalTSConfig.compilerOptions.baseUrl, v.slice(0, -1))
]);

// wrap the utility function that is ruining the party!! >:(
require.cache[require.resolve("react-scripts/scripts/utils/verifyTypeScriptSetup")].exports = function() {
    // let cra think they ruined the party
    verifyTypeScriptSetup();

    // delete the cached tsconfig.json so we can get the cra-updated tsconfig
    delete require.cache[require.resolve("./tsconfig.json")];

    const tsconfig = require("./tsconfig.json");

    // restore paths
    tsconfig.compilerOptions.paths = originalTSConfig.compilerOptions.paths;

    // write tsconfig as it is written in the verifyTypeScriptSetup.js file
    fs.writeFileSync("tsconfig.json", JSON.stringify(tsconfig, null, 2).replace(/\n/g, os.EOL) + os.EOL);
}

module.exports = {
    webpack: {
        configure: config => {
            if (!config.resolve) config.resolve = {};
            if (!config.resolve.alias) config.resolve.alias = {};

            // load the ts aliases into webpack, from tsconfig
            Object.assign(config.resolve.alias, webpackCompatibleAliases);

            // do whatever else you need to

            return config;
        }
    }
}

tsconfig.json (necessary bits only)

{
  "compilerOptions": {
    "baseUrl": "./src",
    "paths": {
      "@contexts/*": [
        "contexts/*"
      ],
      "@hooks/*": [
        "hooks/*"
      ],
      "@util/*": [
        "util/*"
      ],
      "@chat-items/*": [
        "transcript/items/chat/*"
      ],
      "@transcript-items/*": [
        "transcript/items/transcript/*"
      ],
      "@devtools/*": [
        "devtools/*"
      ],
      "@transcript/*": [
        "transcript/*"
      ]
    }
  }
}

EricRabil avatar May 16 '21 00:05 EricRabil

This pull request has been automatically marked as stale because it has not had any recent activity. It will be closed in 5 days if no further activity occurs.

stale[bot] avatar Jun 26 '21 03:06 stale[bot]

I have a dream, bump

yordis avatar Jun 27 '21 01:06 yordis

Please add this already, There's no reason we have to use an external package to just add import aliases!

hichemfantar avatar Jul 24 '21 23:07 hichemfantar

any recent news about this?

pycraft114 avatar Aug 06 '21 09:08 pycraft114

please

EricRabil avatar Aug 06 '21 20:08 EricRabil

This is a must-have feature

kytosai avatar Aug 07 '21 04:08 kytosai

For a framework that wants to be batteries-included this is a pretty huge facepalm to leave sitting here for what could easily become a year or more.

import xyz from "../../../../contexts/xyz" vs import xyz from "@/contexts/xyz"

This seems like a pretty huge enhancement, and an easy one. The fix is sitting right here. Pleaseee.

EricRabil avatar Aug 08 '21 00:08 EricRabil

What Create-React-App it could be a huge problem for some, more information here: https://github.com/straw-hat-team/adr/tree/master/adrs/2068541249

Had happened before, more than I would love to knowledge, https://github.com/straw-hat-team/adr/pull/6#discussion_r526365809

yordis avatar Aug 08 '21 02:08 yordis

this is joke-tier

jeanlucmongrain avatar Sep 02 '21 06:09 jeanlucmongrain

This is what I perceive to be one of the biggest pitfalls of zeroconf build systems, where features like this that you don’t need until you’ve got a large codebase just sit and die in the backlog and you’re left hacking around it.

EricRabil avatar Sep 02 '21 14:09 EricRabil

The easiest workaround without additional packages is to set the base url to be the src folder inside tsconfig:

"compilerOptions": {
    "baseUrl": "./src"
  }

Then you can import assets easily like: import video from "assets/videos/demo_video.m4v";

I realise It's not as convenient as import aliases but It's enough for me because I prefer not to configure additional packages into my project and I must say that It's working pretty well for me and It's definitely made importing less annoying.

Also one more thing, if you want to stop react-scripts from deleting the paths property when you start the app because paths still aren't supported you can move the config into tsconfig.base.json then extend tsconfig.json with that file.

tsconfig.base.json:

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "paths": {
      "@/*": [
        "./src/*"
      ],
      "@/images/*": [
        "./assets/images/*"
      ],
    }
  },
  "include": [
    "src"
  ]
}

tsconfig.json:

{
  "extends": "./tsconfig.base.json",
  "compilerOptions": {
    "baseUrl": "./src"
  }
}

hichemfantar avatar Sep 02 '21 19:09 hichemfantar

The easiest workaround without additional packages is to set the base url to be the src folder inside tsconfig:

Problem with that is the name space collisions, which can be managed with a but of care. But it's not as optimal as a ~ prefix

jeanlucmongrain avatar Sep 03 '21 01:09 jeanlucmongrain

please finish this!

rattkin avatar Nov 09 '21 10:11 rattkin

To anyone looking for a workaround until this PR has merged, have a look at this 👉 https://github.com/risenforces/craco-alias#installation, it is simple and easy to use.

floppydisken avatar Jan 03 '22 11:01 floppydisken

any updates? this feature will increase productivity at least 5X

kailingding avatar Mar 11 '22 00:03 kailingding

any updates? this feature will increase productivity at least 5X

agree 100X

but is there any workaround at the moment?

amir0ff avatar Mar 11 '22 10:03 amir0ff

any updates? this feature will increase productivity at least 5X

agree 100X

but is there any workaround at the moment?

You can use the Craco library but I believe someone said it's broken with the newest cra version.

hichemfantar avatar Mar 11 '22 13:03 hichemfantar

I don't generally use CRA anymore but I've updated this for people who need it. It seems like a lot of tests in the repo don't get run now and there's more general integration tests that are used so everything is passing. I've also used npm link locally with both new JavaScript and TypeScript projects and both work with paths.

Hopefully the CRA team will be able to look at this some point so it can get reviewed/merged.

sheepsteak avatar Sep 10 '22 12:09 sheepsteak

I recommend using Vite or Nextjs for future projects. Create react app seems to be on life support at this point.

hichemfantar avatar Sep 10 '22 13:09 hichemfantar

2 years 126 days - any update on this? Hoping for an early Christmas.

trapgar avatar Mar 10 '23 16:03 trapgar

2 years 126 days - any update on this? Hoping for an early Christmas.

CRA will no longer get any new features. The team is considering converting CRA into a cli tool that scaffolds projects using other tools such as vite and next.

The best solution is to switch to vite. And if SSR is required, then use next or remix.

hichemfantar avatar Mar 10 '23 19:03 hichemfantar

any update?

quanlh-ttlab avatar Apr 02 '23 19:04 quanlh-ttlab