亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

從 JavaScript 到 TypeScript - 模塊化和構(gòu)建

Jonathan Shieber / 2679人閱讀

摘要:不過,相對(duì)于靜態(tài)類型檢查帶來的好處,這些代價(jià)是值得的。當(dāng)然少不了的模塊化標(biāo)準(zhǔn),雖然到目前為止和大部分瀏覽器都還不支持它。本身支持兩種模塊化方式,一種是對(duì)的模塊的微小擴(kuò)展,另一種是在發(fā)布之前本身模仿的命名空間。有一種情況例外。

TypeScript 帶來的最大好處就是靜態(tài)類型檢查,所以在從 JavaScript 轉(zhuǎn)向 TypeScript 之前,一定要認(rèn)識(shí)到添加類型定義會(huì)帶來額外的工作量,這是必要的代價(jià)。不過,相對(duì)于靜態(tài)類型檢查帶來的好處,這些代價(jià)是值得的。當(dāng)然,TypeScript 允許不定義類型或者將所有類型定義為 any,但如果這樣做,TypeScript 帶來的大部分靜態(tài)檢查功能都會(huì)失去作用,換言之,也就沒必要使用 TypeScript 了。

模塊化

在轉(zhuǎn)換之前還要注意的一個(gè)問題就是模塊化。早期的 JavaScript 代碼基本上是每個(gè) HTML 頁(yè)面對(duì)應(yīng)一個(gè)或幾個(gè) JavaScript 腳本,那時(shí)候的 JavaScript 代碼中很少有模塊化的概念。不過隨著 Web 2.0 的興起,大量的工作從后端移到前端,JavaScript 程序變得越來越復(fù)雜,模塊化成為剛需,大量的模塊化框架隨之而來,其中比較有名的有 RequestJS 及其帶來的 AMD 標(biāo)準(zhǔn),還有 SeaJS 帶來的 CMD 標(biāo)準(zhǔn)。而隨著 Node.js 的興起以及 JavaScript 的全?;?,又有了 CommonJS 標(biāo)準(zhǔn)。之后又出現(xiàn)了廣為使用的 SystemJS。當(dāng)然少不了 ES6 的模塊化標(biāo)準(zhǔn),雖然到目前為止 Node.js 和大部分瀏覽器都還不支持它。

TypeScript 本身支持兩種模塊化方式,一種是對(duì) ES6 的模塊的微小擴(kuò)展,另一種是在 ES6 發(fā)布之前本身模仿 C# 的命名空間。大部分使用命令空間的場(chǎng)景都可以使用 ES6 模塊化標(biāo)準(zhǔn)來代替。我們先來看一看兩種模塊化方式區(qū)別。

命名空間

使用命令空間寫的 TS 腳本在轉(zhuǎn)譯成 JS 后,可以不使用任何模塊加載框架,直接在頁(yè)面中加載即可使用。不過很遺憾,這種方式轉(zhuǎn)義出來的 JS 程序不能直接在 Node.js 中使用。因?yàn)?tsc 不為會(huì)命名空間形式的模塊生成 modules.exports 對(duì)象以及 require 語(yǔ)句。

有一種情況例外。將所有 .ts 文件轉(zhuǎn)譯成一個(gè) .js,假設(shè)叫 all.js,那么它可以通過 node all 來運(yùn)行。這種情況下不需要任何模塊的導(dǎo)入導(dǎo)出。

不過在瀏覽器環(huán)境中,嚴(yán)格的按照依賴順序引入生成的 .js 文件是可行的。早期沒有使用模塊化的 JS 文件就可以使用“命名空間”形式的模塊化寫法,甚至可以將原來成百上千行的大型 JS 源文件,拆分成若干小的 TS 文件,再通過 tsc --outfile 輸出單一 JS 文件來使用,這樣既能實(shí)現(xiàn)模塊化重構(gòu),又能不改變?cè)械?HTML(或其它動(dòng)態(tài)頁(yè)面文件)的代碼。

還有一點(diǎn)需要注意的是,在指定生成單一輸出文件的情況下,TypeScript 不會(huì)通過代碼邏輯去檢查模塊間的依賴關(guān)系。默認(rèn)情況下它會(huì)按文件名的字母序逐個(gè)轉(zhuǎn)譯 .ts 文件,除非源文件中通過 /// 明確指定了依賴項(xiàng)。

ES6 模塊

在 TypeScript 使用 ES6 模塊語(yǔ)法來實(shí)現(xiàn)模塊化的情況下,tsc 允許通過 module 參數(shù)來指定生成的 .js 會(huì)應(yīng)用于何種模塊化框架,默認(rèn)的是 commonjs,其它比較常用的還有 amd、system 等。

顯然,如果原來的 JS 程序使用了 AMD 框架,在轉(zhuǎn)換成 TS 的時(shí)候,就可以使用 ES6 模塊寫法,并通過 tsc --module amd 來輸出對(duì)應(yīng)的 JS 文件,同樣不需要修改原來的頁(yè)面文件。

