JeffreyHammansson JeffreyHammansson - 1 month ago 15
Javascript Question

Cannot find module with Webpack, Typescript, custom module directory

What I'm trying to do



I am wrote a dummy module my-component which essentially exports a single class Something. I placed it in app/modules/. Now I am tying to access it using the import Syntax from app/app.js:

import { Something } from 'my-component';


Expectation: With my current Webpack configuration (below) I would expect this to work.

Actual: This throws the error:

ERROR in [default] /<project_dir>/app/app.ts:1:26
Cannot find module 'my-component/Something'.


What I tried to fix it



I know the module in itself is defined correctly, because


  1. I can import it using a relative path:
    import { Something } from './my-component'

  2. I can import it as-is, if I move the module to
    node_modules/my-component
    .



The only combination that fails is importing it without a relative path from my modules/ directory. So I think the issue might be my Webpack configuration.

Setup Details



As you can see below, I have two directories listed as resolve.root:


  • project_dir/app

  • project_dir/node_modules



It seems to manage to resolve from
node_modules
, just not from
app
.

Project layout

Webpack
project_dir/
├── app/ context, resolve.root
│ ├── app.ts
│ └── my-component/
│ ├── index.ts
│ └── Something.ts
├── webpack.config.js
├── node_modules/ resolve.root
│ ├── ...
│ ├── ...
│ └── ...
└── dist/
└── ...


app/app.ts

import { Something } from 'my-component/Something';


app/my-component/index.ts

export { Something } from './Something'


app/my-component/Something.ts

class Something {
}

export { Something };


webpack.config.js

var path = require('path'),
ROOT = path.resolve(__dirname, '.');

module.exports = {
context: path.resolve(ROOT, 'app'),
entry: 'app.ts',
output: {
path: path.resolve(ROOT, 'dist'),
filename: '[name]-[hash].js'
},
module: {
loaders: [
{ test: /\.ts$/, loader: 'awesome-typescript' }
]
},
resolve: {
root: [
path.resolve(__dirname, 'app'),
path.resolve(__dirname, 'node_modules')
],
extensions: [
'', '.ts', '.js'
]
}
};


EDIT
Fixed the project layout.

Answer

I found an easier solution than the previously accepted one:

In your typescript configuration, set the baseUrl in the compilerOptions:

tsconfig.json:

{
  "compilerOptions": {
    "baseUrl": "./app",
    ...
  },
  ...
}

Explanation:

Webpack and Typescript use node module resolution by default, which is fine. When setting up custom module folders though, you need to configure them in both the Webpack and the Typescript config. Changes to the Webpack module resolution config are not propagated to the Typescript compiler.

Comments