Webpack 不适用于 Typescript 别名

Webpack is not working with Typescript aliases

我有这个 webpack.config.js:

{
    target: 'node',
    mode: 'production',
    // devtool: 'source-map',
    entry: {
        index: './source/lib/index.ts',
    },
    resolve: {
        extensions: ['.ts', '.js']
    },
    module: {
        rules: [
            {
                test: /\.ts$/,
                include: path.resolve(__dirname, 'source'),
                use: [
                    {
                        loader: 'ts-loader',
                        options: {
                            compiler: 'ttypescript'
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        new BundleDeclarationsWebpackPlugin({
            entry: "./source/lib/index.ts",
            outFile: "./index.d.ts"
        })
    ],
    externals: [nodeExternals()],
    output: {
        path: path.resolve(__dirname, 'bundled', 'lib'),
        filename: 'index.js',
        library: 'mongo-cleaner',
        libraryTarget: 'umd',
        globalObject: 'this',
        umdNamedDefine: true,
    }
}

因为你可以看到我将一个库与 webpack 捆绑在一起,将 node_modules 保持为外部。

还有这个tsconfig.json

{
    "compilerOptions": {
        "moduleResolution": "node",
        "module": "commonjs",
        "target": "ES5",
        "strictNullChecks": true,
        "lib": [
            "ES2021"
        ],
        "outDir": "../dist",
        "sourceMap": true,
        "declaration": true,
        "baseUrl": ".",
        "paths": {
            "@/*": [
                "./lib/*"
            ],
            "@lib/*": [
                "./lib/*"
            ],
            "@bin/*": [
                "./bin/*"
            ]
        }
    },
    "plugins": [
        {
            "transform": "typescript-transform-paths"
        },
        {
            "transform": "typescript-transform-paths",
            "afterDeclarations": true
        }
    ],
    "include": [
        "lib",
        "bin"
    ]
}

当我执行 tsc -p source 时一切正常,即使我的需求中有“@”路径

但是当我用 webpack 做同样的事情时,我得到了这些错误:

ERROR in ./source/lib/index.ts 50:16-42
Module not found: Error: Can't resolve '@/utils/cleaner' in '/home/euber/Github/mongo-cleaner/source/lib'

ERROR in ./source/lib/index.ts 51:19-48
Module not found: Error: Can't resolve '@/utils/askConfirm' in '/home/euber/Github/mongo-cleaner/source/lib'

ERROR in ./source/lib/index.ts 52:16-42
Module not found: Error: Can't resolve '@/utils/options' in '/home/euber/Github/mongo-cleaner/source/lib'

ERROR in ./source/lib/index.ts 53:13-45
Module not found: Error: Can't resolve '@/interfaces/exported' in '/home/euber/Github/mongo-cleaner/source/lib'

ERROR in ./source/lib/index.ts 54:13-32
Module not found: Error: Can't resolve '@/errors' in '/home/euber/Github/mongo-cleaner/source/lib'

webpack 怎么可能忽略@?

要获得更多信息并能够重现它,只需查看 this repo

更新:

我也试过这个答案,但它不起作用:

webpack.config.js

alias: {
            '@': path.resolve(__dirname, 'lib'),
            '@lib': path.resolve(__dirname, 'lib'),
            '@bin': path.resolve(__dirname, 'bin')
        }

错误:

ERROR in ./source/lib/index.ts 50:16-42
Module not found: Error: Can't resolve '@/utils/cleaner' in '/home/euber/Github/mongo-cleaner/source/lib'

ERROR in ./source/lib/index.ts 51:19-48
Module not found: Error: Can't resolve '@/utils/askConfirm' in '/home/euber/Github/mongo-cleaner/source/lib'

ERROR in ./source/lib/index.ts 52:16-42
Module not found: Error: Can't resolve '@/utils/options' in '/home/euber/Github/mongo-cleaner/source/lib'

ERROR in ./source/lib/index.ts 53:13-45
Module not found: Error: Can't resolve '@/interfaces/exported' in '/home/euber/Github/mongo-cleaner/source/lib'

ERROR in ./source/lib/index.ts 54:13-32
Module not found: Error: Can't resolve '@/errors' in '/home/euber/Github/mongo-cleaner/source/lib'

您已经为 typescript 编译器指定了路径别名,但您还需要指定 aliases for webpack 因为 webpack 以自己的方式解析模块。

因此您需要更新 webpack 配置,如下例所示:

{
...
  resolve: {
    extensions: ['.ts', '.js'],
    alias: {
      '@': path.resolve(__dirname, 'source/lib'),
      '@lib': path.resolve(__dirname, 'source/lib'),
      '@bin': path.resolve(__dirname, 'source/bin')
    }
  }
...
}

@Mikhail Sereniti 的回答是可行的,但是一个模块允许自动处理这个问题。

我添加了这个:

plugins: [new TsconfigPathsPlugin({
  configFile: './source/tsconfig.json',
  extensions: ['.ts', '.js']
})]

它奏效了。

完整代码:

const path = require('path');
const webpack = require('webpack');
const nodeExternals = require('webpack-node-externals');
const BundleDeclarationsWebpackPlugin = require('bundle-declarations-webpack-plugin');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');


const libConfig = {
    target: 'node',
    mode: 'production',
    // devtool: 'source-map',
    entry: {
        index: './source/lib/index.ts',
    },
    resolve: {
        extensions: ['.ts', '.js'],
        plugins: [new TsconfigPathsPlugin({
            configFile: './source/tsconfig.json',
            extensions: ['.ts', '.js']
        })]
    },
    module: {
        rules: [
            {
                test: /\.ts$/,
                include: path.resolve(__dirname, 'source'),
                use: [
                    {
                        loader: 'ts-loader',
                        options: {
                            compiler: 'ttypescript'
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        new BundleDeclarationsWebpackPlugin({
            entry: "./source/lib/index.ts",
            outFile: "./index.d.ts"
        })
    ],
    externals: [nodeExternals()],
    output: {
        path: path.resolve(__dirname, 'bundled', 'lib'),
        filename: 'index.js',
        library: 'mongo-cleaner',
        libraryTarget: 'umd',
        globalObject: 'this',
        umdNamedDefine: true,
    }
};

const binConfig = {
    target: 'node',
    mode: 'production',
    // devtool: 'source-map',
    entry: {
        index: './source/bin/index.ts',
    },
    resolve: {
        extensions: ['.ts', '.js'],
        plugins: [new TsconfigPathsPlugin({
            configFile: './source/tsconfig.json',
            extensions: ['.ts', '.js']
        })]
    },
    plugins: [
        new webpack.BannerPlugin({ banner: '#!/usr/bin/env node', raw: true })
    ],
    module: {
        rules: [
            {
                test: /\.ts?$/,
                include: path.resolve(__dirname, 'source'),
                use: [
                    {
                        loader: 'ts-loader',
                        options: {
                            compiler: 'ttypescript'
                        }
                    },
                    {
                        loader: 'shebang-loader'
                    }
                ]
            }
        ]
    },
    externals: [{
        '../lib/index': {
            amd: '../lib/index',
            root: 'mongo-cleaner',
            commonjs: '../lib/index',
            commonjs2: '../lib/index'
        },
    }, nodeExternals()],
    output: {
        path: path.resolve(__dirname, 'bundled', 'bin'),
        filename: 'index.js',
        library: 'mongo-cleaner',
        libraryTarget: 'umd',
        globalObject: 'this',
        umdNamedDefine: true,
    }
};

module.exports = [
    libConfig,
    binConfig
];

编辑:

我还发现了另一个错误。我将 ttypescript 用于类似目的,但“插件”关键字应该在编译器选项中。

所以,即使没有 TsconfigPathsPlugin 东西,通过像这样更改 tsconfig.json 问题也解决了:

{
    "compilerOptions": {
        "moduleResolution": "node",
        "module": "commonjs",
        "target": "ES5",
        "strictNullChecks": true,
        "lib": [
            "ES2021"
        ],
        "outDir": "../dist",
        "sourceMap": true,
        "declaration": true,
        "baseUrl": ".",
        "paths": {
            "@/*": [
                "./lib/*"
            ],
            "@lib/*": [
                "./lib/*"
            ],
            "@bin/*": [
                "./bin/*"
            ]
        },
        "plugins": [
            {
                "transform": "typescript-transform-paths"
            },
            {
                "transform": "typescript-transform-paths",
                "afterDeclarations": true
            }
        ],
    },
    "include": [
        "lib",
        "bin"
    ]
}