但是,如果原來的 JS 文件沒有使用任何模塊框架的情況下,轉(zhuǎn)換為采用 ES6 模塊寫法的 TS 代碼,在構(gòu)建的時(shí)候就會(huì)麻煩一點(diǎn)。這種情況下即使構(gòu)建成單一輸出文件,仍然會(huì)需要模塊化框架的支持,比如需要 AMD 的 definerequire,或者需要 System 的 API 支持。

為了避免引入模塊化框架,可以考慮以 commonjs 標(biāo)準(zhǔn)輸出 JS,然后通過 Webpack 來把所有生成的 JS 打包成單一文件。這里既然用到了 Webpack,構(gòu)建配置就可以更靈活了,因?yàn)?Webpack 可以指定多個(gè) entry,可以有多個(gè)輸出,它會(huì)通過 import ... 轉(zhuǎn)譯成的 require(...) 自動(dòng)檢查依賴項(xiàng)。而且 Webpack 還可以使用 ts-loader 直接處理 .ts 文件而不需要先使用 tsc 來進(jìn)行轉(zhuǎn)譯。如果在 TS 中用到了高版本 ECMAScript 語(yǔ)法,比如 async/await,還可以通過 babel-loader 來增加一層處理……非常靈活。

但這里往往會(huì)有一個(gè)問題,生成的 .js 中所有定義都不在全局范圍,那么腳本引入網(wǎng)頁(yè)之后,如何使用其中定義的內(nèi)容?這需要借助全局對(duì)象 window——這里不需要考慮 Node.js 的全局對(duì)象 global,因?yàn)樵?Node.js 下一般是采用模塊化的方式引入,不需要向全局對(duì)象注入什么東西。

window 注入對(duì)象(或函數(shù)、值等)的方法也很簡(jiǎn)單,分兩步:申明、賦值,比如:

import MyApi from "./myapi";

declare global {
    interface Window {
        mime: MyApi;
    }
}

window.mime = new MyApi();
常用的構(gòu)建配置

我們?cè)缙陧?xiàng)目中使用 TypeScript 的命名空間,不過最近幾乎都重構(gòu)成 ES6 模塊方式了。由于會(huì)用到 async 函數(shù),所以一般會(huì)配置 TypeScript 輸出 ES2017 代碼,再通過 Babel 轉(zhuǎn)譯成 ES5 代碼,最后由 Webpack 打包輸出。

tsconfig.json
{
    "compilerOptions": {
        "module": "commonjs",
        "target": "es2017",
        "lib": [
            "dom",
            "es6",
            "dom.iterable",
            "scripthost",
            "es2017"
        ],
        "noImplicitAny": false,
        "sourceMap": false
    }
}

targetes5es6 的時(shí)候,TypeScript 會(huì)有默認(rèn)的 lib 列表,這在官方文檔中有詳細(xì)說明。target 定義為 es2017 是為了支持 async 函數(shù),但這個(gè)配置沒有默認(rèn) lib 列表,所以參考官方文檔對(duì) --target es6 使用的 lib 列表,補(bǔ)充 es2017 類型庫(kù)即可。

webpack.config.js

這里使用了 Webpack2 的配置格式。

module.exports = {
    entry: {
        index: "./js/index"
    },
    output: {
        filename: "[name].js"
    },
    devtool: "source-map",
    resolve: {
        extensions: [".ts"]
    },
    module: {
        rules: [
            {
                test: /.ts$/,
                use: [
                    {
                        loader: "babel-loader",
                        options: {
                            presets: ["es2015", "stage-3"]
                        }
                    },
                    "ts-loader"
                ],
                exclude: /node_modules/
            }
        ]
    }
};
gulp task

如果還使用 gulp,任務(wù)是這樣寫的

const gulp = require("gulp");
const gutil = require("gulp-util");

// 轉(zhuǎn)譯JavaScript
gulp.task("webpack", () => {
    const webpack = require("webpack-stream");
    const config = require("./webpack.config.js");
    return gulp.src("./js/**/*.ts")
        .pipe(webpack(config, require("webpack")))
        .on("error", function(err) {
            gutil.log(err);
            this.emit("end");
        })
        .pipe(gulp.dest("../www/js"));
});

這里需要注意的是 webpack-stream 默認(rèn)使用的是 webpack1,而我們的配置需要 webpack2,所以為它指定第二個(gè)參數(shù),一個(gè)特定版本的 webpack 實(shí)例 (由 require("webpack") 導(dǎo)入的)。

需要的 Node 模塊

從上面的構(gòu)建配置中不難總結(jié)出構(gòu)建過程需要安裝的 Node 模塊,有這樣一些

gulp

gulp-util

webpack-stream

webpack

ts-loader

typescript

babel-loader

babel-core

babel-preset-es2015

babel-preset-stage-3

在 Node.js 環(huán)境直接運(yùn)行 .ts

