【问题标题】:How to avoid imports with very long relative paths in Angular 2?如何避免在 Angular 2 中使用非常长的相对路径进行导入?
【发布时间】:2016-04-27 19:56:07
【问题描述】:

如何引入'my-app-name/services' 之类的内容来避免像以下导入那样的行?

import {XyService} from '../../../services/validation/xy.service';

【问题讨论】:

    标签: typescript ecmascript-6 angular angular2-services


    【解决方案1】:

    TypeScript 2.0+

    在 TypeScript 2.0 中,您可以在 tsconfig.json 中添加 baseUrl 属性:

    {
        "compilerOptions": {
            "baseUrl": "."
            // etc...
        },
        // etc...
    }
    

    然后您可以像在基本目录中一样导入所有内容:

    import {XyService} from "services/validation/xy.service";
    

    在此之上,您可以添加一个paths 属性,它允许您匹配一个模式然后将其映射出来。例如:

    {
        "compilerOptions": {
            "baseUrl": ".",
            "paths": {
                "services/*": [
                    "services/validation/*"
                ]
            }
            // etc...
        },
        // etc...
    }
    

    这将允许您从任何地方导入它:

    import {XyService} from "services/xy.service";
    

    从那里,您将需要配置您使用的任何模块加载器以支持这些导入名称。现在 TypeScript 编译器似乎并没有自动映射出来。

    您可以在github issue 中阅读更多相关信息。还有一个rootDirs 属性,在使用多个项目时很有用。

    Pre TypeScript 2.0(在 TS 2.0+ 中仍然适用)

    我发现使用"barrels" 可以更轻松。

    1. 在每个文件夹中,创建一个index.ts 文件。
    2. 在这些文件中,重新导出文件夹中的每个文件。

    示例

    在您的情况下,首先创建一个名为 my-app-name/services/validation/index.ts 的文件。在这个文件中,有代码:

    export * from "./xy.service";
    

    然后创建一个名为my-app-name/services/index.ts 的文件并输入以下代码:

    export * from "./validation";
    

    现在你可以像这样使用你的服务了(index 是隐含的):

    import {XyService} from "../../../services";
    

    一旦你有多个文件,它就会变得更加容易:

    import {XyService, MyOtherService, MyOtherSerivce2} from "../../../services";
    

    必须维护这些额外的文件需要更多的前期工作(可以使用barrel-maintainer 消除这些工作),但我发现最终以更少的工作获得回报。进行主要的目录结构更改要容易得多,并且可以减少您必须执行的导入次数。

    注意

    在执行此操作时,有几件事您必须注意而不能做:

    1. 您必须注意循环再出口。因此,如果两个子文件夹中的文件相互引用,则需要使用完整路径。
    2. 您不应该从同一个原始文件夹返回文件夹(例如,在验证文件夹中的文件中并执行import {XyService} from "../validation";)。我发现了这一点,第一点可能导致未定义导入错误。
    3. 最后,一个子文件夹中不能有两个同名的导出。不过通常这不是问题。

    【讨论】:

    • @ThomasZuberbühler 我认为 TypeScript 1.8 将可用 (see here)。
    • 如何使用 npm 下载 Typescript 2.0+?
    • 一个小提示 - 阅读文档后发现baseUrl 是相对于 'tsconfig.json' 的位置。所以在我们的例子(角度应用程序)中,值必须是"baseUrl": "./app",,其中“app”是应用程序的根。
    • 仅限 angular-cli 用户:如果您使用 angular-cli 2+,他们会切换到 webpack 和黑盒 webpack.config.js(在 node_modules 内)。 “从那里,你需要配置你正在使用的任何模块加载器来支持这些导入名称。” 因为 webpack.config.js 是黑盒的,所以你不能这样做。幸运的是,我发现这个问题已经被here 报告并由this PR 解决。 TL;DR 黑盒化的 webpack 配置足够智能,现在可以查看 tsconfig.json。
    • 对于 angular-cli 用户,您可以生成带有“ng 弹出”的 webpack.config。请注意,您需要从 .angular-cli.json -> 项目中删除弹出的:true 才能为该项目提供服务。
    【解决方案2】:

    最好在 tsconfig.json 中使用下面的配置

    {
      "compilerOptions": {
        "...": "reduced for brevity",
    
        "baseUrl": "src",
        "paths": {
          "@app/*": ["app/*"]
        }
      }
    }
    

    Angular 6 之前的传统方式:

    `import {XyService} from '../../../services/validation/xy.service';`
    

    应该重构为这些:

    import {XyService} from '@app/services/validation/xy.service
    

    又短又甜!

    【讨论】:

    • 此更改在生产中不起作用@shivangGupta
    • 嘿@Shivang Gupta,“...”在compilerOptions 中有什么作用?对不起,我是前端技术的新手。或者,这只是您在答案中用来表示 tsconfig 中已经存在的其他配置的符号吗?
    • 我更喜欢这种方法,因为@app 可以明确范围。我不赞成使用像 @core@shared@app/core@app/shared 这样的内容,因为它们具有更多的上下文。
    【解决方案3】:

    我刚刚遇到了这个问题。我知道它现在已经过去了,但是对于遇到它的任何人来说,都有一个更简单的答案。

    我遇到这种情况只是因为我长期以来一直在做的事情停止工作,我想知道 Angular 7 中是否发生了某些变化。不,这只是我自己的代码。

    尽管我只需要更改 tsconfig.json 中的一行以避免导入路径过长。

    {
      "compilerOptions": {
      "...": "simplified for brevity",
    
       "baseUrl": "src"
      }
    }
    

    例子:

    // before:
    import {XyService} from '../../../services/validation/xy.service';
    
    // after:
    import { XyService } from 'app/services/validation/xy.service';
    

    自从 Angular-CLI 出现以来,这一直对我有用。

    【讨论】:

    • 感谢克里斯的努力,但您应该在回答中提供使用示例!
    猜你喜欢
    • 2019-07-24
    • 1970-01-01
    • 2017-05-18
    • 1970-01-01
    • 2020-11-12
    • 2017-12-26
    • 2018-08-26
    • 1970-01-01
    相关资源
    最近更新 更多