angular2 TS导入cdn js与系统JS

时间:2016-07-15 16:43:59

标签: angular systemjs

我在安装来自cdn网址的正确js时遇到问题,在浏览了10篇文章或帖子后,我找不到一个好方法。

我要在我的角度项目中使用的js文件是http://player.twitch.tv/js/embed/v1.js。目前,我在index.html中只有一个脚本标记,用于加载它。

在组件文件中,我有this.player = new Twitch.Player("video-player", options);之类的代码,但是当我运行npm start时,出现错误错误TS2304:找不到名称'Twitch'。

奇怪的是,如果我注释掉使用'Twitch'的行,我可以启动我的服务器,然后在服务器运行时取消注释掉行,然后应用程序正常工作,利用Twitch播放器库没有任何问题。

我相信我需要在system.config.js文件中安装它,但我找不到如何为来自cdn的js(这不是通过npm提供)。我已经为多个npm包做了这个,但是从cdn我有点迷失了。

我不是100%确定我是否需要在systemjs中执行此操作,所以如果这不正确请忽略这篇文章的其余内容并告诉我你的建议 - 我只需要在js文件中使用Twitch在我的应用程序中被识别和使用。

我发现了几种不同的尝试方法。一个是load the module directly from the url

// index.html
<!-- 2. Configure SystemJS -->
<script src="systemjs.config.js"></script>
<script>
  System.import('app').catch(function(err){ console.error(err); });
  System.import('http://player.twitch.tv/js/embed/v1.js');
</script>

// main.js
import {bootstrap}    from '@angular/platform-browser-dynamic';
import {AppComponent} from './app.component';
import "angular2-materialize";
import "twitch-api";

使用这种方法,我不确定如何将其加载到我的应用程序中。 import "twitch-api"不像npm包那样工作,例如angular2-materialize,因为它没有映射到system.config.js文件中。不确定这种方式是否可行。

另一种方式是load it in the system.config.js file。使用此方法,我将带有url的地图对象添加到js文件中。我想也许整个system.config.js文件是相关的,所以我将它全部粘贴在下面。

在main.ts中,我执行与上面相同的操作,我添加import "twitch-api";执行这些更改后,尝试启动服务器TS2304: Cannot find name 'Twitch'时仍会收到相同的错误消息。

var map = {
    'app':                        'app', // 'dist',
    'rxjs':                       'node_modules/rxjs',
    'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api',
    '@angular':                   'node_modules/@angular',
    "materialize-css":            "node-modules/materialize-css",
    "materialize":                "node_modules/angular2-materialize",
    "angular2-materialize":       "node_modules/angular2-materialize",
    "angular2-localstorage":      "node_modules/angular2-localstorage",
    "twitch-api":                 "http://player.twitch.tv/js/embed/v1.js"
  };
  // packages tells the System loader how to load when no filename and/or no extension
  var packages = {
    'app':                        { main: 'main.js',  defaultExtension: 'js' },
    'rxjs':                       { defaultExtension: 'js' },
    'angular2-in-memory-web-api': { defaultExtension: 'js' },
    "materialize-css":            { main: "dist/js/materialize" },
    "materialize": { main: "dist/materialize-directive", defaultExtension: "js" },
    "angular2-localstorage": {main: "index.js", defaultExtension: 'js'},
    "twitch-api": {}
  };
  var packageNames = [
    '@angular/common',
    '@angular/compiler',
    '@angular/core',
    '@angular/http',
    '@angular/platform-browser',
    '@angular/platform-browser-dynamic',
    '@angular/router',
    '@angular/router-deprecated',
    '@angular/testing',
    '@angular/upgrade',
    ''
  ];
  // add package entries for angular packages in the form '@angular/common': { main: 'index.js', defaultExtension: 'js' }
  packageNames.forEach(function(pkgName) {
    packages[pkgName] = { main: 'index.js', defaultExtension: 'js' };
  });
  var config = {
    map: map,
    packages: packages
  }
  System.config(config);

2 个答案:

答案 0 :(得分:1)

最终更新 因此,在做了一些研究并更好地了解正在发生的事情(在某种程度上)之后,我想提出一个可能更有意义的更新。在某种程度上,原始和更新都有一些虚假信息。

更新中的一件事是错误的,我的声明是关于VS Code处理&#39; import&#39;指示不同。正确的语句是SystemJS,TypeScript编译器会处理&#39; import&#39;指示不同。在SystemJS的基本情况下(当它加载JS文件时)它甚至看不到这些import语句,它确实看到了import语句的产物(基于在tsconfig.json中如何配置Typescript)文件)。

