AngularJS 2 解決部分 第三方套件 無法import問題 -以Chart.js為例

昨天晚上學弟告訴我:他發現 明明已經使用 angular-cli安裝Chart.js這個建構圖表的 Third-party 

但是卻仍然無法使用,會一直報錯:

Cannot find modu
le '../../../node_modules/chart.js'

起初一開始以為只是它單純安裝完後沒有給人家import而產生的錯誤,但後來我自己在看Code的時候發現其實裡頭大有學問。

因此發布上這篇讓其他有相同問題的人可以少採一點坑。

 

 

言歸正傳,在學習TypeScript的時候,我們知道我們可以透過

import {name } from 'your path';

這樣的方式來將套件載入。 例如:Bootstrap、JQuery等等

但是在使用一些Third-party 的時候卻會發現照這樣的方法載入時卻無法使用該套件

就會像如下圖:

找了很久發現網路上有不少網友也有遇到類似得問題,於是我到了Chart.js的官網

發現內部的教學指出如果想要使用這個Library則需要使用以下方式進行 import:

var Chart = require('chart.js')
var myChart = new Chart({...})

看到這筆者突然有了萬般的困惑....

為什麼在這裡需要採用 require的方式進行 import

而不是採用TypeScript的import方式呢?

於是開始google了一下這兩者的差異。

發現其中大有學問啊...

並不是每一個 Third-Party 都採用ES6的方式進行撰寫

在ES6的時候我們之所以可以透過 import這個關鍵字將套件進行載入

原因在於說它將該Module進行export

但是Chart.js這支檔案的內部結構卻不是如此。

Chart.js採用的是 CommonJS的寫法,因此在ES6上,便會認不得這個Module是什麼。

我們來做個簡單的範例就可以了解:

以自己寫計算數值平方為例。

ES6:

//------ lib.js ------
export function square(x) {
    return x * x;
}


//------ main.js ------
import { square } from 'lib.js';
console.log(square(11)); // 121

CommonJS:

//------ lib.js ------
function square(x) {
    return x * x;
}

module.exports = {
    square: square
};

//------ main.js ------
var square = require('lib').square;
console.log(square(11)); // 121

我們發現到兩種寫法中,他們內部的結構並不太一樣

在ES6中,我們會將我們需要的功能進行export 提供給外部做使用

但在CommonJS當中,則是將整個lib包成一個module 並且將會需要用到的功能包成物件來進行export

所以在外面我們才無法使用 import的方式進行載入。

接下來我們來驗證一下此說法是否成立。

我們來看一下Chart.js的Source Code就可以得知:

由此可知,Chart.js的確是採用CommonJS的方式進行export

所以在外部我們則需要使用下列Code 才能使用圖表的功能:

 let ctx = document.getElementById("myChart");
 let Chart = require('chart.js');
 let myChart = new Chart(ctx, {....});

當然這個情況不單單只會發生在Chart.js上,在某些Third-Party上也很有可能會遇到。

因此下一次發現透過 ES6 import的方式無效的時候,不仿可以研究看看Source Code ,了解一下是用何種方式進行撰寫囉!

參考資料來源 :http://2ality.com/2014/09/es6-modules-final.html

以上文章敘述如有錯誤及觀念不正確,請不吝嗇指教:)

有任何家教、案子 或技術相關問題 請都歡迎聯繫我

http://www.zhenghui.idv.tw/