2016-07-15 44 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