Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support absolute imports with @ #5118

Closed
xiaoxiangmoe opened this issue Sep 27, 2018 · 44 comments
Closed

Support absolute imports with @ #5118

xiaoxiangmoe opened this issue Sep 27, 2018 · 44 comments
Milestone

Comments

@xiaoxiangmoe
Copy link
Contributor

webpack.base.conf.js wrote as below:

resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      '@': resolve('src'),
    }
 },

https://github.com/vuejs-templates/webpack/blob/master/template/build/webpack.base.conf.js#L40

Can we use import Hello from '@/components/Hello' like vue?

@Timer
Copy link
Contributor

Timer commented Sep 27, 2018

Place NODE_PATH=src into your .env file and proceed to import components/Hello.

@gaearon
Copy link
Contributor

gaearon commented Sep 27, 2018

I’d say let’s just add @ support. I was resistant because I thought we’d do monorepos sooner. But since that was shelved we might as well do what Vue does.

@Timer Timer added this to the 2.x milestone Sep 27, 2018
@Timer Timer changed the title Is there an equivalent for webpack.resolve.alias? Support absolute imports with @ Sep 27, 2018
@Timer
Copy link
Contributor

Timer commented Sep 27, 2018

We'll need to make sure it works with webpack (obviously), but also Jest/Flow/ESLint(?).

@gaearon
Copy link
Contributor

gaearon commented Sep 27, 2018

Can we just create node_modules/@ and link it?

@xiaoxiangmoe
Copy link
Contributor Author

@gaearon Why does monorepos affect @ support?

@gaearon
Copy link
Contributor

gaearon commented Sep 27, 2018

If we had monorepo support we’d encourage people to put different top level folders into separate packages instead of having a special way to refer to the root.

@xiaoxiangmoe
Copy link
Contributor Author

By the way, our individual packages in monorepo, if we don't want to publish it to NPM, how should it be named?

@gaearon
Copy link
Contributor

gaearon commented Sep 27, 2018

Doesn't matter.

@xiaoxiangmoe
Copy link
Contributor Author

xiaoxiangmoe commented Sep 28, 2018

@gaearon

If we had monorepo support we’d encourage people to put different top level folders into separate packages instead of having a special way to refer to the root.

I think even with monorepo, we still need a special way to refer to the root.

For example, if we needs two axios instances, it would be unreasonable for us to put these strongly business-relevant codes in separate packages.

@iremlopsum
Copy link

@gaearon any update on this?

@tanduong
Copy link

tanduong commented Oct 31, 2018

The simplest way to achieve this is to create node_modules/@ and link it as @gaearon suggested. You could do this by adding a postinstall script to your package.json. Like this:

{
  // ...
  "scripts": {
    "preinstall": "rm node_modules/@",
    "postinstall": "ln -s `pwd`/src node_modules/@",
    // ...
  },
  // ...
}

@robertvansteen
Copy link
Contributor

If we would proceed with this would NODE_PATH support be dropped? Because I’d prefer that over any prefix symbol. I also think for people new to JS/React an absolute path like components/button feels natural while something like @/components/button is yet another thing they need to learn and needs to be explained.

@tanduong
Copy link

@rovansteen I personally prefer an explicit symbol so that I can tell whether the imports come from the application code or a node module. If @ looks weird, you may try with: src, @src, app, @app, ... instead.

@robertvansteen
Copy link
Contributor

@tanduong it's not about that the @ looks weird it's about that it is not a common pattern for paths. Relative paths starting with a . and absolute paths not starting with a dot is a much more common pattern.

@robertvansteen
Copy link
Contributor

You could then argue if the absolute path should be the root directory of the application or the src directory. If you'd go with the root directory you do have the benefit of having to "prefix" all of your absolute imports of your application code with src. I don't know if there's any upside/downside of NODE_PATH vs. webpack alias if you go with src as the prefix.

@dmythro
Copy link

dmythro commented Oct 31, 2018

Is there any IDE support on this for proper auto-complete etc?

Didn't see such practice on corporate projects before. But relative paths are very annoying indeed.

@yordis
Copy link

yordis commented Oct 31, 2018

@Z-AX definitely IDEs auto-complete and indexing will become an issue.

Even in Vue, I didn't use this.

