-
-
Save nerdyman/2f97b24ab826623bff9202750013f99e to your computer and use it in GitHub Desktop.
const { resolve } = require('path'); | |
/** | |
* Resolve tsconfig.json paths to Webpack aliases | |
* @param {string} tsconfigPath - Path to tsconfig | |
* @param {string} webpackConfigBasePath - Path from tsconfig to Webpack config to create absolute aliases | |
* @return {object} - Webpack alias config | |
*/ | |
function resolveTsconfigPathsToAlias({ | |
tsconfigPath = './tsconfig.json', | |
webpackConfigBasePath = __dirname, | |
} = {}) { | |
const { paths } = require(tsconfigPath).compilerOptions; | |
const aliases = {}; | |
Object.keys(paths).forEach((item) => { | |
const key = item.replace('/*', ''); | |
const value = resolve(webpackConfigBasePath, paths[item][0].replace('/*', '').replace('*', '')); | |
aliases[key] = value; | |
}); | |
return aliases; | |
} | |
module.exports = resolveTsconfigPathsToAlias; |
{ | |
"compilerOptions": { | |
"module": "commonjs", | |
"moduleResolution": "node", | |
"outDir": "./dist", | |
"allowJs": true, | |
"target": "es6", | |
"jsx": "react", | |
"sourceMap": true, | |
"noImplicitAny": true, | |
"strictNullChecks": true, | |
"baseUrl": "./", | |
"lib": [ | |
"DOM", | |
"ES5", | |
"ES6", | |
"es2017.object" | |
], | |
"paths": { | |
"Root/*": ["src/*"], | |
"Components/*": ["src/components/*"], | |
"Data/*": ["src/data/*"], | |
} | |
}, |
import Banner from 'Components/banner'; |
// add paths to webpack | |
const resolveTsconfigPathsToAlias = require('./resolve-tsconfig-path-to-webpack-alias'); | |
module.exports = { | |
// ... | |
resolve: { | |
// ... | |
alias: resolveTsconfigPathsToAlias({ | |
tsconfigPath: '../tsconfig.json', // Using custom path | |
webpackConfigBasePath: '../', // Using custom path | |
}), | |
} | |
} |
I use IntelliJ and it uses tsconfig.json to resolve stuff in the IDE. Your code works perfectly. Thank you very much :)
this worked for me too, thx!
Great! I look for it some days.
+1
Working, yay!
Made it into a package:
One problem I encountered, if you have an alias such as "root" which is aliased to the root of your source code. Set up like this
"root": ["*"]
Then it will incorrectly be expanded to ${webpackConfigBasePath}/*
instead of ${webpackConfigBasePath}
. This can be fixed by appending .replace("*", "")
to line 19
Is that a common use case UberMouse? I haven't seen root aliased by *
before, would using *
not include node_modules
too?
Usually, I use "Root/*": ["src/*"]
.
Also, glad people found this useful! 😄
It's probably not, just a quirk of how ours are setup (our path prefixes point directly to src/ in your example, not to the folder containing src).
Definitely useful, I used to maintain three mappings. One for tsconfig, one for jest and one for Webpack. I set this up yesterday and a Jest equivalent the other day so now I just need to maintain one set of mapping which is great.
Works great, many thx @nerdyman
Great idea! Thank you!
However, there're couple of things can be improved. I wrote my modification which helps improve:
- Handle and ignore cases in which
paths.values
is empty. - Cleaner code as it's written in a more declarative manner.
- More performant as it doesn't alter the object, instead it returns a constant which can be cached by either Node.js or Webpack.
See https://gist.github.com/phuctm97/7470a3b981fd80a501b4047e1e99a9f4 for more details or appreciation. Thank you!
const path = require('path');
/**
* Helper function infers Webpack aliases from tsconfig.json compilerOptions.baseUrl and
* compilerOptions.paths.
*
* @param {string} tsconfigPath - Path to tsconfig.json (Can be either relative or absolute path).
* @return {object} An object representing corresponding Webpack alias.
*/
module.exports = (tsconfigPath = './tsconfig.json') => {
const tsconfig = require(tsconfigPath);
const { paths, baseUrl } = tsconfig.compilerOptions;
return Object.fromEntries(Object.entries(paths)
.filter(([, pathValues]) => pathValues.length > 0)
.map(([pathKey, pathValues]) => {
const key = pathKey.replace('/*', '');
const value = path.resolve(path.dirname(tsconfigPath),
baseUrl, pathValues[0].replace('/*', ''));
return [key, value];
}));
};
Not sure you folks are aware of this https://www.npmjs.com/package/tsconfig-paths-webpack-plugin. May be it can help someone in the future.
At lease tsconfig-paths-webpack-plugin doesn't work with webpack:^5:11.1 as it seems now.
I really appreciate this @nerdyman
Not sure you folks are aware of this https://www.npmjs.com/package/tsconfig-paths-webpack-plugin. May be it can help someone in the future.
this plugins replaces the context of resolve.alias object so u will not be able to add any custom aliases to your webpack configuration, and will be left in hands with only the one mentioned in tsconfig - what is kinda .... complicated )
@MisaGu Have you heard of the spread operator?
// add paths to webpack
const resolveTsconfigPathsToAlias = require('./resolve-tsconfig-path-to-webpack-alias');
module.exports = {
// ...
resolve: {
// ...
alias: {
...resolveTsconfigPathsToAlias({
tsconfigPath: '../tsconfig.json', // Using custom path
webpackConfigBasePath: '../', // Using custom path
}),
Utilities: path.resolve(__dirname, 'src/utilities/'),
Templates: path.resolve(__dirname, 'src/templates/'),
}
}
}
@nerdyman It seems to me that this gist is missing the baseUrl
. I had to edit to this to get it working.
const { resolve } = require('path');
/**
* Resolve tsconfig.json paths to Webpack aliases
* @param {string} tsconfigPath - Path to tsconfig
* @param {string} webpackConfigBasePath - Path from tsconfig to Webpack config to create absolute aliases
* @return {object} - Webpack alias config
*/
function resolveTsconfigPathsToAlias({
tsconfigPath = './tsconfig.json',
webpackConfigBasePath = __dirname,
} = {}) {
const { paths, baseUrl } = require(tsconfigPath).compilerOptions;
const aliases = {};
Object.keys(paths).forEach((item) => {
const key = item.replace('/*', '');
const value = resolve(webpackConfigBasePath, baseUrl, paths[item][0].replace('/*', '').replace('*', ''));
aliases[key] = value;
});
return aliases;
}
module.exports = resolveTsconfigPathsToAlias;
there is an issue in this configuration, because the first matched alias is selected instead of the most specific one
@its-dibo moved more specific first in the tsconfig paths as a workaround...
I can confirm this worked for me!