昨天晚上學弟告訴我:他發現 明明已經使用 angular-cli安裝Chart.js這個建構圖表的 Third-party
但是卻仍然無法使用,會一直報錯:
Cannot find modu
le '../../../node_modules/chart.js'
起初一開始以為只是它單純安裝完後沒有給人家import而產生的錯誤,但後來我自己在看Code的時候發現其實裡頭大有學問。
因此發布上這篇讓其他有相同問題的人可以少採一點坑。
言歸正傳,在學習TypeScript的時候,我們知道我們可以透過
這樣的方式來將套件載入。 例如: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
以上文章敘述如有錯誤及觀念不正確,請不吝嗇指教:)
有任何家教、案子 或技術相關問題 請都歡迎聯繫我