It sounds good, it looks good, but in practice becomes an issue.

@xiaoxiangmoe
Copy link
Contributor Author

@Z-AX
For js file,we can write a fake webpack config, see umijs/umi#1109
For ts file, we can use paths in tsconfig, see #5645

@fooey
Copy link

fooey commented Nov 1, 2018

Is there any IDE support on this for proper auto-complete etc?

Didn't see such practice on corporate projects before. But relative paths are very annoying indeed.

VS Code at least supports jsconfig.json which uses the exact same "paths" options as tsconfig to tell the editor how to resolve paths.

https://code.visualstudio.com/docs/languages/jsconfig

So far as I can tell, TypeScript does not support NODE_PATH. I was adopting TypeScript in an existing CRA app relying on NODE_PATH, and tsconfig's path options saved me from running into a big blocker while CRA's typescript support was in beta.

@tanduong's proposal for a filesystem link isn't OS independent, so now I'm stalled trying to figure out what to do with a project I over optimistically started porting over to typescript and is just completely broken ATM

edit: Using a collage of packages (rimraf, lnk-cli, globstar), I think I have a cross environment happy pre/post install setup that seems to be mostly working

scripts: {
		"preinstall": "yarn unlink-modules",
		"postinstall": "yarn link-modules",
		"unlink-modules": "rimraf node_modules/@",
		"link-modules": "globstar --node -- lnk \"./src/*\" \"./node_modules/@/\"",
		"relink-modules": "yarn unlink-modules && yarn link-modules",
		// ...
}

@gaearon
Copy link
Contributor

gaearon commented Jan 3, 2019

There is also another plausible alternative — we could embrace tsconfig.json / jsconfig.json, and make paths specified there work across the setup (Webpack/Jest). See #5645 (comment) for that.

@jakewies
Copy link

jakewies commented Jan 3, 2019

tsconfig.json/jsconfig.json specify a baseUrl too. This is one of the items on the list of things to do along with this issue. If CRA embraces the paths option, can it embrace the baseUrl as well?

@gaearon
Copy link
Contributor

gaearon commented Jan 3, 2019

Probably — let's discuss in #5645? I don't fully understand what this entails.

@Kepro
Copy link

Kepro commented Jan 8, 2019

what about... '@/': paths.appSrc + '/',
I'm using this for long time and without any issues... :)

@mzvast
Copy link

mzvast commented Jan 25, 2019

The simplest way to achieve this is to create node_modules/@ and link it as @gaearon suggested. You could do this by adding a postinstall script to your package.json. Like this:

{
  // ...
  "scripts": {
    "preinstall": "rm node_modules/@",
    "postinstall": "ln -s `pwd`/src node_modules/@",
    // ...
  },
  // ...
}

This script is so DANGEROUS!
It DELETE all my src folder!

@jjvainstein
Copy link

Messing around I just found one setting that works without craco for the absolute paths:

1 - Update .env file to NODE_PATH=./;

2 - Create one tsconfig.paths.json:

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

3 - Add this as your first entry in tsconfig.json:

"extends": "./tsconfig.paths.json",

Now everything should work fine, just reference the src/ folder in your imports instead of @.

YES, CRA will complain about the tsconfig.json absolute paths and stuff, but... VSCode seems to work pretty well with it and I think other IDEs will just as well.

EDIT: CRA complains but don't really remove the lines because it extends from the paths.json file so it can't modify it!

Hi! I tried this solution but is not working for me. This is my tsconfig.json:

{
"extends": "./tsconfig.paths.json",
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"isolatedModules": true,
"noEmit": true,
"jsx": "preserve",
"noUnusedLocals": true,
"noUnusedParameters": true,
"resolveJsonModule": true
},
"include": [
"src"
]
}

@jjenzz
Copy link

jjenzz commented Feb 15, 2019

My solution:

yarn add react-app-rewired --dev

Update package.json scripts:

"scripts": {
  "start": "react-app-rewired start",
  "build": "react-app-rewired build",
  "test": "react-app-rewired test --env=jsdom",
  "eject": "react-app-rewired eject"
},

Add config-overrides.js to project root:

const path = require('path');

