Angular2 - 根路径相对导入

48

我在使用angular2/typescript时遇到了导入问题。我想要使用带有根路径的导入方式,比如:'app/components/calendar',而不是目前只能使用以下方式:

//app/views/order/order-view.ts
import {Calendar} from '../../components/calendar 

日历的定义如下:

//app/components/calendar.ts
export class Calendar {
}

当你越深入文件层级时,这个问题显然会变得更糟糕。最深处为"../../..",但它仍然非常糟糕且脆弱。是否有一种方法可以使用相对于项目根目录的路径?

我正在使用Visual Studio工作,相对导入似乎是使VS能够识别这些导入的唯一方法。


1
"baseUrl" maybe should set "./src" and paths relate to it wiil get it to work, it origin to be "./" , but my is not work, I don't know why! and then add "paths": { "@app/*": ["app/*"] } to tsconfig.json and use like import { PageNotFoundComponent } from '@app/error-page/page-not-found.component'; - Cheney
6个回答

35

答案

从 TypeScript 2.0 开始,您可以将 tsconfig.json 属性 baseUrl 设置为以下内容:

{
  "compilerOptions": {
    "baseUrl": "app"
}

然后,您可以使用您希望的组件导入方式,例如:

import { Calendar } from 'components/calendar';

附录

回退路径解决方案

一个重要的考虑因素是,指定 baseUrl 选项会导致 TypeScript 编译器:

  1. 相对于 baseUrl 查找路径
  2. 当解析失败(模块未找到)时,相对于 moduleResolution 选项查找路径

SystemJS

由于在 Angular 开发阶段大量使用 SystemJS,因此一定要正确配置 systemjs.config.js,以便正确解析路径。


来源和更多详细信息: https://github.com/Microsoft/TypeScript/issues/5039


@MerekDulwski,我在一个问题中引用了您的解决方案,但我在使用TSLint时遇到了一些问题:https://dev59.com/xKzla4cB1Zd3GeqPC9Ie - BBaysinger
1
在我遇到问题后,我发现这并不是理想的解决方案。我在这里发布了我新的首选解决方案:https://dev59.com/21sW5IYBdhLWcg3wwZfG#51599367 请试一试。 - BBaysinger
1
实际上这是相同的解决方案。只是将baseUrl选项设置为根项目目录,使其与我的建议不同,我同意,这并不是最好的选择。我会更新我的答案,很高兴你找到了完美的解决方案。 - Marek Dulowski

18

更新

不要使用这个解决方案。采用Node.js模块解析算法。 社区依赖于它,如果您试图使用其他方式,则一切都将崩溃。使用别名或其他提供的解决方案。

简短回答 有一种方法,但您不应该这样做。 将编译器选项"moduleResolution"设置为"classic"

详细回答

您是否在使用tsconfig.json?我想您是的。我一直在寻找一种方法,使语句import someModule = require ("../../../../someModule" 变成 import someModule=require("src/path/to/someModule")。 经过数小时的浪费时间后,我发现tsc可能会使用不同的模块解析算法。我使用的是Atom,它创建了带有moduleResolution属性设置为"node"tsconfig.json文件,并使用Node.js的糟糕(请原谅我的法语)模块解析算法。我只需把它改为“classic”,然后按照显而易见的方式工作。


2
“classic”选项完全破坏了angular2,你知道如何修复吗? - Jarek
1
请将您的源文件放在名为“node_modules”的文件夹中。这在此答案中有解释:https://dev59.com/mWgv5IYBdhLWcg3wFs2l#24461606 - caeus
37
那是我听过的可能性最糟糕的选择。@caeus - Stephan Kristyn
5
到目前为止,有19个人点赞了@nottinhill,他们中有没有更好的解决方案? - Neutrino
拥抱节点解析算法(不是开玩笑,经过一段时间的处理后,它并不那么糟糕)。否则,您可以开始为您的模块使用别名。 - caeus
显示剩余2条评论

13

基本上,在Angular 6中,您可以从顶部底部开始import

我的两个选项

它们可以使用由angular CLI生成的默认配置。

  1. 从顶部
    如果它离应用程序的根更近,我更喜欢这种方式

    import { DateService } from "src/app/shared-services/context/date.service";

  2. 从底部

    import { DateService } from "../../../../../../../shared-services/context/date.service";

上下文:

TypeScript配置:tsconfig.json

{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es5",
    "typeRoots": [
      "node_modules/@types"
    ],
    "lib": [
      "es2017",
      "dom"
    ]
  }
}


Angular的技术栈

ng -v

Angular CLI: 6.0.8
Node: 8.9.0
OS: win32 x64
Angular: 6.0.7
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.6.8
@angular-devkit/build-angular     0.6.8
@angular-devkit/build-optimizer   0.6.8
@angular-devkit/core              0.6.8

@angular-devkit/schematics        0.6.8
@angular/cli                      6.0.8
@ngtools/webpack                  6.0.8
@schematics/angular               0.6.8
@schematics/update                0.6.8
rxjs                              6.2.1
typescript                        2.7.2
webpack                           4.8.3

7

一种方法是使用重新导出文件并使用更短的路径捆绑文件。

您可以在应用程序的根目录中拥有一个components.ts文件夹。

export {Calendar} from './components/calendar'
export {*} from './components/map'

并从组件中导入它

import {Calendar, Map} from '../../components';

然而,这种方式更适合导出模块以供他人使用,而不是组织项目的方式。

另一种选择是放弃使用导入语句,改为使用内部模块。

calendar.ts

module Components {
    export class Calendar {}
}

你可以在项目的任何文件中像这样使用它。

new Components.Calendar();

或者使用别名导入它。

import Calendar = Components.Calendar;
new Calendar();

5
简而言之:您现在应该能够使用src作为根目录,并且它将“只是工作”。
在Angular 2.0中,当您运行ng new my-proj时,它会自动创建一个名为my-proj/src/tsconfig.app.json的文件。该文件包含一个baseUrl行。
"baseUrl": "./",

因此,您不需要更改配置的任何内容,可以将所有导入的范围限定在以src为根目录的位置。假设您的项目结构类似于:
my-proj/
  README.md
  src/
    app/
      sidebar/
        sidebar.component.ts
      user.service.ts

您可以使用以下方式导入文件:

import { Sidebar } from 'app/sidebar/sidebar.component';
import { UserService } from 'app/user.service';

编辑添加:Sublime不会读取src/tsconfig.json,只会读取顶层的tsconfig.json(参见此问题)。如果在Sublime中导入行上遇到Cannot find module 'app/...'错误,则可以添加以下内容:

"baseUrl": "./src",

将以下内容添加到您的顶级tsconfig.json文件中。

4

对于由Angular-CLI生成的新项目的默认配置,您无需更改任何内容。至少从版本6开始,我知道这是正确的(以前的版本不确定)。要进行根相对导入,您可以在导入的开头使用 src /

import { VideoPlayerComponent } from 'src/app/pages/shared/video-player/video-player.component';

这是比@MarekDulowski的答案更好的解决方案,因为根相对导入可以很容易地识别,并且可以通过查询“ src / ”在全局范围内轻松找到/搜索。
我从这个解决方案中了解到: https://dev59.com/xKzla4cB1Zd3GeqPC9Ie#51582699

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接