This is my original webpack config file, consisting of two different configurations which both are used:
const ExtractTextPlugin = require('extract-text-webpack-plugin')
module.exports = [{
entry: __dirname + '/src/browser/main',
output: {
path: __dirname + '/dist/browser',
filename: 'bundle.js'
},
resolve: {
extensions: ['', '.js', '.ts'] // '' is needed to find modules like "jquery"
},
module: {
loaders: [
{
test: /\.ts$/,
loader: 'ts'
}
]
}
}, {
entry: ['babel-polyfill', __dirname + '/src/app/browser/app'],
output: {
path: __dirname + '/dist/app/browser',
filename: 'bundle.js'
},
resolve: {
root: ['./node_modules', './src'],
extensions: ['', '.js', '.ts'] // '' is needed to find modules like "jquery"
},
module: {
loaders: [
{
test: /\.ts$/,
loader: 'ts'
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract('style', 'css!sass')
}
]
},
plugins: [
new ExtractTextPlugin('bundle.css')
]
}]
Even though all my imports are accepted by, for instance, Atom (text editor with TypeScript plugin), currently only the following alternative works:
const ExtractTextPlugin = require('extract-text-webpack-plugin')
module.exports = [{
entry: __dirname + '/src/browser/main',
output: {
path: __dirname + '/dist/browser',
filename: 'bundle.js'
},
resolve: {
extensions: ['', '.js', '.ts'] // '' is needed to find modules like "jquery"
},
module: {
loaders: [
{
test: /\.ts$/,
loader: 'ts'
}
]
}
}, {
entry: ['babel-polyfill', __dirname + '/src/app/browser/app'],
output: {
path: __dirname + '/dist/app/browser',
filename: 'bundle.js'
},
resolve: {
root: ['./node_modules', './src'],
extensions: ['', '.js', '.ts'] // '' is needed to find modules like "jquery"
},
module: {
loaders: [
{
test: /\.ts$/,
loader: require.resolve('ts-loader')
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract('style', 'css!sass')
}
]
},
plugins: [
new ExtractTextPlugin('bundle.css')
]
}]
(note the require.resolve('ts-loader')
)
As you can see, in the first config 'ts'
is still present (since it still works), while in the second one I needed to replace it by require.resolve('ts-loader')
. Now I try to find the reason for this requirement. I can remember that I was forced to use require.resolve
in other projects as well, but I never was aware of the reason.
The inconspicuous line of code which makes the difference (second config):
import * as dateTime from 'lib/date-time/date-time'
If I comment it, it works again using 'ts'
.
On my file system, the path lib/date-time/date-time.ts is located directly below ./src (which is mentioned in the resolve/root array). And it is not the first import depending on the resolve/root array.
Webpack output with error message:
> webpack
ts-loader: Using [email protected] and /.../src/app/browser/tsconfig.json
ts-loader: Using [email protected] and /.../src/browser/tsconfig.json
Hash: 5058e7029f1c0243a269161aa4ddda242a3d33a0
Version: webpack 1.14.0
Child
Hash: 5058e7029f1c0243a269
Version: webpack 1.14.0
Time: 3165ms
Asset Size Chunks Chunk Names
bundle.js 283 kB 0 [emitted] main
+ 4 hidden modules
Child
Hash: 161aa4ddda242a3d33a0
Version: webpack 1.14.0
Time: 3670ms
Asset Size Chunks Chunk Names
bundle.js 617 kB 0 [emitted] main
bundle.css 25 kB 0 [emitted] main
[0] multi main 40 bytes {0} [built]
+ 329 hidden modules
ERROR in Cannot find module './node_modules/ts-loader/index.js'
@ ./src/records/departure/departure.ts 2:15-49
Child extract-text-webpack-plugin:
+ 2 hidden modules
Child extract-text-webpack-plugin:
+ 2 hidden modules
Child extract-text-webpack-plugin:
+ 2 hidden modules
Child extract-text-webpack-plugin:
+ 2 hidden modules
Use
root: path.resolve('./src'),
Because the documentation on resolve.root states:
The directory (absolute path) that contains your modules. May also be an array of directories. This setting should be used to add individual directories to the search path.
It must be an absolute path! Don’t pass something like ./app/modules.
In addition, since resolve.modulesDirectories already has node_modules
as the defaults, we can omit it from resolve.root
. In other words, we don't need root: [path.resolve('./node_modules'), path.resolve('./src'),]
I'm not a Webpack developer but my hunch is that at every import, Webpack will change the current directory to that file so that it can resolve relative imports. During the import of the date-time
module from ./src/records/departure/departure.ts
, it will now use the directory ./src/records/departure
and at that time it'll also need to use a loader, but because you've set the root using a relative path (./node_modules
), it will look in ./src/records/departure/node_modules
instead. Hence giving you this error.
The above is not exactly correct but still kind of apply but here's the link to the docs: module.loaders
IMPORTANT: The loaders here are resolved relative to the resource which they are applied to. This means they are not resolved relative to the configuration file. If you have loaders installed from npm and your node_modules folder is not in a parent folder of all source files, webpack cannot find the loader. You need to add the node_modules folder as an absolute path to the resolveLoader.root option. (resolveLoader: { root: path.join(__dirname, "node_modules") })