node_modules 的 Angular2 和 TypeScript 导入

Posted

技术标签:

【中文标题】node_modules 的 Angular2 和 TypeScript 导入【英文标题】:Angular2 & TypeScript importing of node_modules 【发布时间】:2016-05-11 15:15:55 【问题描述】:

我有一个非常简单的“hello world”Angular2 应用程序。我还做出了一个明显不合理的决定,即在我的开发项目和 Spring 后端的最终部署文件夹之间使用不同的目录结构。

由于这种差异,我在导入 TypeScript 时遇到了问题,当我尝试在浏览器中打开实际应用程序时,这条线最终产生了 404 错误(无法找到 /angular2/core 库):

import Component, View from 'angular2/core';

长话短说,我最终添加了 /app 文件夹以使一切正常,但我最终修改了我的导入语句,如下所示:

import Component, View from '../node_modules/angular2/core';

然而,这最终导致了一些奇怪的行为。出于某种原因,在库路径中指定 ../node_modules 会导致 JS 使用 ajax 调用从头开始加载所有 Angular2 文件,以从 npm_modules/angular2/ 文件夹中检索每个单独的文件,即使这是我的 html 标头的一部分:

<script src="/node_modules/angular2/bundles/angular2.dev.js"></script>

当我终于意识到发生了什么时,我将导入语句恢复为

import Component, View from 'angular2/core';

这一切都奏效了。 Angular2 现在已完全从上面的脚本标签加载,并且没有文件被额外的 ajax 调用加载。

有人能解释一下是什么原因造成的吗?我认为这是正常行为,但我不明白导入的工作原理以及为什么指定更详细的路径会产生如此大的影响。

【问题讨论】:

有关在 TS 世界中导入模块的更多详细信息:typescriptlang.org/docs/handbook/module-resolution.html 文档在这方面做得很好。真的。 【参考方案1】:

TypeScript 的 import 规则遵循与 node.js 相同的约定。如果导入以点开头:

import Something from './some/path';

然后它被视为声明导入的文件的相对路径。但是,如果它是绝对路径:

import Component from 'angular2/core';

然后假设是一个外部模块,所以Typescript会沿着树上走寻找package.json文件,然后进入node_modules文件夹,找到与import同名的文件夹,然后在模块的package.json 中查找主.d.ts.ts 文件,然后加载该文件, 将查找与指定文件同名的文件,或一个index.d.tsindex.ts文件。

哇,写出来的时候看起来很复杂,而且仍然有一些例外......但总而言之,如果你之前使用过 node.js,那么它的行为方式应该完全相同。

需要注意的一点是,应该设置一个 TypeScript 编译器选项,以便输入分辨率以这种方式工作

在 tsconfig.json 中

"moduleResolution": "node"

现在您问题的第二部分是如何在不使用 ajax 调用的情况下加载它。这是System.js 的一个功能。 index.html 文件中加载的脚本标签会导入一个包,该包将 angular2 包注册到系统。一旦发生这种情况,系统就会知道这些文件并正确地将它们分配给它们的引用。这是一个相当深奥的话题,但是可以在systemjs 或systemjs-builder 的自述文件中找到很多信息。

【讨论】:

非常感谢您提供详细且写得好的答案。几年来我一直在工作中使用nodejs,但直到现在我才设法避免遇到这个问题。很高兴我现在知道幕后发生了什么 - 再次感谢! @Thierry Templier:嗨,我有代码使用 node.js 模块,例如,var fs: any = require('fs')。它会导致问题。你知道如何使用 import 来做到这一点吗? @Ng2-Fun 'fs' 是节点核心模块,在浏览器中不可用,因此 Systemjs 将无法找到要加载的文件。这是我在不同用例中遇到的问题。即使在节点中运行,Systemjs 也会尝试为此加载模块,即使它不需要。除了将打字稿编译为 commonjs 之外,我还没有找到解决方案(尽管我没有尝试以这种方式运行应用程序)。对于使用 commonjs 的节点中的非 angular2 打字稿,您可以使用 import * as fs from 'fs'; 这应该可以满足您的需求。 @SnareChops:我实际上尝试在我的 angular2 应用程序中将 typescript 编译为 commonjs,它仍然无法正常工作。 如果我执行 'npm install some-lib' 然后在其中一个 ts 文件中使用 'import * as sl from 'some-lib',我假设 systemjs 会加载它。当我构建/服务时,源代码包括节点/模块/some-lib 文件夹 - 但是是什么创建了这个文件夹?它正在工作 - 在 Angular 2 Quickstart 中尝试过 - 但我无法弄清楚在构建/服务时创建和填充节点模块文件夹的内容!

以上是关于node_modules 的 Angular2 和 TypeScript 导入的主要内容,如果未能解决你的问题,请参考以下文章

node_modules/angular2-qrscanner/angular2-qrscanner.d.ts,找到版本 4,预期 3,解析符号

我可以为所有 angular2/4 项目使用一个 node_module 文件夹吗

由于 node_modules,Visual Studio 使用 Angular2 太慢了

angular2 找不到名称要求

将 Angular 2 node_modules 文件编译成一个文件

Angular2 添加 PrimeNG 组件