用typescript來寫npm模塊

用typescript來寫npm模塊

還不知道typescript是啥的前端童鞋須要作下功課了。javascript

隨着es6的普及,愈來愈多的npm模塊都開始用es6編寫或者重構,看上去或者聽起來都挺高大上的。前端

然而,模塊調用者要使用這些模塊,依然要去npm倉庫或者github上仔細看該模塊的api,哪些方法該傳什麼類型的參數,返回什麼類型的值都須要注意。java

因此說,用es6來寫模塊僅僅是寫得爽了,用起來和以前並沒什麼不一樣。那如何作到寫起來爽用得也爽呢,答案是typescriptwebpack

用起來爽不爽,貼張gif感覺一下。git

intellesence.gif

mini-moment這個模塊是我用typescript寫的,上面gif中能夠看到,Moment有哪些靜態方法、實例有哪些屬性和方法、方法都接收什麼類型的參數、返回什麼類型的值編輯器都給出了智能提示,不用去看api了,也不用擔憂傳錯參數。這可不是用es6寫能作到的。es6

那智能提示是怎麼作到的呢?github

這都要歸功於typescript的頭文件*.d.ts,這個文件就像模塊的名片,裏面定義了模塊的各類類/方法/屬性等信息。目前主流的前端/Node.js的類庫/框架都有對應的.d.ts文件,能夠去DefinitelyTyped上找一下。要使用的話能夠經過tsd或者typings這兩個工具安裝(兩個工具的做者是同一我的,目前tsd已經廢棄了,可是typingstsd好用,常常出問題,typings不行的時候我就會用tsd)。web

因此咱們寫的模塊要想用的時候有智能提示,就要編寫對應的.d.ts文件,並把這個文件發佈出去。目前有下面幾種方法typescript

  1. 添加到DefinitelyTyped倉庫npm

    • fork DefinitelyTyped這個github倉庫

    • 提交本身模塊的.d.ts文件和對應的測試文件

    • 提交pull requestDefinitelyTyped,等待做者merge

    • merge後調用者就能夠經過tsd/typings來安裝使用

    此方法能夠解決模塊依賴問題,可是週期太長,DefinitelyTyped做者可能不會及時merge,也可能把你的pull request打回來。

  2. 放在本身的github之類的倉庫

    • 指定頭文件路徑,經過tsd/typings來安裝使用

    此方法頭文件由本身維護,不方便管理,可是用的時候要處處copy頭文件路徑。

  3. 隨模塊一塊兒發佈

    • 編寫頭文件,命名爲index.d.ts,放在項目根目錄

    • npm publish的時候包含這個文件

此方法不須要用tsd/typings安裝,npm install模塊的時候就有了,可是這種方法在依賴其餘模塊的時候就比較坑。

以上幾種方法各有利弊,視狀況選擇。

說了頭文件的編寫,再說文件的打包,打包固然是webpack了。

咱們用typescript開發的模塊最終是要編譯成javascript的,可是typescript在編譯的時候有些坑爹,當編譯的target選項設置爲es6時只會將代碼編譯成es6的語法,這樣的代碼在不少瀏覽器上是跑不起來的,而將target設置爲es5或者es3的時候又無法使用某些es6的特性。非常蛋疼,不過還好,咱們有babel這個好基友,新特性照寫,代碼照跑。

因此咱們的loader能夠這樣寫:

{
    loaders: [
        { test: /\.ts?$/, loader: "babel?presets[]=es2015!ts" }
    ]
}

還沒完,咱們開發的模塊編譯後要兼容各類模塊規範,用typescript或者es6的模塊導入導出通常是用的importexport,通常是編譯成commonjs或者amd規範,這樣的代碼不必定在全部環境都能跑起來。不要緊,咱們還有umd

因此咱們的webpack.config.js能夠這樣寫:

"use strict";

const webpack = require('webpack');

const modName = "YOUR_MOD_NAME";

module.exports = {
    entry: "./src/index.ts",
    output: {
        filename: `./dist/${modName}.js`,
        library: modName,
        libraryTarget: 'umd',
        umdNamedDefine: true
    },
    resolve: {
        extensions: [".ts", ".js"]
    },
    module: {
        loaders: [
            { test: /\.ts?$/, loader: "babel?presets[]=es2015!ts" }
        ]
    }
};

自從typescript的生態愈來愈好後,我已再次入坑typescript,目前已經用typescript寫了幾個東西了,後續會再分享一些使用typescript的經驗。

相關文章
相關標籤/搜索