1. 程式人生 > >TypeScript——Web前端開發的救贖

TypeScript——Web前端開發的救贖

JavaScript程式碼有多爛?     入職到現在做了6年js開發了(包括之前的2年一共寫了8年js),現在我們團隊有10幾20號人寫js(純js開發),需要維護的js程式碼有40-50萬行,不得不承認js程式碼的維護成本很高,或者直接說“js程式碼就是垃圾程式碼”,現在我們仍每天在製造大量的垃圾。     javascript開發要克服很多缺陷,作為團隊建設,儘管我們經常組織走讀程式碼、抓函式變數命名、抓各種規範,希望使大家寫程式碼的風格一致,但還是會產生很多垃圾程式碼,原因大家都知道(專案工期是最大的敵人);而這些垃圾很難會有重構的機會,不一定是有bug,只是難以讀懂,很難由別人去新增或者修改功能。由於JS是弱型別且執行時編譯的指令碼,從工具層面上很難對程式碼重構提供幫助:一個函式或變數,很難知道它被什麼地方呼叫著(新晉IDE Webstorm做的不錯但是遠遠不夠),所以即使是重新命名一個變數(你敢不敢用全文批量替換?),都會有很大風險,你會畏懼這種改動;開發工具甚至無法幫你檢查拼寫錯誤,也就是說,你改動的程式碼至少必須執行一次(程式碼要高度覆蓋執行),否則你根本就不能確定重構程式碼沒有產生影響。完整的重構流程可以減少風險,但是規劃版本、建立分支、分配測試資源等都是成本。所以簡單到像函式命名這麼小的問題,但也就那樣吧,只要沒人追究就不必改了,久而久之……     曾經覺得,只要貫徹大家寫單元測試,寫好註釋生成文件,就能使專案可維護度大大提示(確實也有幫助),但是這些測試程式碼、註釋本身也有很大的編寫成本,在工期緊張的時候根本無暇顧及(除非你本身非常熟悉寫單元測試和優雅的程式碼結構及註釋,但是這個素質培養週期太長了),而這些工作很難從後期補救(垃圾程式碼的特徵就是很難被程式測試,很難組織成文件T_T),還有一個問題更是糾結,測試程式碼也需要維護,也有垃圾的測試程式碼,這就變成一個死迴圈無解了。    JavaScript的替身
JS“爛”,引發業界的各種吐槽,很多團隊在發明JS的替身,如:coffeescript,google的dart,以及微軟的typescript等等,這三種程式碼都可以直接編譯成js。這其中,coffeescript語法簡捷(同時使用縮排替代花括號),受到Ruby、Python開發人員的追捧。Google的Dart,只能說它是一門全新的語言,Google為它開發虛擬機器(內建在Chrome中),也可以作為服務端開發語言,但是對js的相容程度比較差,一個hello world編譯成js居然會有3萬行程式碼(前端js可是惜字如金),所以Dart作為前端web開發,只能算是它的業餘愛好。微軟的typescript(下面簡稱ts)則完全另闢蹊徑,目前沒有直接執行ts的虛擬機器(以後可能會有),只能編譯成js執行,也就是說它適用於任何能執行js程式碼的場景作為開發語言。     微軟的“陰謀”?
微軟對作業系統的把持,以至於她失去了網際網路時代的第一桶金,直到現在微軟都不是一家網際網路公司。早期微軟對js這門語言有自己的獨特見解:“js是一門簡潔,c風格語法的指令碼工具,js能做的vbscript也能做,所以ie裡的靜態指令碼和asp的動態指令碼都可以同時用vbs和js來寫(可是vbs是微軟的親兒子啊),到後來.net生態都有JS.NET這種東西”。對於web前端開發,在微軟強大的visual studio開發環境下,js的支援度卻如屎一樣渣,甚至像Dreamweaver這種業餘編碼工具都能夠爆掉vs(除錯功能除外),直到vs2012才有了飛躍性的改變。     不可否認,微軟仍是這個星球上開發工具做的最好的公司。2009年開始的HTML5潮流使得微軟不得不重視JS開發,所以後來windows 8選擇js作為預設的app開發語言,vs2012對js的支援度終於達到專業選手的級別(從無數細節上反映),可是微軟內部不會不知道js存在缺陷,它不適合構建大規模應用開發。所以我猜想:TypeScript的發明是在2010年就開始了(甚至更早),而ts的誕生,象徵著微軟對js的態度從曖昧->擁有->到超越的3級跳躍。     TypeScript的閃亮登場
2012年10月首度對外公佈typescript(當時已經是0.7?的版本)同時開源,ts的編譯器是用js編寫的(後來改成ts?),可以線上編寫。     與coffeescript這些屌絲開發語言不同,ts的團隊是由C#之父安德斯·海爾斯伯格帶領,響應內部呼聲而建立的工具語言(內需轉出口),從無數細節和舒適度上,可以讓你的js專案完美遷移到ts上。1年前剛推出的時候,我只是覺得眼前一亮,然後就沒有然後了,過了一年,在我休假的這段時間內重新研究,有了翻天覆地的改觀,讓我用一句話形容TS:Typescript是微軟內部出品的,用actionscript的語法在寫js的一門新語言,vs用類似對c#的支援度來服務ts的開發,ts團隊做了很多努力可以讓你的js專案無痛升級到ts環境,使用ts開發,可以大量減少你檢查語法、查閱API、除錯程式碼的時間,ts能將你從開發js的痛苦深淵中解脫。以下從各方面描述ts為我們帶來的便利。     JS的初學者吐槽 js普及,支援的開發工具眾多,大多數開發人員使用他們最熟悉的編輯器來寫js程式碼(有用vim的,美工用dreamweaver,有的java開發人員用eclipse,.net開發人員用vs……),學生時代我用windows記事本寫js(大多數人不會懂機器慢的人喜歡用記事本體驗流暢感那種心情,後來換了電腦,用vs開發讓我有種暴發戶的感覺,主要原因還是因為我寫c#),當然所有開發工具都不會告訴你哪個變數拼寫錯誤,當你花幾個小時才定位到是拼寫問題的時候……可能論壇上罵js垃圾的人就有你的身影,我剛開始學的時候也不知道怎麼除錯,硬是一行行的alert(),現在知道那叫插樁程式碼(某些情況我現在還會用),以前哪有chrome這麼強大的東西,當然我沒工作前也不知道vs能除錯js程式碼。    總結一下初學者的吐槽原因:1.工具支援度差,容易犯低階錯誤;2.什麼BOM DOM API基本不熟,標準化的東西文件差勁,並且需要花大量時間學習各種瀏覽器下的差異化,大多數人覺得那是浪費生命;並且很多年過去了,工具、類庫支援度日益強大的今天,仍有不少人對js還是原來最初的印象。ts是“強型別”的js,不會讓你為這些低階錯誤浪費時間。    寫ts你不用煩惱用什麼開發工具了,直接就是vs(當然這也是硬傷,用linux的人傷不起,對微軟反感的人傷不起,機器配置差傷不起,window xp傷不起,vs2012要win7以上才能安裝,不過現在Webstorm和vim都已經添加了對Typescript的支援,雖然可能不及vs強大,但是對於ts的支援度肯定好於現在任何編輯器對js的支援度),最低的配置當然是windows記事本+編譯器,編譯器是js寫的,跨平臺。可以直接從官網下載msi安裝包,或者直接用npm命令安裝。(安裝vs2012+ts擴充套件最好了,vs2012從微軟官網下載安裝,貌似也不會提示你需要註冊什麼的,直接能用,不然用免費版的簡裝vs也支援ts)     
  Typescript的學習門檻 學習js的前提是,建議是你至少有一年以上js的開發經驗,然後:    如果你學過actionscript3,那麼你大概半天就可以學會基本的ts開發,因為ts的語法和as非常接近;    如果你學過java,C#,PHP(同時有js基礎),那麼大概一天可以掌握基本的ts開發;    如果你沒有as和java,c#的開發經驗,那麼其實說明你專注於js開發,你可以一邊寫ts一邊檢視編譯後的js程式碼,更能很快了解整個ts的工作原理。    Javascript程式碼就是Typescript程式碼  js和as的語法都源自ECMAScript標準,所以二者高度相容,ts同樣符合ECMAScript的標準,ts是js的超集,甚至你把xxx.js檔名改成xxx.ts,那麼它就是ts程式碼檔案了。    不用記API了——強型別的DOM API,jQuery,Backbone,NodeJs 資深js開發都瞭解,js語言層面上的知識量很少,然後就是記海量的API,做web開發記瀏覽器API,HTML5 API以及API支援程度,瀏覽器差異性等;做遊戲開發要記住遊戲引擎的API;做nodejs開發要記住node的api;因為編輯器的支援力弱,所以一個JS開發人員體現效率的一方面,就是看他記住了多少常用的API:包括瀏覽器內建的API、第三方的(比如google map),jquery再易用你也得記住一些API(常備一個api文件),而我用了jquery五六年能記住的API肯定沒有50%。另一方面一門追求效率,程式碼要精簡(頻寬需要)的弱型別指令碼,各種非OO式的api設計以及文件的可讀性肯定會非常差勁,這也是眾多吐槽點之一(這裡在強烈鄙視nodejs的官方文件)。    那麼做ts開發,我是否需要準備一個強型別的Typescript程式碼寫的jQuery類庫?但是像jQuery這種大眾化類庫,追求程式碼精簡程度是必要的,不可能用ts重寫一遍(ts編譯後的js雖然不臃腫,但也不是超級精簡)。Typescript團隊提供了一套虛構宣告語法,可以把現有的程式碼API用標頭檔案的形式描述出來,xxx.d.ts(d.ts命名提醒vs這種檔案不需要編譯)這套虛構定義語法,讓你不需要去實現函式體裡的程式碼,類似定義interface和抽象類。     
     按照這種方式,可以把你目前的js專案裡的api全部定義出來(不改動原來的程式碼),然後專案裡新增加的程式碼就可以用ts來開發了(我現在也是這樣幹)。 這個地址有常用js類庫的ts介面定義標頭檔案,閱讀這些標頭檔案甚至比直接讀這些類庫官方提供的文件更有效率。 更有價值的是ts內建了DOM和BOM API的介面定義檔案(預設引用):lib.d.ts,你再也不用記住海量的DomAPI和其它HTML5 API了              
  高階特性之函式過載(常量引數過載)—— 事件驅動強型別化 Javascript在各種環境都是被設計成事件驅動的開發方式,但是不同於c#,js裡面沒有強型別的事件,大部分都是通過函式加特定的事件名一起工作的,比如window.addEventListener("事件名",func),jQuery.bind("事件名",func),Backbone.View.on("事件名",func),但是作為一個類庫提供者,你怎麼讓別人知道你的物件支援多少種事件呢?每個事件回撥函式的引數列表又是怎樣? 上面兩個截圖就很清晰的告訴你,addEventListener這個函式是過載的,有62種引數方式,很直接地告訴你window物件支援繫結多少種事件,且回撥函式也強型別化了,這樣,甚至是初學者也不需要去查閱w3c的dom api文件也能開發了。我們的團隊使用Backbone開發,大量地使用了backbone的事件驅動,所以這個特性真是令人雞凍不宜。    強型別JSON,視覺化WebAPI  ts實際上也鼓勵你把JSON強型別化,那麼你在做web開發的時候再也不用記憶一些資料實體的屬性拼寫,vs內建支援把一段JSON自動轉化為宣告好的interface(複製一段json->在編輯器裡右鍵->選擇性貼上->把JSON貼上為類,這裡不確定是不是Web Essentials這個vs外掛給你新增的功能),我用nodejs寫了一個代理指令碼,自動抓取介面資料,然後自動生成所有json的interface宣告,這些json宣告真正是一次編寫到處引用,因為interface只是作為你開發和編譯時候的型別檢查依據,生成js以後毫無痕跡,所以不管前端js(pc或手機)還是後臺nodejs都能使用。       
