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

收錄待用,修改轉載已取得騰訊雲受權前端


導語

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

1、前言

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

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

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

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

2、代碼優化方向

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

一、代碼冗餘。咱們常常引入了一個大的utils庫,實際上只是引用了這個庫中的一個方法,可是卻打包了整個庫,代碼的冗餘和浪費。隨着引入的文件愈來愈多,這種問題也會變得愈來愈明顯。不管是基於代碼潔癖,仍是代碼體積來看,都有優化的必要。瀏覽器

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

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

3、代碼優化實施

一、優化方向一,其實經過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%。

二、優化方向二,在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語法,咱們看到實際編譯的文件仍是很大的:

此問題待解決。

4、配置以及DEMO

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

一、webpack.config.js,因爲是webpack2,和webpack並不徹底同樣,這裏須要修改兼容一下。

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

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

四、因爲進行Babel編譯估計比較慢,建議開發階段不要開Babel編譯。如今的Chrome瀏覽器55版本以上都支持async/await語法,在開發模式中PC模擬調試的時候,徹底能夠不開Babel編譯。在進行真機調試的過程當中,IOS的最新瀏覽器和Android新系統的最新瀏覽器也都是支持async/await語法的,也不用編譯。

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

http://static.zybuluo.com/wwanghee/atuflxa5zj7jkgnc2n6tgup0/async_await.zip

下載以後運行

npm install
webpack //無壓縮版
webpack --optimize-minimize //壓縮版

原文連接:https://www.qcloud.com/community/article/608654

相關文章
相關標籤/搜索