所以在这个问题上唯一的#34;链接&#34;在&#34; import&#34;中的TypeScript和SystemJS之间陈述是&#34; twitch-api&#34;。 TypeScript会将.ts文件转换为.js文件,SystemJS将在加载页面时读取该文件,它将在其配置设置中查找名为&#34; twitch-api&#34;的软件包。这就是为什么如果您注释掉&#34; Twitch&#34;反对让网站启动,然后取消注释&#34; Twitch&#34;对象,SystemJS已经将该软件包加载到您的站点中,因此它可以正常工作。

对于TypeScript编译器,当编译器遇到import语句时,它有自己的rules集(查找&#39; TypeScript如何解析模块&#39;部分)。基于此,我们看到TypeScript忽略了SystemJS,它只查看文件夹结构中的特定位置。

由于导入是非相对类型,因此它会在您的node_modules中查找与&#34; twitch-api&#34;的匹配,它还会查找扩展名为[&#39; .ts& #39;,&#39; .tsx&#39;&#39; .d.ts&#39]。有趣的是这是一个URL,文件夹结构中没有文件。在正常情况下,TypeScript需要这样才能正确构建JS文件。不幸的是,Twitch没有提供.ts / .tsx / .d.ts文件,DefinitelyTyped也没有为Twitch提供.d.ts文件。

所以我解决这个问题的方法是为Twitch创建我自己的.d.ts文件(不完整,而且Twitch实际上做的不正确)。所以在我的&#34; node_modules&#34;文件夹我创建了一个名为&#34; twitch-api&#34;的文件夹。然后创建文件&#34; index.d.ts&#34;,在该文件中我将此定义放入(再次清楚,这不是定义代码,因为我不知道是什么方法&#34; Twitch.Player(&#34;视频播放器&#34;,选项);&#34;实际上返回但它仍然有效,因为SystemJS没有使用定义文件。)

export class Twitch{
    static Player(type:string,options:{}):void;    
}

export class Player{
    constructor(type:string,options:{});
}

一旦这两件事情到位,我就可以使用完整的导入语句,如

import {Twitch,Player} from 'twitch-api'

在您的情况下,您可能需要为定义文件添加更多用于Twitch / Player对象的任何其他方法或属性。

最后,我不确定为什么你能够通过使用&#34; Twitch声明一个变量来解决这个问题:任何&#34;工作。我认为这是因为&#34; import&#39; twitch-api&#39;&#34;导致TypeScript编译器不执行它通常会执行的某些检查。这意味着它只需要知道什么&#34; Twitch&#34;是不是看起来很深。这是我最好的猜测。

<强>更新 所以我的第一个猜测是完全错误的,我开始根据你的设置使用pluker,很明显这是其他的东西。我将plunker分成new个,如果我知道如何正确实例化Twitch.Player,那么它就可以在示例中使用。

当它在运行时执行更改后,它应该是显而易见的。您看到的错误是在Typescript编译器中。我不知道你正在使用什么IDE,但我使用的是VS代码而且我遇到了这些因为&#34; import&#34;声明与Plunker中的声明不同。

我认为你几乎就在那里,但你需要两者的结合。第一个例子失败的原因是&#34; twitch-api&#34;不是来自导入命令的已识别包。

我认为你的第二次尝试失败的原因是你如何实现地图和包对象。这是一个plunker,显示了如何使用外部URL实现配置。这是config.js文件的摘录。我不确定你何时需要使用&#34; main&#34;如果文件没有命名,我认为你必须使用它&#34; index&#34;或者它不遵循包裹的名称?

var  map = {
'app':                        'src', // 'dist',
'rxjs':                       'https://npmcdn.com/rxjs@5.0.0-beta.6',
'ng2-toastr':                 'https://npmcdn.com/ng2-toastr@0.3.0'
};

var packages = {
'app':                        { main: 'app.ts',  defaultExtension: 'ts' },
'rxjs':                       { defaultExtension: 'js' },
'ng2-toastr':                 { main: 'bundles/ng2-toastr.js', defaultExtension: 'js' }
};

答案 1 :(得分:0)

在我看来,您正在尝试在Angular / Typescript项目中使用Twitch交互式播放器。

我最近遇到了同样的问题,这就是为什么我决定为Twitch交互式嵌入播放器实现Typescript包装器的原因。这与Angular 100%兼容,因此,如果您仍然需要实现此目的的方法,请签出该存储库。我知道我迟到了几年,但我将把它留给其他人。

希望它能帮助^ ^

https://github.com/frozencure/twitch-player