2016-07-15 96 views
0

我遇到问题安装正确的js来自cdn网址,并通过查看超过10篇文章或帖子后,我找不到一个好方法来做到这一点。angular2 TS导入cds js与系统JS

我想要安装在我的角度项目中使用的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); 

回答

1

最后更新 所以做了些研究,并更好地了解发生了什么事情(在一定程度上)之后,我希望把在更新,可能使一些更有意义。在某种程度上,原始和更新都有一些虚假的信息。从错了更新

一两件事,是我对VS代码语句区别对待的“进口”的指令。正确的语句是SystemJS,TypeScript编译器对待'import'指令的方式不同。在SystemJS的基本情况(当它加载JS文件),它甚至没有看到这些import语句,但它确实看到import语句的产品(基于打字稿是如何在tsconfig.json文件中配置)。

所以在这个问题中的“导入”语句唯一的“链接”打字稿和SystemJS之间是“抽搐API”。 TypeScript会将.ts文件转储到一个.js文件中,当页面被加载时,SystemJS将读取这个文件,它会在它的配置设置中查找名为“twitch-api”的包。这就是为什么你的网站会工作,如果你注释掉了“Twitch”对象的使用来启动网站,然后取消注释“Twitch”对象,SystemJS已经将该软件包加载到您的网站,所以它只会工作。

对于TypeScript编译器,当编译器遇到import语句时,它有自己的一组rules(查找'How TypeScript解析模块'部分)。基于此,我们发现TypeScript不知道SystemJS,它只在您的文件夹结构中的特定位置查找。

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

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

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

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

一次。这两件事情已经到位,我能够使用完整的导入语句像

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

在你的情况可能要更添加到您的定义文件的任何其他方法或属性是你的U se为Twitch/Player对象。

最后,我不确定为什么你只需用“Twitch:any”声明一个变量就能解决问题。我认为这是因为“import”twitch-api'“会导致TypeScript编译器不执行某些通常会执行的检查。这意味着它只需要知道“Twitch”是什么并且不会深入。这是我最好的猜测。


更新 所以我的第一个猜测是完全错误的,我开始根据您的设置pluker玩耍和很明显,这是别的东西。我把plunker分成一个new,如果我知道如何正确地实例化Twitch.Player,它将在这个例子中起作用。

这应该是显而易见的,当它在运行时进行更改后会工作。您看到的错误是在Typescript编译器中。我不知道你在使用什么IDE,但我使用的是VS代码,我遇到过这些问题,因为“import”语句与Plunker中的不同。


我认为你几乎在那里,但你需要一种两种组合。第一个例子失败的原因是因为“twitch-api”不是从导入命令中识别的包。

我认为你的第二次尝试失败的原因是你如何实现地图和包对象。这是一个plunker,显示如何使用外部URL实现您的配置。这是config.js文件的摘录。当您需要使用“主”属性时,我不确定所有规则,我认为如果文件未命名为“index”或者它不遵循包的名称,则必须使用它?

var map = { 
'app':      'src', // 'dist', 
'rxjs':      'https://npmcdn.com/[email protected]', 
'ng2-toastr':     'https://npmcdn.com/[email protected]' 
}; 

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

嘿谢谢你把它放在一起。这个答案并不完全是“正确的”,但你提到这是一个TS编译错误,这让我足以让谷歌更好。我需要声明'Twitch:any;'然后它一切正常。我相信有一个更好的方法来做到这一点,但它现在起作用!谢谢。 – awwester