在 Node.js 中可以通過 ts-node 包來直接運(yùn)行 TypeScript 代碼。需要做的只是在入口代碼文件(當(dāng)然是個(gè) .js 代碼)中添加一句

require("ts-node").register({ /* options */ })

或者

require("ts-node/register")

因?yàn)?Node.js 7.6 開始已經(jīng)直接支持 async 函數(shù)語(yǔ)法,所以即使用到了這個(gè)語(yǔ)法,也不用擔(dān)心 ts-node 在內(nèi)存的轉(zhuǎn)譯結(jié)果不能運(yùn)行。

入口文件仍然必須是 .js 文件,這是個(gè)小小的遺憾,不過對(duì)于使用 Node.js 寫構(gòu)建腳本的用戶來說,有兩個(gè)好消息:gulp 和 webpack 都直接支持 .ts 入口(或配置)文件。比如以 gulp 為例,可以定義 gulpfile.ts (注意擴(kuò)展名是 .ts) 如下

import * as gulp from "gulp";

gulp.task("hello", () => {
    console.log("hello gulp");
});

不過 gulp 也是通過 ts-node 模塊來實(shí)現(xiàn)使用 TypeScript 的,而 ts-node 的功能依賴于 typescript,所以別忘了安裝這兩個(gè)模塊。

擴(kuò)展閱讀

從 JavaScript 到 TypeScript - 聲明類型

從 JavaScript 到 TypeScript - 泛型

從 JavaScript 到 TypeScript - 接口

關(guān)注作者的公眾號(hào)“邊城客?!?→

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/82387.html

相關(guān)文章

  • webpack實(shí)戰(zhàn)

    摘要:和類似的預(yù)處理器還有等。的用處非常多,包括給自動(dòng)加前綴使用下一代語(yǔ)法等,目前越來越多的人開始用它,它很可能會(huì)成為預(yù)處理器的最終贏家。 webpack實(shí)戰(zhàn) 查看所有文檔頁(yè)面:全棧開發(fā),獲取更多信息??祚R加鞭,加班加點(diǎn),終于把這個(gè)文檔整理出來了,順便深入地學(xué)習(xí)一番,鞏固知識(shí),就是太累人,影響睡眠時(shí)間和質(zhì)量。極客就是想要把事情做到極致,開始了就必須到達(dá)終點(diǎn)。 原文鏈接:webpack實(shí)戰(zhàn),原...

    cyrils 評(píng)論0 收藏0
  • 使用 TypeScript 改造構(gòu)建工具及測(cè)試用例

    摘要:第一個(gè)完全使用重構(gòu)的純項(xiàng)目已經(jīng)上線并穩(wěn)定運(yùn)行了。測(cè)試用例的改造前邊的改為大多數(shù)原因是因?yàn)閺?qiáng)迫癥所致。但是測(cè)試用例的改造則是一個(gè)能極大提高效率的操作。 最近的一段時(shí)間一直在搞TypeScript,一個(gè)巨硬出品、賦予JavaScript語(yǔ)言靜態(tài)類型和編譯的語(yǔ)言。 第一個(gè)完全使用TypeScript重構(gòu)的純Node.js項(xiàng)目已經(jīng)上線并穩(wěn)定運(yùn)行了。 第二個(gè)前后端的項(xiàng)目目前也在重構(gòu)中,關(guān)于前...

    Cristic 評(píng)論0 收藏0
  • [譯]學(xué)習(xí)如何去學(xué)習(xí) JavaScript - 5 個(gè)你應(yīng)該如何花在學(xué)習(xí) JS 上時(shí)間的建議

    摘要:擁抱異步編程縱觀發(fā)展史也可以說成開發(fā)的發(fā)展史,你會(huì)發(fā)現(xiàn)異步徹底改變了這場(chǎng)游戲??梢赃@么說,異步編程已成為開發(fā)的根基。這也是你應(yīng)盡早在上投入大量時(shí)間的一處核心知識(shí)點(diǎn),這其中包含和等重要概念。這也是最突出的一項(xiàng)貢獻(xiàn)。 原文地址:Medium - Learning How to Learn JavaScript. 5 recommendations on how you should spend ...

    wanglu1209 評(píng)論0 收藏0
  • 如何使用TypeScriptWebpack編寫網(wǎng)頁(yè)應(yīng)用

    摘要:所以,如果你也考慮開始使用,不妨也看一下。使用模塊中,模塊的使用方法與一致。安裝好定義文件之后,如果使用等對(duì)支持較好的編輯器,則會(huì)提供更加強(qiáng)大的代碼提示功能。如果使用配合的,則可以方便地構(gòu)建瀏覽器可以運(yùn)行的代碼。 TypeScript所做的,是在JavaScript的基礎(chǔ)上加入了類型,TypeScript編譯器將TypeScript編譯成JavaScript,可以在瀏覽器或者nodej...

    Codeing_ls 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<