中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

為什么要用Babel編譯Typescript

發布時間:2022-04-19 16:15:43 來源:億速云 閱讀:170 作者:iii 欄目:移動開發

這篇文章主要介紹“為什么要用Babel編譯Typescript”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“為什么要用Babel編譯Typescript”文章能幫助大家解決問題。

typescript 給 javascript 擴展了類型的語法和語義,讓 js  代碼達到了靜態類型語言級別的類型安全,之前只能在運行時發現的類型不安全的問題,現在能在編譯期間發現了,所以大項目越來越多的選擇用 typescript  來寫。除此之外,typescript 還能夠配合 ide 做更好的智能提示,這也是用 typescript 的一個理由。

類型安全:如果一個類型的變量賦值給它不兼容類型的值,這就是類型不安全,如果一個類型的對象,調用了它沒有的方法,這也是類型不安全。反之,就是類型安全。類型安全就是變量的賦值、對象的函數調用都是在類型支持的范圍內。

最開始 typescript 代碼只有自帶的 tyepscript compiler(tsc)能編譯,編譯不同版本的 typescript  代碼需要用不同版本的 tsc,通過配置 tsconfig.json 來指定如何編譯。

但是 tsc 編譯 ts 代碼為 js 是有問題的:

tsc 不支持很多還在草案階段的語法,這些語法都是通過 babel 插件來支持的,所以很多項目的工具鏈是用 tsc 編譯一遍 ts 代碼,之后再由  babel 編譯一遍。這樣編譯鏈路長,而且生成的代碼也不夠精簡。

所以,typescript 找 babel 團隊合作,在 babel7 中支持了 typescript 的編譯,可以通過插件來指定 ts 語法的編譯。比如  api 中是這樣用:

const parser = require('@babel/parser');  parser.parse(sourceCode, {     plugins: ['typescript'] });

這個插件是 typescript 團隊與 babel 團隊合作了一年的成果。

但是,這個插件真的能支持所有 typescript 代碼么?答案是否定的。

我們來看一下 babel 不支持哪些 ts 語法,為什么不支持。

babel 能編譯所有 typescript 代碼么?

babel 的編譯流程是這樣的:

為什么要用Babel編譯Typescript

  • parser: 把源碼 parse 成 ast

  • traverse:遍歷 ast,生成作用域信息和 path,調用各種插件來對 ast 進行轉換

  • generator:把轉換以后的 ast 打印成目標代碼,并生成 sourcemap

而 typescript compiler 的編譯流程是這樣的:

為什么要用Babel編譯Typescript

  • scanner + parser:分詞和組裝 ast,從源碼到 ast 的過程

  • binder + checker:生成作用域信息,進行類型推導和檢查

  • transform:對經過類型檢查之后的 ast 進行轉換

emitter:打印 ast 成目標代碼,生成 sourcemap 和類型聲明文件(根據配置)

其實 babel 的編譯階段和 tsc 的編譯階段是類似的,只是 tsc 多了一個 checker,其余的部分沒什么區別。

  • babel 的 parser 對應 tsc 的 scanner + parser

  • babel 的 traverse 階段 對應 tsc 的 binder + transform

  • babel 的 generator 對應 tsc 的 emitter

那么能不能基于 babel 的插件在 traverse 的時候實現 checker 呢?

答案是不可以。

因為 tsc 的類型檢查是需要拿到整個工程的類型信息,需要做類型的引入、多個文件的 namespace、enum、interface 等的合并,而  babel 是單個文件編譯的,不會解析其他文件的信息。所以做不到和 tsc 一樣的類型檢查。

一個是在編譯過程中解析多個文件,一個是編譯過程只針對單個文件,流程上的不同,導致 babel 無法做 tsc 的類型檢查。

那么 babel 是怎么編譯 typescript 的呢?

其實 babel 只是能夠 parse ts 代碼成 ast,不會做類型檢查,會直接把類型信息去掉,然后打印成目標代碼。

這導致了有一些 ts 語法是 babel 所不支持的:

  • const enum 不支持。const enum 是在編譯期間把 enum 的引用替換成具體的值,需要解析類型信息,而 babel  并不會解析,所以不支持。可以用相應的插件把 const enum 轉成 enum。

  • namespace 部分支持。不支持 namespace 的跨文件合并,不支持導出非 const 的值。這也是因為 babel  不會解析類型信息且是單文件編譯。

上面兩種兩個是因為編譯方式的不同導致的不支持。

  • export = import = 這種 ts 特有語法不支持,可以通過插件轉為 esm

  • 如果開啟了 jsx 編譯,那么

