Gatsby: Support for TypeScripts 'paths' option

Created on 4 Mar 2018  路  16Comments  路  Source: gatsbyjs/gatsby

Description

I'm trying to implement alias for importing Typescript modules from root of my project. According to typescripts docs it can be done by adding following configuration to 'tsconfig.json' file

    "baseUrl": "./src",
    "paths": {
      "@components": ["/components"]

Then from anywhere ts/tsx file: import { MyComponent } from '@components/MyComponent'.

Environment

Gatsby version: 1.1.40
Node.js version: v8.9.4
Operating System: macOS 10.13.3

Actual result

Module @components/MyComponent not found. The Same behavior has been fixed with create-react-app: issue 203.

Expected behavior

Typescript should find my module.

Steps to reproduce

1. gatsby new website-gatsby-clean https://github.com/haysclark/gatsby-starter-typescript

2. add Typescript paths config to tsconfig.json

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

3. create src/components/MyComponent.tsx

const MyComponent = () => <h1>Hello</h1>
export default MyComponent

4. import MyComponent into src/pages/index.tsx

...
import MyComponent from '@components/MyComponent'
...
public render() {
    return <MyComponent />
}
...
help wanted

Most helpful comment

I was struggling to make this work, not realizing the example by @t49tran was using the v1 gatsby config API. For the record, if anyone arrives here looking for a solution using v2, here's the summary:

You don't need the tsconfig-paths-webpack-plugin, and I'm not sure how it relates to be honest.

In tsconfig I have this:

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

So in code you can write things like import { widths } from '@src/styles/variables'

Then to make the build succeed, add to gatsby-node.js:

exports.onCreateWebpackConfig = function({ actions }) {
  actions.setWebpackConfig({
    resolve: {
      alias: {
        '@src': path.resolve(__dirname, 'src')
      }
    }
  })
}

I personally like the @ prefix, because it makes it very clear that you're not importing from node_modules.

All 16 comments

It looks like you'd need to use the tsconfig-paths-webpack-plugin to enable this setup? I think you could do this using Gatsby's webpack hooks - see the docs page on custom webpack configs.

Note that Gatsby v1 uses webpack version one. Gatsby v2 will upgrade to a newer release of webpack.

@m-allanson thanks. Not sure how to make it work. I've tried that:

yarn add --dev tsconfig-paths-webpack-plugin

then

const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');

function TsconfigPathsContructor() {
  return new TsconfigPathsPlugin();
}

exports.modifyWebpackConfig = ({ config, stage }) => {
  if (stage == "develop" || stage == "build-javascript") {
    const opts = [{
      configFile: "./tsconfig.json"
    }];

    config.plugin("ts-config-paths-plugin", TsconfigPathsContructor, opts);
  }

  return config;
};

Not a complete solution, but I got rid of the TS error (in VS Code) with this in tsconfig.json:

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

Though gatsby/webpack still throws an error that the dependency is not found when I import a module using path defined in tsconfig.json. Not sure how to get this working!

@m-allanson any idea how to make it work?

I resolved the problem after having a look here #484. Basically, what I do is add an alias option to webpack.resolve in gatsby-node.js:

exports.modifyWebpackConfig = function({ config, env }) {
  config.merge({
    resolve: {
      alias: {
        `[ALIAS]`: [PATH_TO_ALIAS]
      }
    }
  });
  return config;
};

Thanks @t49tran. It'd be nice for gatsby-plugin-typescript to support this automatically. It could read tsconfig.json and automatically apply the aliases to webpack.

I think it makes complete sense @m-allanson, I will have a look into gatsby-plugin-typescript and see if I can do something.

Due to the high volume of issues, we're closing out older ones without recent activity. Please open a new issue if you need help!

I was struggling to make this work, not realizing the example by @t49tran was using the v1 gatsby config API. For the record, if anyone arrives here looking for a solution using v2, here's the summary:

You don't need the tsconfig-paths-webpack-plugin, and I'm not sure how it relates to be honest.

In tsconfig I have this:

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

So in code you can write things like import { widths } from '@src/styles/variables'

Then to make the build succeed, add to gatsby-node.js:

exports.onCreateWebpackConfig = function({ actions }) {
  actions.setWebpackConfig({
    resolve: {
      alias: {
        '@src': path.resolve(__dirname, 'src')
      }
    }
  })
}

I personally like the @ prefix, because it makes it very clear that you're not importing from node_modules.

I personally like the @ prefix, because it makes it very clear that you're not importing from node_modules.

This could also indicate a @scoped package located in ./node_modules/, although I didn't check if @src scope is available there. In this context, maybe using # instead of @ could help better distinguish between scoped-packages and internal/local packages resolved via paths.

Thanks for the exports.onCreateWebpackConfig info :-).

@jbmusso You're right, a different character would probably be better. I realized that shortly after :) But I haven't ran into any problems yet. The prefixes I'm using are so generic they are not very likely to clash with a library namespace (src, components, modules, utils, config, ...)

@0x80 Forgetting this line at the top of the gatsby-node.js file

var path = require('path');

Here's a quick starter project for anyone interested:

https://github.com/martinmckenna/gatsby-typescript-starter

Has anybody been successful at getting this working while also using TSLint? I have followed what @0x08's recommendedation but I keep running into a "not found" error:

Cannot find module '@src/UI-Kit'.

I'll also run in to other lint errors (like no-submodule-imports) but those are easily fixed by explicitly allowing @src in my tslint.json.

If anyone's still struggling with this issue, I was able to get it working pretty easily using tsconfig-paths-webpack-plugin.

tsconfig.json

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

gatsby-node.js

const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin')

exports.onCreateWebpackConfig = ({ actions }) => {
  actions.setWebpackConfig({
    resolve: {
      plugins: [new TsconfigPathsPlugin()],
    },
  })
}

And then you can import like this

import Foo from '@components/foo'

If anyone's still struggling with this issue, I was able to get it working pretty easily using tsconfig-paths-webpack-plugin.

tsconfig.json

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

gatsby-node.js

const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin')

exports.onCreateWebpackConfig = ({ actions }) => {
  actions.setWebpackConfig({
    resolve: {
      plugins: [new TsconfigPathsPlugin()],
    },
  })
}

And then you can import like this

import Foo from '@components/foo'

This certainly works for Gatsby v2.

How to remove the warning from VSCode? Did anyone found a solution to this?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ferMartz picture ferMartz  路  3Comments

KyleAMathews picture KyleAMathews  路  3Comments

brandonmp picture brandonmp  路  3Comments

3CordGuy picture 3CordGuy  路  3Comments

ghost picture ghost  路  3Comments