Webpack双入口配置下ts-loader报错问题(VSCode扩展项目)
问题:TypeScript项目引用+Webpack双入口打包触发TS6059错误
项目背景
这是一个VSCode扩展项目,采用TypeScript项目引用(tsc project reference)结构,包含两个独立模块:
- client:language client
- server:language server
项目目录结构如下:
├── client │ ├── package.json │ ├── package-lock.json │ ├── src │ │ ├── extension.ts │ │ └── logging.ts │ └── tsconfig.json ├── package.json ├── package-lock.json ├── server │ ├── package.json │ ├── package-lock.json │ ├── src │ │ ├── server.ts │ │ └── utils.ts │ └── tsconfig.json ├── tsconfig.base.json ├── tsconfig.json └── webpack.config.js
报错情况
尝试通过Webpack配置双入口,将项目打包为client.js和server.js时,ts-loader抛出如下错误:
ERROR in /home/quan/repos/cmake-intellisence/client/tsconfig.json /home/quan/repos/cmake-intellisence/client/tsconfig.json [tsl] ERROR TS6059: File '/home/quan/repos/cmake-intellisence/server/src/server.ts' is not under 'rootDir' '/home/quan/repos/cmake-intellisence/client/src'. 'rootDir' is expected to contain all source files. The file is in the program because: Root file specified for compilation
注意:仅配置单个入口(仅client或仅server)时,打包完全正常。
相关配置文件
webpack.config.js
'use strict'; const path = require('path'); const webpack = require('webpack'); /**@type {import('webpack').Configuration}*/ const config = { target: 'node', // vscode extensions run in webworker context for VS Code web 📖 -> https://webpack.js.org/configuration/target/#target entry: { client: './client/src/extension.ts', server: './server/src/server.ts' }, // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/ // entry: "./server/src/server.ts", // entry: "./client/src/extension.ts", output: { // the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/ path: path.resolve(__dirname, 'dist'), filename: '[name].js', libraryTarget: 'commonjs2', devtoolModuleFilenameTemplate: '../[resource-path]' }, devtool: 'source-map', externals: { vscode: 'commonjs vscode' // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/ }, resolve: { // support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader mainFields: ['browser', 'module', 'main'], // look for `browser` entry point in imported node modules extensions: ['.ts', '.js'], alias: { // provides alternate implementation for node module and source files }, fallback: { // Webpack 5 no longer polyfills Node.js core modules automatically. // see https://webpack.js.org/configuration/resolve/#resolvefallback // for the list of Node.js core module polyfills. } }, module: { rules: [ { test: /\.ts$/, exclude: /node_modules/, use: [ { loader: 'ts-loader', options: { "projectReferences": true } } ] } ] } }; module.exports = config;
根目录tsconfig.json
{ "include": [], "references": [ { "path": "./client" }, { "path": "./server" } ] }
tsconfig.base.json
{ "compilerOptions": { "module": "commonjs", "target": "es2020", "lib": [ "es2020" ], "sourceMap": true, "composite": true } }
client/tsconfig.json
{ "extends": "../tsconfig.base.json", "compilerOptions": { "outDir": "out", "rootDir": "src", }, "include": [ "src" ] }
server/tsconfig.json
{ "extends": "../tsconfig.base.json", "compilerOptions": { "outDir": "out", "rootDir": "src", "resolveJsonModule": true }, "include": [ "src" ] }
解决方案建议
方案1:为不同入口指定对应tsconfig
修改Webpack配置中的module.rules,通过oneOf区分client和server的源码路径,分别指定对应的tsconfig文件,避免ts-loader混淆项目引用的配置:
module: { rules: [ { test: /\.ts$/, exclude: /node_modules/, oneOf: [ { include: path.resolve(__dirname, 'client/src'), use: { loader: 'ts-loader', options: { configFile: './client/tsconfig.json', projectReferences: true } } }, { include: path.resolve(__dirname, 'server/src'), use: { loader: 'ts-loader', options: { configFile: './server/tsconfig.json', projectReferences: true } } } ] } ] }
方案2:创建Webpack专用的根目录tsconfig
在项目根目录新增tsconfig.webpack.json,专门用于Webpack打包,统一rootDir并包含所有源码:
{ "extends": "./tsconfig.base.json", "compilerOptions": { "rootDir": ".", "outDir": "./dist" }, "include": [ "client/src/**/*", "server/src/**/*" ], "references": [ { "path": "./client" }, { "path": "./server" } ] }
然后修改ts-loader的配置,指定使用这个新的配置文件:
use: [ { loader: 'ts-loader', options: { configFile: './tsconfig.webpack.json', projectReferences: true } } ]
方案3:拆分Webpack配置为两个独立文件
分别创建webpack.client.js和webpack.server.js,各自对应单个入口和对应的tsconfig:
webpack.client.js:entry设为./client/src/extension.ts,ts-loader指定configFile: './client/tsconfig.json'webpack.server.js:entry设为./server/src/server.ts,ts-loader指定configFile: './server/tsconfig.json'
然后在package.json中添加打包命令:
"scripts": { "build:client": "webpack --config webpack.client.js", "build:server": "webpack --config webpack.server.js", "build": "npm run build:client && npm run build:server" }
这种方式完全隔离两个模块的打包流程,彻底避免配置冲突。
内容的提问来源于stack exchange,提问作者zhuo.quan
相关产品推荐
相关产品推荐

