How is one supposed to compute where ../../../../../some/file
is!? Nobody likes doing folder math in their head!
...but when you have a large project already using relative imports, it's annoying to convert it. This tool should help you convince the rest of your team that it can be effortless. Note that there are some helpful hints at the bottom of this readme, since you will likely have to update your tooling.
absolutely -g './src/**/*.ts?(x)' -n '@' -r './src'
This will rename an import in a file ./src/components/clock/index.ts
like so:
- import { thing } from '../avatar';
+ import { thing } from '@app/components/avatar';
need an option for what to do with things that go out of the root probably error | ignore with warning
For extra info about glob syntax see here
Flag | Name | Description | Type | Info |
---|---|---|---|---|
-g | --glob | the glob used to enumerate files that should be edited | [string] | [required] |
-n | --root‑name | name the root of the project, ex: "@app" in "@app/components/..." | [string] | [required] |
-r | --root‑path | a path you want to be considered the root of the project | [string] | [default: the current path] |
-b | --fail-on-out-of-bounds | whether we should ignore file references above the specified root | [boolean] | [default: don't fail] |
After you convert all of your import statements in all of your files, you'll have to update all of your tooling to be aware of the absolute file references as well. Below is a running list of common tools and how to get them to respect absolute imports.
// jest.config.js
module.exports = {
...
moduleNameMapper: {
'^@app/(.*)$': '<rootDir>/src/$1',
},
};
If you use eslint-plugin-import, you'll want to tell it how to recognize your internal files:
// eslintrc.json
{
...
"settings": {
"import/internal-regex": "^(@app)/"
}
}
// tsconfig.json
{
"compilerOptions": {
...
"baseUrl": "./",
"paths": {
"@app/*": ["./src/*"]
}
}
}
Ok this is complicated, and I think it can be summed up by looking at the length of
this thread. Despite being able to interpret your
absolute paths as a type checker and compiler, when you actually build your project (export to js files), TypeScript
does not want to convert your absolute paths back to relative ones. That means that you can't simply do yarn tsc
and
then node ./dist/index.js
. Here are two workarounds.
If you want to run your app using ts-node, then you have to also use this plugin
to tell it how to interpret the tsconfig.json
"paths" defined locations: tsconfig-paths.
You can then run your application with something like:
ts-node -r tsconfig-paths/register src/index.ts
Check the "scripts.dev" section of package.json for an example.
If you want to compile your app to js, and then run it with node, however, you'll have to use tsc-alias to convert your absolute references back to relative ones in the compiled output.
tsc-alias
usesrootDir
fromtsconfig.json
to rewrite your paths.tsc-alias
had a bug on non-Windows machines at the time of writing this, you can check "scripts.postinstall" in package.json for an example of how to deal with that.
Check the "scripts.build" section of package.json for an example.
// webpack.js
const path = require('path');
module.exports = {
...
resolve: {
alias: {
'@app': path.resolve(__dirname, 'src'),
},
},
};
If you're using Typescript, see Typescript to familiarize yourself with that aspect. If you're using js, see here.
Note that there are some caveats with getting absolute paths to work with CRA. First, CRA supports absolute imports (as indicated in the link above), but not with a "paths" directive. You can follow the conversation here.
You'll see in that issue that there is in fact a workaround for this by using the "extends" directive in
tsconfig.json
, and using react-app-rewired to inject an adjustment
to the webpack config.
Here is a
blogpost that explains it more thoroughly.