Vue.js前後端同構方案之準備篇——代碼優化

歡迎大家關注騰訊雲技術社區-知乎官方機構號,我們將持續在知乎為大家推薦技術精品文章哦~

作者:王鶴

導語

目前Vue.js的火爆不亞於當初的React,本人對寫代碼有潔癖,代碼也是藝術。此篇是準備篇,工欲善其事,必先利其器。我們先在代碼層面進行優化,對我們完成整個技術架構是起到基礎作用的。此準備篇是獨立的,即使你們的項目不使用Vue.js,也不影響文章的閱讀,是代碼的基礎優化。

一、前言

目前Vue.js的火爆不亞於當初的React,本人對寫代碼還是有一定潔癖的,代碼也是藝術。很長時間在找尋最適合自己的前端開發框架,包括在React最火的時候,我依然在堅持尋找,但React在我心目中並不完美。認識Vue.js的時候,Vue還是1.0階段,發現其理念和我心目中的理念相當接近。

文檔友好,API簡潔易懂,申明式的模板(我的最愛),MVC的架構,同步/非同步組件化等等。一路跟隨Vue.js走來,從1.0到2.0,逐步成為世界級的JS框架。作為見證者還是挺開心的。

我們最新上線的項目是基於Vue的前端後端同構一體化實現的,運用了SSR(Sever Side Render)。從代碼的編寫和維護角度上,已經比較不錯了。而且本身Vue.js的開發效率就很高,所以目前我們團隊還會在這塊繼續深挖。

此篇是準備篇,工欲善其事,必先利其器。我們先在代碼層面進行優化,對我們完成整個技術架構是起到基礎作用的。此準備篇是獨立的,即使你們的項目不使用Vue.js,也不影響文章的閱讀,是代碼的基礎優化。

二、代碼優化方向

技術選型沒有最好的,只有最適合業務的。目前我們的業務是用gulp+webpack打包構建的。目前有幾個痛點:

1、代碼冗餘。我們經常引入了一個大的utils庫,實際上只是引用了這個庫中的一個方法,但是卻打包了整個庫,代碼的冗餘和浪費。隨著引入的文件越來越多,這種問題也會變得越來越明顯。無論是基於代碼潔癖,還是代碼體積來看,都有優化的必要。

2、非同步流程式控制制。隨著JS前端的發展,我們站著大牛的肩膀上,逐步擺脫了回調地獄,以及各種非同步流程的坑。有著目前來看最好的非同步流程解決方案「async/await方案」。Node 7.6版本已經正式支持了此特性,Browser端也可以統一,達到前後端同構的目的。清晰的非同步流程式控制制對於團隊代碼的理解和維護都有著積極的意義。

3、代碼潔癖的考慮,引入箭頭函數,簡化代碼。利用箭頭函數不綁定this的特性,解決this「漂移」問題。

三、代碼優化實施

1、優化方向一,其實通過tree-shaking的能力就可以做到了。我們使用Webpack2來實現我們tree-shaking的能力。但這裡我們要注意一定要用ES6的import/export來實現。代碼如下:

  • ./src/invoke.js

//模塊的繼承

export * from ./invoke_base.js;

//定義變數或常量

const xxx = 1;

//定義私有函數

function _private(){

//

}

//定義公有函數

export function aaa() {

console.log(1);

}

export function bbb() {

console.log(2);

}

export default function ccc(){

console.log(3);

}

  • ./src/invoke_base.js

export function ddd() {

console.log(4);

}

  • ./src/tree_shaking.js

import * as uu from ./invoke.js;

console.log(uu.ddd);

改造好代碼後,通過執行webpack命令,我們可以得到如下結果:

注意一下紅框部分的內容,在非壓縮模式下,實際上並不是完全意義上的tree-shaking,還是有把沒有使用的方法打入文件中,但是會提示「unused harmony export」這樣的提示。

然後我們執行一下webpack的壓縮命令:

壓縮代碼中只有「console.log(4)」,也就是aaa, bbb, ccc這三個被標記為「unused harmony export」的方法在壓縮版本中移除了,只有ddd由於被引用,所以保留了。證明我們的tree-shaking是成功的。而且要看到ddd是基類模塊的方法,證明在繼承的情況下,tree-shaking也是正確執行的!

盡量使用import * as uu from ./invoke.js隱式語法而無須使用import {ddd} from ./invoke.js這種顯式語法。

使用前者非常方便的在調用的時候使用uu.xxx這種寫法,而且tree-shaking是可以正確解析的。比如代碼中只調用了uu.ddd,那麼uu.aaa, uu.bbb, uu.ccc是可以tree-shaking過濾掉的。而不用特意地指定import {ddd} from ./invoke.js

這種隱式的寫法極大的方便了我們代碼的靈活性。而不需要調用一個,我就要在import的地方顯式的加一個!看,一切都很美好。tree-shaking是很智能的!

階段性小結:

1)用import/export來改造代碼,這是tree-shaking的基礎,ES6的模塊支持繼承,可以正確執行tree-shaking。

2)webpack的打包非壓縮的情況下會保留unused function,壓縮版才會真正去掉。

3)盡量使用import * as uu from ./invoke.js隱式語法而無須使用import {ddd} from ./invoke.js這種顯式語法。

4)我們的業務接入tree-shaking特性後,代碼體積有減少30%。

2、優化方向二,在Browser側我們的非同步流程式控制制其實並沒有特別複雜,畢竟使用場景上還是沒那麼多的回調地獄。通常我們的解決方案就是簡單地就用回調處理,複雜的邏輯,可能有用類似Step.js,Async.js這種類庫來解決。代碼從可讀性上還是可以的,比如:

這個示例中綜合了同步和非同步代碼,從代碼的表現形式上還是可以理解為同步的流程。但這種類庫本質還是callback的方式,採用Promise的方式是我們未來的趨勢,而且直接上Async/Await方案,爭取一步到位。改造後我們的代碼可以類似如下圖所示:

類比可以看出,我們的代碼在可讀性上又上了個台階。會有種擺脫了垃圾代碼的舒暢感。

在後端Node 7.6已經正式支持了async/await語法,所以後端直接升級即可。在前端而言,我們這裡還是有不少工作要做的。(不想看過程的朋友,直接下載本文結尾的DEMO自行實踐)

1)首先我們的瀏覽器端對Promise對象還有兼容問題:

我們必須引入Promise-polyfill才能安心在瀏覽器端使用。經過我們業務的實踐和篩選,我們最終選擇了這個taylorhakes/promise-polyfill,這個Promise-polyfill的優點是代碼少,該有的核心方法都有,滿足我們的業務需要。不要使用Babel自帶的poly-fill,代碼太冗餘了。所以我們在文件中引入:

import Promise from promise-polyfill;

2)其次我們要通過Babel來翻譯async/await語法,Babel翻譯前:

Babel翻譯後:

其實這樣看起來並沒有特別的差別,但這樣運行是會報錯的。會提示:

這裡主要是缺少regeneratorRuntime的定義,所以我們需要人為的補上去,在文件頭部引入:

import "regenerator-runtime/runtime";

就可以愉快地在前端使用async/await啦

階段性小結:

1)需要配置好webpack.config.js以及babel的配置,這個參考DEMO。

2)在需要進行async/await的文件引入

3)雖然可以支持瀏覽器的async/await語法,我們看到實際編譯的文件還是很大的:

此問題待解決。

四、配置以及DEMO

參考DEMO來看,有些配置的地方還是要注意一下的。

1、webpack.config.js,由於是webpack2,和webpack並不完全一樣,這裡需要修改兼容一下。

2、.babelrc的配置推薦使用babel-preset-env,這是目前最新的解決方案,會非常靈活的通過參數指定來兼容當前的環境。

3、一定要升級最新的正式版的webpack2,beta版的webpack2有一些BUG會導致編譯不過。

4、由於進行Babel編譯估計比較慢,建議開發階段不要開Babel編譯。現在的Chrome瀏覽器55版本以上都支持async/await語法,在開發模式中PC模擬調試的時候,完全可以不開Babel編譯。在進行真機調試的過程中,IOS的最新瀏覽器和Android新系統的最新瀏覽器也都是支持async/await語法的,也不用編譯。

所以做兩個webpack文件是一個方法,比如webpack.dev.config.js以及webpack.config.js。我們編譯的過程放到提測階段即可。這樣節省開發編譯的時間和效率,這是個小技巧。

static.zybuluo.com/wwan

下載之後運行

npm install

webpack //無壓縮版

webpack --optimize-minimize //壓縮版

相關閱讀

react渲染性能優化

騰訊工程師們怎麼玩 Vue.js?

vue.js 初體驗— Chrome 插件開發實錄

此文已由作者授權騰訊雲技術社區發布,轉載請註明文章出處

原文鏈接:Vue.js前後端同構方案之準備篇--代碼優化 - 騰雲閣 - 騰訊雲

獲取更多騰訊海量技術實踐乾貨,歡迎大家前往騰訊雲技術社區
推薦閱讀:

[譯]Web 的現狀:網頁性能提升指南
node.js-腳本合併

TAG:Vuejs | 前端框架 | 前端性能優化 |