編譯成js後
    
 如何將目前的js專案程式碼遷移到ts上?   1、先用偽宣告(xxx.d.ts)把專案的公共類庫定義好;(可以進行微重構,遮蔽私有屬性和方法,遮蔽不建議使用的方法)   2、新模組的程式碼全用ts來寫;(新程式碼與老的js隔離,不產生相互依賴,擁有很大的重構性)   3、慢慢把老的模組重寫成ts,然後替換xxx.d.ts;   4、全新的專案完全可以直接用ts開發。    自動化構建你ts專案裡的指令碼,以至在打包的時候能全域性性的再次編譯(單個編譯的方式容易在依賴程式碼更新後產生編譯錯誤)    可以借鑑以下文章:百度《我用TypeScript 語言的七個月》    最終之言:可以重構的程式碼勝於一切  以上我略過了很多ts的基礎知識,你可以從官網中學習如何開始ts的體驗:安裝vs2012 -> 安裝Typescript for vs2012的外掛 -> 建立一個Typescript HTML App工程,然後開始你的ts體驗之旅,也可以直接用線上版的ts編輯器進行ts編碼體驗:http://www.typescriptlang.org/Playground/    vs對於ts的支援非常強大,不過最方便的還是轉到定義(F12)和查詢所有引用的功能以及全域性自動重新命名物件,這個是弱型別語言無法具備的功能,是重構程式碼的重要依靠。    用ts寫程式碼,你可以儘快把功能完成,然後不斷地迭代重構程式碼,這種開發模式可以響應快速的需求,又能保證程式後續的生命力。     再安裝一個vs外掛,2.9版本,就可以左右分欄,左邊是ts,右邊是js,儲存自動編譯(必須是2.9版本,3.0版本作者已經移除了ts的支援,由於ms的要求詳見http://vswebessentials.com/changelog)     http://vswebessentials.com/nightly/webessentials2012-2.9.vsix     如果不安裝外掛,也可以讓ts在儲存的時候自動編譯,需要對vs進行一下配置。