【问题标题】:Why I can not import directly from node_modules using SystemJS?为什么我不能使用 SystemJS 直接从 node_modules 导入?
【发布时间】:2017-05-03 18:48:00
【问题描述】:

虽然 SystemJS 上有很多 questionsdocumentation,但我仍然不明白导入语法。 具体来说,为什么打字稿找不到ng-boostrap.js使用这个代码:

import { createPlatform } from '../../node_modules/@ng-bootstrap/ng-bootstrap/bundles/ng-bootstrap',

这是直接导入文件,但这段代码有效:

import {createPlatform } from './node_modules/@angular/core/bundles/core.umd.js';

systemjs.config.js 中的 map 包含以下行:

'@angular/core': 'npm:@angular/core/bundles/core.umd.js'.

为什么我不能使用 systemJS 从node_modules 直接导入?

【问题讨论】:

    标签: javascript angular typescript systemjs


    【解决方案1】:

    注意:虽然下面的解决方案有效,但有些信息是不正确的。请参阅下面 cmets 中的讨论。

    首先,TypeScript 对 JS 文件一无所知。它知道如何生成它们,但不知道如何针对它们进行编译。所以我不确定你是怎么得到的

    import {createPlatform } from './node_modules/@angular/core/bundles/core.umd.js';
    

    在你的 TypeScript 代码中编译。

    我们可以做到

    import {createPlatform } from '@angular/core';
    

    在 TypeScript 中,因为 TypeScript 已经在寻找 node_modules。而@angular/core,如果你在你的node_module里面看,有一个目录@angular/core,有一个index.d.ts文件。这是我们的 TypeScript 代码编译的文件,而不是 JS 文件。 JS文件(上面第一个代码sn-p中的那个)只在运行时使用。 TypeScript 应该对该文件一无所知。

    使用上面的第二个sn-p,TypeScript编译成JS的时候是这样的

    var createPlatform = require('@angular/core').createPlatform;
    

    作为运行时,SystemJS 看到这个,然后查看 map 配置,并将 @angular/core 映射到绝对文件位置,并且能够加载该文件

    '@angular/core': 'npm:@angular/core/bundles/core.umd.js'
    

    这是 ng-bootstrap 应该遵循的模式。使用指向 TypeScript 定义文件的导入,以便编译

    import { ... } from '@ng-bootstrap/ng-bootstrap';
    

    如果您查看node_modules/@ng-bootstrap/ng-bootstrap 目录,您应该会看到index.d.ts 文件。这是 TypeScript 将用来编译的。编译成JS的时候,编译如下

    var something = require('@ng-bootstrap/ng-bootstrap').something;
    

    并且在 SystemJS 配置中,我们需要将@ng-bootstrap/ng-bootstrap 映射到模块文件的绝对路径,否则 SystemJS 将不知道如何解析它。

    '@ng-bootstrap/ng-bootstrap': 'npm:@ng-bootstrap/ng-bootstrap/bundles/ng-bootstrap.js'
    

    其中一个关键的收获是了解编译时和运行时之间的区别。编译类型是 TypeScript,它对 JS 文件一无所知,因为它们是运行时文件。 SystemJS 是需要了解运行时 (JS) 文件的那个。

    【讨论】:

    • 除了开头和结尾之外,您的答案几乎是正确的。如果您指定 "allowJs": true,typescript 会将此类导入直接解析为 JavaScript 文件,但它会更喜欢 .d.ts.ts 文件(如果存在)。
    • @AluanHaddad 我猜我什么都知道:-)
    • @AluanHaddad 我假设如果你导入 JS 文件,你会丢失编译时输入。对吗?
    • 不,这是不正确的。 JavaScript 文件将由相同的语言服务解析,类型推断将完全有效,并由适用的 JSDoc cmets 补充,以提供尽可能多的类型信息。主要区别在于 JS 文件中,推理失败不会导致类型错误。混合 JS 和 TS 项目是完全可行的。
    • 我想投票给这个答案,你的问题是对的,但问题不在于 TypeScript 理解一种文件而 SystemJS 理解另一种文件,实际上这两种工具都理解这两种类型的文件.问题是 TypeScript 和 SystemJS 使用不同的解析算法。
    猜你喜欢
    • 2014-11-25
    • 1970-01-01
    • 1970-01-01
    • 2019-12-02
    • 2023-03-20
    • 2018-05-05
    • 1970-01-01
    • 2022-01-26
    • 2021-02-03
    相关资源
    最近更新 更多