Next-plugins: typescript with next & absolute imports breaks vs code integration

Created on 8 Apr 2018  路  9Comments  路  Source: vercel/next-plugins

_This may be a Code / Typescript issue, but wanted to post here in case anyone's solved it._

Has anyone been able to make absolute import paths work with next-typescript without losing VS Code module resolution?

Currently using absolute imports via babel-plugin-module-resolver, but whenever I call import Whatever from 'absolute/whatever', Code reports that the 'Cannot find the module' (relative imports work fine).

Project builds fine, but editor integration would be clutch.

Have tried:

  • setting path and baseUrl props in tsconfig.json
  • setting aliases via config.resolve.alias in next.config.js
  • using module-aliases in lieu of the babel plugin

But nothing seems to make the editor resolve paths correctly.

relevant versions

@zeit/next-typescript 0.1.1
next 5.1.0
typescript 2.9.0 (@next)
babel-plugin-module-resolver 3.0.0
VS Code 1.21.1

Most helpful comment

closing b/c i've somehow fixed this, though unclear on what did it.

for wayward googlers, here's my relevant .babelrc:

[
            "module-resolver",
            {
                "root": ["./"],
                "alias": {
                    "@components": "./components",
                    "@styles": "./styles",
                    "@utils": "./utils",
                    "@static": "./static",
                    "@higher-order-components": "./higher-order-components",
                    "@content": "./content",
                    "@src": "./src",
                    "@pages-code": "./pages-code",
                    "@pages": "./pages",
                    "@typings": "./typings",
                    "@server": "./server"
                }
            }
        ]

and in tsconfig.json:

  "baseUrl": ".",
        "paths": {
            "@components/*": ["./components/*"],
            "@utils/*": ["./utils/*"],
            "@styles/*": ["./styles/*"],
            "@static/*": ["./static/*"],
            "@higher-order-components/*": ["./higher-order-components/*"],
            "@content/*": ["./content/*"],
            "@src/*": ["./src/*"],
            "@pages-code/*": ["./pages-code/*"],
            "@pages/*": ["./pages/*"],
            "@server/*": ["./server/*"],
            "@typings/*": ["./typings/*"],
            "store/*": ["./src/store/*"]
        }

I am not sure why this wasn't working initially. I cleared any settings having to do with typescript & added tslint.json to the project, but afaik those shouldn't have affected IDE type checking. but, works like a charm now, so no complaints.

All 9 comments

I've created a repository and an SO question to accompany this issue

closing b/c i've somehow fixed this, though unclear on what did it.

for wayward googlers, here's my relevant .babelrc:

[
            "module-resolver",
            {
                "root": ["./"],
                "alias": {
                    "@components": "./components",
                    "@styles": "./styles",
                    "@utils": "./utils",
                    "@static": "./static",
                    "@higher-order-components": "./higher-order-components",
                    "@content": "./content",
                    "@src": "./src",
                    "@pages-code": "./pages-code",
                    "@pages": "./pages",
                    "@typings": "./typings",
                    "@server": "./server"
                }
            }
        ]

and in tsconfig.json:

  "baseUrl": ".",
        "paths": {
            "@components/*": ["./components/*"],
            "@utils/*": ["./utils/*"],
            "@styles/*": ["./styles/*"],
            "@static/*": ["./static/*"],
            "@higher-order-components/*": ["./higher-order-components/*"],
            "@content/*": ["./content/*"],
            "@src/*": ["./src/*"],
            "@pages-code/*": ["./pages-code/*"],
            "@pages/*": ["./pages/*"],
            "@server/*": ["./server/*"],
            "@typings/*": ["./typings/*"],
            "store/*": ["./src/store/*"]
        }

I am not sure why this wasn't working initially. I cleared any settings having to do with typescript & added tslint.json to the project, but afaik those shouldn't have affected IDE type checking. but, works like a charm now, so no complaints.

It seems baseUrl from tsconfig.json doesn't apply at all. Only module-resolver in .babelrc matters.

