这几天在写typescript,遇到个路径依赖问题,编写的.ts文件直接运行OK,但是编译成.js后,运行提示 Error: Cannot find module xxx,📝记录分析和解决过程 。
问题描述
原始文件,有index.ts 其会引用src/say.ts,如下所示,
// index.ts
import { sayHi } from "src/say";
console.log(sayHi());
// src/say.ts
export function sayHi() {return "hi";
}
// tsconfig.json
{"compilerOptions": {"baseUrl": "./","outDir": "./build","experimentalDecorators": true,"lib": ["es2015", "es2016", "es2017.object", "es2020.Promise", "esnext.asynciterable", "dom"],"module": "commonjs","moduleResolution": "node","noImplicitAny": false,"sourceMap": true,"strict": true,"strictPropertyInitialization": false,"target": "es2017",},"compileOnSave": true,"exclude": ["node_modules/**/*", "**/*.d.ts", "test"],"include": ["src/**/*", "./index.ts"],
}
如果直接运行 npx tsx index.ts ,可以直接运行。
但是如果先编译npx tsc 得到build文件夹以及编译的js文件后,运行 node build/index.js,则会报错
node:internal/modules/cjs/loader:942throw err;^Error: Cannot find module 'src/say'
Require stack:
原因分析
当使用npx tsx index.ts时,会参考tsconfig.json文件中baseUrl (或paths)参数,找到src路径。但是使用tsc编译后,这部分信息并不会体现在编译后的build文件里面,此时再执行node build/index.js 则会提示找不到模块。
进一步说,这个问题 本质是别名问题 ,tsc不会转换路径别名。也看到网上有这么评价tsc,
- tsc不会转换路径别名,其实也是因为tsc的定位就是在开发阶段中使用的一个工具。
下一步,我们需要找到一种方式,让编译后的文件路径是正常的。
解决方案
方式1 修改引用路径
这种比较简单直接,不改变编译工具,还用tsc,引用时把相对路径加上 ,则编译后的路径依赖是正常的。
// index.ts
// import { sayHi } from "src/say"; noimport { sayHi } from "./src/say"; // yes
console.log(sayHi());
方式2 打包
不动代码,把项目整体打包成一个文件。以webpack打包工具举例。
npm install --save-dev webpack webpack-cli
npm install --save ts-loader
webpack配置文件
// webpack.config.js
const path = require("path");module.exports = {entry: "./index.ts",module: {rules: [{test: /\.tsx?$/,use: "ts-loader",exclude: /node_modules/,},],},resolve: {extensions: [".tsx", ".ts", ".js"],preferRelative: true,},output: {filename: "bundle.js",path: path.resolve(__dirname, "dist"),},
};
执行打包
npx webpack
打包后得到node dist/bundle.js,运行也是正常的。也不会再报路径模块找不到的问题。