Webpack 不能总是解析 TS 加载器

Webpack cannot always resolve the TS loader

这是我原来的 webpack 配置文件,由两个不同的配置组成,两者都被使用:

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')
  ]
}]

即使我的所有导入都被接受,例如,Atom(带有 TypeScript 插件的文本编辑器),目前只有以下替代作品:

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')
  ]
}]

(注意 require.resolve('ts-loader')

如您所见,在第一个配置中 'ts' 仍然存在(因为它仍然有效),而在第二个配置中我需要将其替换为 require.resolve('ts-loader')。现在我试图找到这个要求的原因。我记得我在其他项目中也被迫使用require.resolve,但我一直不知道原因。

造成差异的不显眼的代码行(第二个配置):

import * as dateTime from 'lib/date-time/date-time'

如果我评论它,它会再次使用 'ts'

在我的文件系统上,路径 lib/date-time/date-time.ts 位于 ./src 的正下方(在 resolve/root 数组中提到)。这不是第一个依赖于 resolve/root 数组的导入。

带有错误消息的 Webpack 输出:

> webpack

ts-loader: Using typescript@2.1.4 and /.../src/app/browser/tsconfig.json
ts-loader: Using typescript@2.1.4 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

使用

root: path.resolve('./src'),

因为 documentation on resolve.root 声明:

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.

此外,由于resolve.modulesDirectories已经有node_modules作为默认值,我们可以从resolve.root中省略它。换句话说,我们不需要 root: [path.resolve('./node_modules'), path.resolve('./src'),]

我不是 Webpack 开发人员,但我的直觉是在每次导入时,Webpack 都会将当前目录更改为该文件,以便它可以解析相对导入。在从 ./src/records/departure/departure.ts 导入 date-time 模块的过程中,它现在将使用目录 ./src/records/departure,那时它还需要使用加载器,但是因为您已经设置了root 使用相对路径 (./node_modules),它将在 ./src/records/departure/node_modules 中查找。因此给你这个错误。

以上内容并不完全正确,但仍然适用,但这里是文档的 link: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") })