The baseUrl needs to be configured in next.config.js as well. Ideally @zeit/next-typescript would take care of that like I did below at config.resolve.modules.unshift(__dirname):

// next.config.js
//const withPreact = require('@zeit/next-preact')
const withTypescript = require('@zeit/next-typescript')
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin')

module.exports = /*withPreact*/(withTypescript({
  webpack(config, options) {
    // Do not run type checking twice:
    if (options.isServer) config.plugins.push(new ForkTsCheckerWebpackPlugin())

    config.resolve.modules.unshift(__dirname)

    return config
  },
}))

Should we reopen this issue to drive that forward?

Quick note for any Googlers for whom @brandonmp 's config doesn't work - don't forget that when you have a .babelrc specified, Nextjs's webpack config's resolver.extensions configuration _will not be respected_ by the plugin module-resolver.

You need to specify an extensions key value containing all the file extensions you want to resolve in the .babelrc module-resolver entry eg:

[
            "module-resolver",
            {
                "root": ["./"],
                "alias": {
                    "@components": "./components",
                    ...
                }
               "extensions": [ '.wasm', '.mjs', '.js', '.jsx', '.json', '.ts', '.tsx' ]
            }
        ]

When I upgraded to Next.js 9 and removed @zeit/next-typescript, the aliases stopped working. Adding this line to next.config.js made it working again (as seen in https://github.com/zeit/next-plugins/blob/master/packages/next-typescript/index.js#L31):

  webpack(config, options) {
      ...
      config.resolve.extensions.push('.ts', '.tsx')
      ...
  }

.babelrc

{
  "presets": ["next/babel"],
  "plugins": [
    [
      "module-resolver",
      {
        "root": ["./"],
        "alias": {
          "@": "./src/app",
          "@client": "./src/client",
          "@server": "./src/server"
        }
      }
    ]
  ]
}

Hie. I'm using nextjs 9.0.5, react 16.9.0, and babel-plugin-module-resolver 3.2.0... I've tried all the solutions above and I still cannot get it to work. Below are files

.babelrc

{
  "presets": ["next/babel"],
  "plugins": [
    [
      "styled-components",
      {
        "ssr": true,
        "displayName": true,
        "preprocess": false
      }
    ],
    [
      "module-resolver",
      {
        "root": ["./"],
        "alias": {
          "@src": "./src"
        },
        "extensions": [".js", ".jsx", ".tsx"]
      }
    ]
  ]
}

tsconfig.json

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": false,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve"
  },
  "exclude": ["node_modules"],
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
  "baseUrl": ".",
  "paths": {
    "@src/*": ["./src/*"]
  }
}

next.config.js

const withSass = require('@zeit/next-sass');

module.exports = withSass({
  sassLoaderOptions: {},
  webpack(config, options) {
    config.resolve.extensions.push('.ts', '.tsx');
    return config;
  },
});

What am I missing?

Solved it by adding the baseUrl and paths in the complierOptions like this

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": false,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "baseUrl": ".",
    "paths": {
       "@src/*": ["./src/*"]
    }
  },
  "exclude": ["node_modules"],
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
}

Next config file

const withPlugins = require('next-compose-plugins');


const nextConfig = {
  webpack: function (config) {
    config.module.rules.push({
        test: /\.(eot|woff|woff2|ttf|svg|png|jpg|gif)$/,
        use: {
        loader: 'url-loader',
          options: {
            limit: 100000,
            name: '[name].[ext]'
          }
        }
    })
    config.resolve.extensions.push('.ts', '.tsx')
    return config
  }
}
const exp = {
  experimental: {
    jsconfigPaths: true
  },
}

module.exports = nextConfig && exp; 

And tsconfig file

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": false,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve"
  },
  "include": ["next-env.d.ts", "./src/**/*.ts", "./src/**/*.tsx"],
  "exclude": [
    "node_modules"
  ],
  "baseUrl": ".",
  "paths": {
    "@components/*": ["./components/*"],
    "@styles/*": ["./styles/*"],
  }
}

Please help.

Was this page helpful?
0 / 5 - 0 ratings