module.exports = function override(config) {
  config.resolve = {
    ...config.resolve,
    alias: { '@': path.resolve(__dirname, 'src') },
  };

  return config;
};

Add jsconfig.paths.json/tsconfig.paths.json to project root:

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

Add the following to jsconfig.json / tsconfig.json:

"extends": "./tsconfig.paths.json", // or jsconfig.paths.json

CRA warns about compilerOptions.baseUrl and compilerOptions.paths not being supported but everything works as expected.

@Ruffeng
Copy link

Ruffeng commented Feb 16, 2019

@jjenzz your solution works smooth!

Hope the core team will provide a solution without other packages to achieve it ...

@jjvainstein
Copy link

My solution:

yarn add react-app-rewired --dev

Update package.json scripts:

"scripts": {
  "start": "react-app-rewired start",
  "build": "react-app-rewired build",
  "test": "react-app-rewired test --env=jsdom",
  "eject": "react-app-rewired eject"
},

Add config-overrides.js to project root:

const path = require('path');

module.exports = function override(config) {
  config.resolve = {
    ...config.resolve,
    alias: { '@': path.resolve(__dirname, 'src') },
  };

  return config;
};

Add jsconfig.paths.json/tsconfig.paths.json to project root:

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

Add the following to jsconfig.json / tsconfig.json:

"extends": "./tsconfig.paths.json", // or jsconfig.paths.json

CRA warns about compilerOptions.baseUrl and compilerOptions.paths not being supported but everything works as expected.

Thanks for your solution. One silly question, how I can use to solution to avoid using '@'? I mean, instead of doing `@/components/DummyComponent' I would like to do 'components/DummyComponent'.

@Kepro
Copy link

Kepro commented Feb 16, 2019

@jjvainstein rly? :) second comment in this thread

@jjvainstein
Copy link

@jjvainstein rly? :) second comment in this thread

@Kepro that simple solution doesn't work for me and many other people. I tried creating that .env file with it doesn't work. So for that reason I was thinking that with the solution using eact-app-rewired plus some modification I can achieve that.

jefffriesen added a commit to RadiantLabs/microgrid-appliance-analysis that referenced this issue Feb 20, 2019
@aramvr
Copy link

aramvr commented Feb 25, 2019

There appears to be some confusion in other threads so I'll repeat my comment from #5585:

Just to be clear — we do want to support absolute paths.

In particular, we want to:

I'm sorry for the frustration this is causing. We're not asking you to convert your code to use relative paths — but please wait for either of these two issues to resolve.

Is there any news?

@robertvansteen
Copy link
Contributor

@aramvr there is a work-in-progress PR (#6116) and I believe the intention is to ship it with 3.0 but there is still some work to do.

@mchurichi
Copy link

just wanted to add to @jjenzz solution that you also need to map @ to the right path if you want jest to resolve correctly... this worked for me

  // package.json 
  "jest": {
    "moduleNameMapper": {
      "@/(.*)": "<rootDir>/src/$1"
    }
  },

@rambabusaravanan
Copy link

Messing around I just found one setting that works without craco for the absolute paths:

1 - Update .env file to NODE_PATH=./;

2 - Create one tsconfig.paths.json:

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

3 - Add this as your first entry in tsconfig.json:

"extends": "./tsconfig.paths.json",

Now everything should work fine, just reference the src/ folder in your imports instead of @.

YES, CRA will complain about the tsconfig.json absolute paths and stuff, but... VSCode seems to work pretty well with it and I think other IDEs will just as well.

EDIT: CRA complains but don't really remove the lines because it extends from the paths.json file so it can't modify it!

This really works super awesome ..
Thanks @zaguiini ..

@ianschmitz
Copy link
Contributor

baseUrl is now supported in tsconfig.json and jsconfig.json. Check out #6475 and install our alpha release if you want to try it out!

@ianschmitz ianschmitz modified the milestones: 3.x, 3.0 Apr 19, 2019
MadratJerry added a commit to MadratJerry/Compilers-Playground that referenced this issue Apr 21, 2019
@nik-lampe
Copy link

nik-lampe commented Apr 23, 2019

This enables me to use absolute paths, but not aliases, right?

// edit
Nevermind, just read in #6656 that it's the case

@lock lock bot locked and limited conversation to collaborators Apr 28, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests