1. 程式人生 > >VUE+TS+WEBPACK框架的專案實踐

VUE+TS+WEBPACK框架的專案實踐

一、作者簡介

WONDER專注於框架的研究,致力於提升效能,解放生產力。包括但不限於設計流程化,重構流程化,前端流程化,基於資料流、狀態流的自動化測試。致力於基於javascript語言的全平臺解決方案的研究(包括前端(vue為核心),後端(thinkjs為核心),終端(weex為核心、小程式為輔助)),目標以「技術引擎」的思想為業務側提供強勁動力和生產力。

二、前言

很久以前在WONDER讀書的時候,大家經常用記事本寫原生程式碼的能力作為一個人寫程式碼能力的評判標準。會對用jQuery+Dreamweaver(那個時候還沒有Webstorm這種神器)嗤之以鼻。回到現在,特別厲害的大神對一些框架也嗤之以鼻,對於一些框架的使用心得都拉入了演講主題的黑名單。

這些現象的本質是什麼,在於牛X的人認為使用這些框架的人「沒啥技術含量」,顯得不夠牛X,逼格不夠。但站在專案的角度和團隊的一致性角度,逼格高低who care。質量和效率才是第一位的要素。框架的深入研究和合理運用才是大勢。我們期待有一天,動動滑鼠就可以完成以前可能需要加班加點才能乾的活,剩下的時間陪陪家人,陪陪愛人,養養花花草草。

另外隨著最近AI智慧的興起,可以預見智慧程式設計和雲程式設計是未來的大勢所趨。讓我們開始打好基礎,迎接未來的變遷。

三、框架的選型

沒有什麼框架是全能的,都有其適用場景。我們的最初的定位一定要圍繞我們的業務來選擇。我們個性化業務是基於移動端的多頁面應用。我們綜合考慮之後,決定使用vuejs+typescript+webpack2來作為現在和將來的核心主框架,未來的演變也基於此基礎。

1、為什麼使用vuejs

早些年,前端的MVVM框架呈現爆發式的增長,比如angular,react,vuejs,avalon,meteor。對比過這些框架,最終選擇了vuejs作為我們業務的「核心引擎」。原因如下:

1)angular和react雖然火爆,但是學習曲線還是太陡了,需要理解很多東西,上手不易。vuejs上手非常容易,語法簡單。我們試驗過,一個有前端基礎但沒有接觸過vuejs的同學,基本上一天就可以上手開發簡單應用。幾天之內學會模組元件的概念基本就可以完成中等複雜的業務。這是其它框架無法相比的。

2)vuejs的文件是非常友好的,當然現在其它框架的文件建設也在加強。這也告訴我們一個東西是否能普及開,核心有兩點,一是本身足夠好用,二是足夠方便理解。vuejs做到了這點,所以它火了。

3)vuejs體積小適合移動端業務,vuejs在gzip壓縮後的程式碼是react的一半。而且移動端基本沒啥相容性問題。PC的話相容IE9+。如果是PC業務,其實我們現在也只是相容IE9+。把時間浪費在相容性問題上完全是浪費生命。所以現在的前端開發者,感謝這個時代吧。

4)vuejs最新的版本中也逐步借鑑學習了一些其它框架的優秀的思想,能學習和使用一種框架用到深處,我想是足夠滿足我們的業務需求的。

2、為什麼使用typescript

1)資料流結構規範化的重要性

在業務需求的中級階段,我們意識到資料流結構規範化的重要性。vuejs因為本質是MVVM框架,引入了資料流的概念。但JS是弱型別語言,資料流本身比較隨意,比如一個Button的屬性,基本屬性有按鈕文字(text),按鈕狀態(status),按鈕進度(process)等三個基本資料屬性。但是團隊中不同人可能有自己的想法,關於一個Button的定義命名都有可能不一樣。長期看來,註定無法維護。這時候資料結構的規範(介面,強型別)顯得非常重要。引入這些概念,對基本元件的定義和規範在程式碼編寫階段自然就形成了約定(不遵守規範,編譯都通不過),這比文件規範約束有效和方便得多。

typescript恰好就是為此類需求而誕生的,而且充分考慮到相容性。對之前JS的程式碼完全相容。

2)使用ES6/ES7特性,具有優秀的自編譯能力

很多ES6/ES7專案的編譯都是通過babel進行處理的,不熟悉的朋友可能整配置都要搞半天,而且babel還有babel5和babel6的區別,兩者也並不太相容。

typescript具有自編譯的能力,不需要額外引入babel。只依賴tsconfig.json,將此檔案放到專案的根目錄,即可全域性配置。

typescript不僅能滿足babel的編譯的功能,而且比babel做得更好。比如很重要的async/await語法,babel在使用的時候會引入相當大的一個檔案:

image.png-182kB

typescript則非常乾淨利落,就幾十行程式碼:

image.png-468.7kB

3)typescript2.0引入了@types,系統性地解決了絕大部分公共庫的型別定義問題

WONDER遲遲沒有在生產專案中使用typescript的一個很大的原因就是型別定義實在是太麻煩了。從DefinitelyTyped到typings,最後是@types。微軟自己也發現有這麼個問題,所以也在一直演進。目前來看,@types算是一個不錯的方案。充分利用npm進行管理和維護,且絕大多數公共庫都已經支援@types,比如@types/jquery、@types/node等。vue更先進一些,直接本身vue模組即支援typescript的型別定義。不需要額外的@types/vue。也就是npm install vue即可在typescript中正常使用。

3、為什麼使用webpack2

使用webpack2最核心的地方就是使用tree-shaking特性,tree-shaking是大勢所趨,符合程式碼極簡主義,提高程式碼使用率。對於程式碼的精簡還是挺高的,大概可以優化30%的程式碼體積。

要使用webpack2的tree-shaking,前提條件就是使用ES6的module,這是核心根本。所以意味著所有的程式碼要基於ES6的module來寫。建議從新專案入手,代價較小。

階段性小結:

1、使用vuejs,從資料驅動的角度來處理邏輯,操作DOM,可以完全拋棄zepto/jQuery

2、由於使用資料驅動,資料本身的結構由為重要,再加上方便優雅地使用ES6/ES7,我們引入了typescript作為主要開發語言

3、利用ES6的module的重構程式碼,通過webpack2的tree-shaking來達到簡化程式碼體積,提高程式碼利用率的目的。

四、專案實踐

從本章節起開始結合線上專案來講講框架的使用和細節。本次介紹的專案名叫「個性化體驗卡」。基本上藉助此專案從頭搭建了一套基礎底層,專案本身是多頁面專案。

1、專案結構

首先是專案結構,基本上只需要一個公共庫目錄和專案本身目錄即可。

image.png-262.9kB

公共庫目前搭基礎,包含common和shim兩個即可,這裡特別指出的是mqq的庫被重寫後,從原先的1400行,減少到200行。去除了相當多的無用程式碼,極簡風格。

專案本身目錄也很好理解:

common——專案的公共方法目錄,比如helper之類的
comp——專案的元件目錄,核心目錄。以後各個業務都是元件複用
css——CSS目錄,釋出時會inline到html中
html——入口檔案目錄,基本就是一個框架,如下圖所示:

image.png-384.3kB

由於tree-shaking的因素,我們的首屏業務邏輯程式碼可以直接inline到頁面當中,複雜的次屏邏輯可以以動態元件的形式載入。形成直出+主內嵌JS+非同步動態JS元件的優雅的載入模式。

細節提示:

這裡有個開發細節和大家講解一下,我們在上圖中,我把vuejs並沒有以模組的形式打入到detail.entry.js裡,因為一是額外增加了js的體積,二是我們的專案是多頁面的專案,公共vuejs是可以也有必要進行快取和複用的。

這裡採用外鏈離線包+強快取的形式是比較合理的。

2、配置檔案

初學者在做配置的時候一般比較蒙逼,所以有腳手架這麼個東西來幫助初學者快速搭好環境,但實際上每個人從事的專案不完全一樣。腳手架並不能完全滿足需求。所以瞭解一下配置的基本原理還是有相當必要的。

本文是基於vuejs、typescript、webpack2的框架,用gulp進行把幾個東西串起來。

因為文中的腳手架結合了一些專案本身的各種功能,等WONDER之後有時間抽離出來,再在本文進行更新。這裡先講幾個核心需要注意的點。

1)npm install 幾個最重要的模組

gulp、vue、vue-class-component、typescript、webpack、@types/node、ts-loader、text-loader

這幾個裝了以後,基本上專案用到的最核心模組都有了。

2)配置tsconfig.json

{
  "compilerOptions": {
    //語法編譯為es5語法
    "target": "es5",
    //模組採用import語法且不作轉換,轉換工作交給gulp任務中的webpack2
    "module": "es2015",
    //NPM模式載入
    "moduleResolution": "node",
    //對於沒有Export的庫進行相容
    "allowSyntheticDefaultImports": true,
    //開啟修飾器模式
    "experimentalDecorators": true,
    //識別基本的系統類庫
    "lib": [
      "dom",
      "es5",
      "es2015"
    ],
    "baseUrl": ".",
    "paths": {
    //這裡根據自己專案的情況指定alias目錄
      "lib/*": [
        "./litelib/*"
      ]
    }
  }
}

細節提示:

這個配置非常非常關鍵,建議初學者直接Copy(除paths根據自己專案指定外),每個配置都有用,我也寫了註解,不要隨意刪減。

3)webpack.config.js配置

image.png-167.6kB

細節提示:

注意紅框部分的地方,一定不要配置錯。

externals這樣寫的目的是不要把vue打包進來,一定要注意大小寫。大小寫不對就容易出錯。不理解的初學者直接Copy。

rules就只配這一個就可以了,其實就是對於模板html檔案的處理。由於我們的程式碼(IDEWebStorm自帶的特性)在編寫的時候就轉換成了js,所以webpack不需要加ts-loader。但最理想的狀態就是編譯過程交給webpack或gulp進行,IDE不自動編譯js檔案,這樣原始碼比較純粹。

3、vuejs的元件寫法

vuejs其實是一個很靈活的框架,可以有很多種寫法。vue的元件看官方文件也有很多寫法。但在typescript中,寫法和之前有很大變化(但其實和react、angularjs很像了)。如果不這麼寫,你會發現你的編輯器到處報錯。。So,目前我們線上專案中的元件大概長這個樣子:

image.png-313.8kB

這就是一個元件,如何使用呢,我們看入口檔案的JS。

image.png-64.5kB

更多細節可以參考官方DEMO:

這種寫法是很優雅和可維護的,以及配合typescript的特性,感覺非常的愉快!

4、編輯器的選擇

我們專案組的同學基本就兩種編輯器,一種是Webstorm,一種是vscode。其實Webstorm除了卡,其它都比vscode好用。

這兩種編輯器,Webstorm自帶編譯功能,所見即所得。配置好tsconfig.json,剩下都省心。vscode略複雜,需要建立一個task,然後在跑專案的時候執行build。也可以達到類似的效果。

5、環境搭建的坑

其實如果初學者前面不按照我說的一些細節來操作的話,很容易在搭環境上一堆編譯報錯,編輯器語法報錯。會影響初學者的學習熱情。所以WONDER這裡會儘量在抽離一個相對普適的腳手架給各位使用,盡請期待。

其實初學者按照我上述的配置操作的話,一般問題也不是太大。有遇到任何編譯報錯或者語法報錯,歡迎和WONDER交流,我也作下記錄。

6、相容性問題

專案實踐過程中,有些相容性問題這裡提出來。避免大家再踩。

1)首先關於Promise的相容性實踐證明如果你是基於手Q或微信的移動端業務,可以不需要引入Promise-Polyfill。PC端還是建議需要Promise-Polyfill。PC對檔案大小不敏感,所以加下polyfill無所謂。移動端沒有必要,主流都支援。目前線上業務也沒有收到什麼反饋頁面功能由相容性異常的。

2)有些寫法儘量不要用,WONDER已知的就是不要使用ES6的模板字串。

首先雖然我們配置了tsconfig.json,但是並不是所有的語法都轉成了ES5,模板字串就沒有完全轉義。在IOS8的系統裡面相容性有問題,模板會報錯,程式會出問題。

3)不要使用Object.assign,這個也不會轉義,在IOS8系統也有相容問題。而且也不是很優雅。WONDER找到一個優雅的寫法,就是使用ES6的三點解構符...,雖然這兩者並不完全相同,且三點解構符其實也並不是用在這裡的。只是結合我們的使用場景,比較巧妙。

我們使用最多的無非就是兩個object物件引數的合併。如果Object.assign有相容性問題,又不想寫諸如_.extend。那麼就試試這種寫法,如下所示:

image.png-43.8kB

我們看看typescript如何翻譯變成這裡的,對應的JS如下:

image.png-70.8kB

我們注意到__assign方法,其實就是翻譯了三點解構符。果然如此:

image.png-67.4kB

7、資料介面

這個是專案實踐過程中的細節了。interface這裡指的是資料介面,也就是我們熟知的DAO層。JS之前過於靈活,現在有typescript輔助,資料結構的定義會更加清晰和規範。不符合規範會報錯的。

image.png-268.5kB

然後無論如何format,模板那邊只focus這個介面的結構即可。

五、遺留問題

此框架還有繼續完善的地方,比如SSR部分(據說隔壁團隊已經研究出可以根據CPU負載的情況進行自動選擇是否是SSR還是非同步載入),多頁面的VUEX,輕量級腳手架,CSS部分的特性使用。這些問題下次高階篇再詳細介紹。