這四種就是 babel 不支持的 ts 語法,其實影響并不大,這幾個特性不用就好了。

結論:babel 不能編譯所有 typescript 代碼,但是除了 namespace 的兩個特性外,其余的都可以做編譯。

babel 是可以編譯 typescript 代碼,那么為什么要用 babel 編譯呢?

為什么要用 babel 編譯 typescript 代碼?

babel 編譯 typescript 代碼有 3 個主要的優點:

產物體積更小

tsc

tsc 如何配置編譯目標呢?

在 compilerOptions 里面配置 target,target 設置目標語言版本

{     compilerOptions: {         target: "es5" // es3、es2015     } }

typescript 如何引入 polyfill 呢?

在入口文件里面引入 core-js.

import 'core-js';

babel7

babel7 是如何配置編譯目標呢?

在 preset-env 里面指定 targets,直接指定目標運行環境(瀏覽器、node)版本,或者指定 query 字符串,由  browserslist 查出具體的版本。

{     presets: [         [             "@babel/preset-env",             {                 targets: {                     chrome: 45                 }             }         ]     ] }
{     presets: [         [             "@babel/preset-env",             {                 targets: "last 1 version,> 1%,not dead"             }         ]     ] }

babel7 如何引入 polyfill 呢?

也是在 @babel/preset-env 里面配置,除了指定 targets 之外,還要指定 polyfill 用哪個(corejs2 還是  corejs3),如何引入(entry 在入口引入 ,usage 每個模塊單獨引入用到的)。

{     presets: [         [             "@babel/preset-env",             {                 targets: "last 1 version,> 1%,not dead",                 corejs: 3,                 useBuiltIns: 'usage'             }         ]     ] }

這樣可以根據 @babel/compat-data 的數據來針對的做語法轉換和 api 的 polyfill:

先根據 targets 查出支持的目標環境的版本,再根據目標環境的版本來從所有特性中過濾支持的,剩下的就是不支持的特性。只對這些特性做轉換和  polyfill 即可。

為什么要用Babel編譯Typescript

而且 babel 還可以通過 @babel/plugin-transform-runtime 來把全局的 corejs 的 import  轉成模塊化引入的方式。

顯然,用 babel 編譯 typescript 從產物上看有兩個優點:

  • 能夠做更精準的按需編譯和 polyfill,產物體積更小

  • 能夠通過插件來把 polyfill 變成模塊化的引入,不污染全局環境

從產物來看,babel 勝。

支持的語言特性

typescript 默認支持很多 es 的特性,但是不支持還在草案階段的特性,babel 的 preset-env 支持所有標準特性,還可以通過  proposal 來支持更多還未進入標準的特性。

{     plugins: ['@babel/proposal-xxx'],     presets: ['@babel/presets-env', {...}] }

從支持的語言特性來看,babel 勝。

編譯速度

tsc 會在編譯過程中進行類型檢查,類型檢查需要綜合多個文件的類型信息,要對 AST 做類型推導,比較耗時,而 babel  不做類型檢查,所以編譯速度會快很多。

從編譯速度來看, babel 勝。

總之,從編譯產物大小(主要)、支持的語言特性、編譯速度來看,babel 完勝。

但是,babel 不做類型檢查,那怎么類型檢查呢?

babel 和 tsc 的結合

babel 可以編譯生成更小的產物,有更快的編譯速度和更多的特性支持,所以我們選擇用 babel 編譯 typescript  代碼。但是類型檢查也是需要的,可以在 npm scripts 中配一個命令:

{     "scripts": {         "typeCheck": "tsc --noEmit"     } }

這樣在需要進行類型檢查的時候單獨執行一下 npm run typeCheck 就行了,但最好在 git commit 的 hook 里(通過 husky  配置)再執行一次強制的類型檢查。

關于“為什么要用Babel編譯Typescript”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

枣强县| 孝义市| 保靖县| 和政县| 贵港市| 新泰市| 望江县| 木里| 九龙坡区| 永春县| 敦化市| 大庆市| 岑巩县| 连州市| 玉田县| 宜宾市| 五家渠市| 河池市| 杂多县| 福鼎市| 积石山| 江华| 嘉兴市| 灵宝市| 汝阳县| 施甸县| 宜川县| 和顺县| 海安县| 盘锦市| 揭阳市| 南漳县| 胶州市| 肥东县| 泰和县| 秦皇岛市| 前郭尔| 富顺县| 衡阳市| 平山县| 民丰县|