Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Convert TypeScript tsconfig paths to webpack alias paths
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
}),
}
}
@chrisabrams

This comment has been minimized.

Copy link

chrisabrams commented Aug 14, 2018

I can confirm this worked for me!

@Paradoxia

This comment has been minimized.

Copy link

Paradoxia commented Sep 23, 2018

I use IntelliJ and it uses tsconfig.json to resolve stuff in the IDE. Your code works perfectly. Thank you very much :)

@eralvarez

This comment has been minimized.

Copy link

eralvarez commented Dec 16, 2018

this worked for me too, thx!

@bndynet

This comment has been minimized.

Copy link

bndynet commented Jan 7, 2019

Great! I look for it some days.

@ridaamirini

This comment has been minimized.

Copy link

ridaamirini commented Feb 20, 2019

+1

@adjiganoff

This comment has been minimized.

Copy link

adjiganoff commented May 27, 2019

Working, yay!

@arzyu

This comment has been minimized.

Copy link

arzyu commented Sep 10, 2019

@UberMouse

This comment has been minimized.

Copy link

UberMouse commented Oct 2, 2019

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

@nerdyman

This comment has been minimized.

Copy link
Owner Author

nerdyman commented Oct 3, 2019

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! 😄

@UberMouse

This comment has been minimized.

Copy link

UberMouse commented Oct 3, 2019

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.

@nicolad

This comment has been minimized.

Copy link

nicolad commented Feb 6, 2020

Works great, many thx @nerdyman

@phuctm97

This comment has been minimized.

Copy link

phuctm97 commented Apr 12, 2020

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];
    }));
};
@jraoult

This comment has been minimized.

Copy link

jraoult commented Apr 29, 2020

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.