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'.
I know the module in itself is defined correctly, because
import { Something } from './my-component'
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.
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.
Cannot find module
If you experience this issue with dynamic module loading using ESNEXT
,
you have to add "moduleResolution": "node"
to your tsconfig.json
.
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.
Ok. I created a replica of your project structure. It seems that the case is that the import statement does not behave the same as the require, AND, webpack resolve.root config works as expected with it.
For the modules, change your import statements to require like this:
app.ts
// Define require function for TypeScript to know that it
// will exist at runtime
declare function require(name:string);
// Require your module
var Something = require('my-component/Something');
// var myComponent = require('my-component');
my-component/Something.ts
// Export something (used a function to test)
export function Something() {
console.log("Hello");
}
my-component/index.ts
// Definition of require function as mentioned before
declare function require(name:string);
// Passing other modules
var exportedModules = {
Something: require("my-component/Something")
};
export default exportedModules;
Like this, it will work without problems and resolve with the module names as you defined in Webpack. Unfortunately, I couldn't achieve it with the import.
I pushed the solution to a repository. Check it out if you need!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With