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?
Place NODE_PATH=src
into your .env
file and proceed to import components/Hello
.
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.
We'll need to make sure it works with webpack (obviously), but also Jest/Flow/ESLint(?).
Can we just create node_modules/@
and link it?
@gaearon Why does monorepos affect @
support?
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.
By the way, our individual packages in monorepo, if we don't want to publish it to NPM, how should it be named?
Doesn't matter.
@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.
@gaearon any update on this?
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/@",
// ...
},
// ...
}
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.
@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.
@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.
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.
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.
@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.
@z-ax
For js file,we can write a fake webpack config, see https://github.com/umijs/umi/issues/1109
For ts file, we can use paths in tsconfig, see https://github.com/facebook/create-react-app/issues/5645
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",
// ...
}
@fooey your prescript
doesn't work for the first installing without node_modules
if rimraf
doesn't exist in global packages
@fooey your
prescript
doesn't work for the first installing withoutnode_modules
ifrimraf
doesn't exist in global packages
@orlov-vo good catch. I always have rimraf installed globally and didn't think of that. Maybe getting rid of the preinstall and having the postinstall do the combined relink would be fine. I'll have to take another stab at it tonight.
I have just discovered that this script is very dangerous if you are using Yarn:
"postinstall": "ln -s `pwd`/src node_modules/@",
Yarn thinks it owns node_modules
and can clear it out at will, for example when upgrading a package. That in itself isn't fatal, as it's easy enough to run the postinstall
again. However, Yarn thinks any node_modules
directory starting with @
is a scope and it carefully recurses one level down to delete any content. The result: goodbye src
directory. :-( The issue is described here:
https://github.com/yarnpkg/yarn/issues/5709
The cross-platform alternative above doesn't seem to suffer from the same problem:
"link-modules": "globstar --node -- lnk \"./src/*\" \"./node_modules/@/\"",
...as it creates multiple links one level below node_modules/@
.
For those, who are still looking for a solution have a look at this small repo. It supports create-react-app v2.x, TypeScript v3.x, and absolute path imports.
This is achieved by using craco and extending the tsconfig.json
file.
This is very disappointing. I am using CRA + TypeScript for almost a year (using react-scripts-ts
). I was excited that CRA now supports TS out of the box but this is a blocker for me. I think CRA should stay a scaffolding tool rather than some sort of overlooking entity, forcing me to setup my project in a certain way. I don't want to eject or use another tool for config overriding just to do a basic setup.
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!
@zaguiini Yes, it works for absolute path. Sadly, this doesn't solve the alias problem.
I'm seriously thinking about ejecting. Right at the point, where I started to think that CRA is becoming less opinionated and more open to configuration, this feels like a knife in the back.
There appears to be some confusion in other threads so I'll repeat my comment from https://github.com/facebook/create-react-app/issues/5585:
Just to be clear — we do want to support absolute paths.
In particular, we want to:
NODE_PATH
work for TS. (https://github.com/facebook/create-react-app/issues/5692)@
alias work by default for everyone — both in JS and TS. (this issue)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.
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 https://github.com/facebook/create-react-app/issues/5645#issuecomment-451170386 for that.
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?
Probably — let's discuss in https://github.com/facebook/create-react-app/issues/5645? I don't fully understand what this entails.
what about... '@/': paths.appSrc + '/',
I'm using this for long time and without any issues... :)
The simplest way to achieve this is to create
node_modules/@
and link it as @gaearon suggested. You could do this by adding apostinstall
script to yourpackage.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!
Messing around I just found one setting that works without
craco
for the absolute paths:1 - Update
.env
file toNODE_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"
]
}
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.
@jjenzz your solution works smooth!
Hope the core team will provide a solution without other packages to achieve it ...
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
andcompilerOptions.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'.
@jjvainstein rly? :) second comment in this thread
@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.
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:
- Make
NODE_PATH
work for TS. (#5692)- Make
@
alias work by default for everyone — both in JS and TS. (this issue)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?
@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.
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"
}
},
Messing around I just found one setting that works without
craco
for the absolute paths:1 - Update
.env
file toNODE_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 ..
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!
This enables me to use absolute paths, but not aliases, right?
// edit
Nevermind, just read in https://github.com/facebook/create-react-app/pull/6656 that it's the case
Most helpful comment
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.