TypeScript tsconfig.json 配置如何把非相对路径转为相对路径

相对导入是以/,./或../开头的。 下面是一些例子:
  • import Entry from "./components/Entry";
  • import { DefaultHeaders } from "../constants/http";
  • import "/mod";
所有其它形式的导入被当作非相对的。 下面是一些例子:
  • import * as $ from "jQuery";
  • import { Component } from "@angular/core";

也就是说我的问题是想把import 'jquery'编译后成为import jquery from './xxx/xxx/jquery'

配置文件

{
    "compilerOptions": {
        "module": "commonjs",
        "target": "ES6",
        "outDir": "../dist",
        "sourceMap": true,
        "lib": [
            "dom",
            "es2015",
        ],
        "typeRoots": [
            "../node_modules/@types"
        ],
        "baseUrl": "../",
        "paths": {
            "request":["node_modules/request/request.js"]
        }
    },
    "files": [
        "../test/test.ts"
    ]
}

目录结构

  • config 保存tsconfig.json的文件夹

    • tsconfig.json
  • dist 输出编译结果的目录
  • node_modules node模块文件夹

    • @types TypeScript声明文件

      • request 保存request的声明文件夹
    • request request本体文件夹
  • test 测试使用的文件

    • test.ts 等待编译的文件

问题说明

假设我当前的项目路径在/下.

/test/test.ts中有如下的内容.

import * as request from 'request'

console.log(request);

/路径下我使用如下命令编译:

tsc -p ./config/tsconfig.json

/dist下输出:

  • test.js
  • test.js.map

我们看一下test.js的内容:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const request = require("request");
console.log(request);
//# sourceMappingURL=test.js.map

那么问题来了如果我们是在Node中运行,根据node的加载规则,实际上是可以被加载的.

但是我希望编译的时候最终的路径是相对路径require('../node_modules/request/request.js'),而不是一个request.

在上面的tsconfig.json中,我尝试使用了baseUrlpaths属性,但是他们没有预期的工作,是我理解错误,还是操作的方式错误.

阅读 13.5k
2 个回答

问题核心

完整的相对导入在typescript编译后的路径不会随着outDir输出的目录而修改.

imoprt abc from "./node_modules/xxx/dist/xxx.min.js";

编译成javascript:

const abc = require('./node_modules/xxx/dist/xxx.min.js');

这本身没有问题,但是考虑如下的目录结构,我们这句引入放到了index.js中:

+-- dist
+-- node_modules
+- index.ts

但是我们设置了输出目录在dist文件夹中,最后输出的结果:

+-- dist
   +-- index.js
+-- node_modules
+- index.ts

但是index.js在执行的时候就会报错const abc = require('./node_modules/xxx/dist/xxx.min.js');无法解析到指定的文件,因为dist目录下没有node_modules目录.

解决方式

实际上非常简单,是我们忘记了node的和typescript的解析规则.

我们编写的ts代码无非两种:

  1. 我们自己编写的
  2. 其他人的第三方模块

在node中第三方模块统统放到了node_modules目录下,而node在运行的时候会根据名称来进行匹配node_modules目录,会从当前路径一直向上查找node_modules目录然后进入进行匹配.

而typescript是可以解析node模块的,解析规则和node一致.

所以我们根本不需要写完整的引入,写相对的就可以了.

对于我们的问题,例如我们要引入多个jquery中的压缩版本,我们完全可以不以当前的路径为起点:

import $ from "jquery/dist/jquery.min.js";

typescript会自动进行查找,在node执行的时候也会正确的解析到模块.

拓展

我们自己编写的第三方模块该如何处理.

最方便的就是直接上传到npm了,但是你还有其他选择.

利用package.json文件就可以了在package.json中存在的依赖会向当前的node_modules目录中进行查找,npm可以从git仓库中安装模块,例如我编写了一个myjquery的模块上传到github,在安装这个模块后在package.json中就可能如下显示:

----
  "dependencies": {
    "myjquery": "git://github.com/xxxx/myjquery.git#dev",
  },
----

使用npm安装模块的时候执行:

npm myjquery git://github.com/xxxx/myjquery.git#dev --save

最后:

你甚至可以直接在node_modules文件夹中填入你的模块,然后在package.json中写入对应的目录名称,然后给他一个假的版本号,这也可以运行.
直接名称和填入对应的是可以运行并且解析的,但是npm在每次安装包或者更新的时候都会进行检查,此时就会移除我们手动填入的模块.

兄弟,你解决了没? 我也遇到了相同的问题。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题