『翻譯』基於 Vue.js 與 Webpack 的三種代碼分割範式

原文連接:3 Code Splitting Patterns For VueJS and Webpackhtml

前言

代碼分割是提高單頁應用初始加載速度的重要方式之一。由於用戶不用在第一次進入應用時下載全部代碼,用戶能更快的看到頁面並與之交互。這會改善用戶體驗,尤爲在移動端;並且這對 SEO 有很大幫助,由於 Google 會下降加載速度慢的網站權重。vue

上週我寫了一篇關於Vue.js 與 Webpack 如何分割代碼的文章,長話短說,每一個組件都封裝在單個文件中,那很容易分割代碼,當你導入模塊時,Webpack 能夠建立一個分割點,而且 Vue 也能夠很方便的加載一個異步組件。webpack

我認爲代碼分割最困難的部分不是如何讓它工做起來,而是什麼時候何地讓它工做。我想說,當設計你的應用時,就要將代碼分割做爲架構考慮進去。web

在這篇文章中,我將介紹目前 Vue.js 的三種代碼分割方式:vue-router

  • By page(按照頁面切分)bootstrap

  • By page fold(按照頁面的可見區域摺疊切分)
    sxsa架構

  • By condition(按條件加載)

注:這篇文章最初於2017/07/08發表在Vue.js開發博客上。異步

1.By page(按照頁面切分)

按照頁面切分是思路最清晰的。這個簡單的應用有三個頁面:網站

咱們假設每一個組件都是一個單獨的文件,好比:Home.vue, About.vueContact.vue,而後咱們可使用 Webpack 的動態 import(dynamic import) 功能拆分紅單獨的構建文件。當用戶訪問不一樣頁面時,Wenpack 會異步加載並請求改頁文件。ui

若是你使用 vue-router,這很容易實現,由於你的頁面已經在單獨的組件裏了。

const Home = () => import(/* webpackChunkName: "home" */ './Home.vue');
const About = () => import(/* webpackChunkName: "about" */ './About.vue');
const Contact = () => import(/* webpackChunkName: "contact" */ './Contact.vue');
const routes = [
  { path: '/', name: 'home', component: Home },
  { path: '/about', name: 'about', component: About },
  { path: '/contact', name: 'contact', component: Contact }
];複製代碼

看看咱們編譯代碼時的統計數據,每一個頁面都在它們本身的文件裏,但要注意到有個重要的bundle文件叫 build_main.js,它包含了全部的公共代碼以及異步加載其餘文件的邏輯。不管用戶訪問哪一個路由,都必須先加載它。

如今我訪問 http://localhost:8080/#/contact 加載 Contact 頁面,我查看 Network 菜單,發現下列文件被加載:

注意 build_main.js 這一欄的 initiator 值爲 (index)。這意味着 index.html 請求了這個腳本,這正是咱們所期盼的。可是 build_1.jsinitiator 倒是 bootstrap_a877…,這是 Webpack 腳本負責的異步加載文件。當你使用 Webpack 的動態導入功能,這個腳本會自動加入構建。最重要的一點是: build_1.js 不會阻塞初始頁面的加載。

2.By page fold(按照頁面的可見區域摺疊切分)

摺疊如下(Below the 「fold」)表明頁面初始時不可見的部分。你能夠異步加載這些內容,由於用戶一般須要一兩秒鐘才能閱讀完摺疊以上的內容,尤爲是在第一次訪問站點時。

在這個實例應用中,我考慮把摺疊線設在刊頭下。那麼讓咱們在頁面初始化時加載導航欄和刊頭,它們之下的全部內容,稍後再加載。我會建立一個名叫 BelowFold 的組件,提取出相關的代碼以下:

Home.vue:

<template>
  <div>
    <div class="jumbotron">
        <h1>Jumbotron heading</h1>
        ...
    </div>
    <below-fold></below-fold>
    <!--All the code below here has been put into-->
    <!--into the above component-->
    <!--<div class="row marketing">
      <div class="col-lg-6">
        <h4>Subheading</h4>
        <p>Donec id elit non mi porta gravida at eget metus. Maecenas faucibus mollis interdum.</p>
        ...
      </div>
      ...
    </div>-->
  </div>
</template>
<script>

  const BelowFold = () => import(
    /* webpackChunkName: "below-fold" */ './BelowFold.vue'
  );
  export default {
    ...
    components: {
        BelowFold
    }
  }
</script>複製代碼

BelowFold.vue:

<template>
  <div class="row marketing">
    <div class="col-lg-6">
      <h4>Subheading</h4>
      <p>Donec id elit non mi porta gravida at eget metus. Maecenas faucibus mollis interdum.</p>
      ...
    </div>
    ...
  </div>
</template>複製代碼

當咱們編譯代碼時,能夠看到 below-fold 被打包成了單獨的文件:

提示:below-fold 小到只有1.36k,看起來彷佛不值得把它單獨分離出來。由於如今只是一個很小的演示應用。在真實的應用中,頁面的大部份內容都在摺疊如下,所以可能有大量的代碼,它包括 JSCSS 以及全部子組件。

3.By condition(按條件加載)

另外一個選擇方案是按條件加載。好比:模態框、Tab頁、菜單等。

這個應用有個模態框,當你按下"Sign up today"按鈕時會彈出它:

和以前同樣,咱們只是將模態框代碼移動到它本身的單個文件組件中:

Home.vue:

<template>
  <div>
    <div class="jumbotron">...</div>
    <below-fold></below-fold>

    <home-modal v-if="show" :show="show"></home-modal>
  </div>
</template>
<script>
  const BelowFold = () => import(
    /* webpackChunkName: "below-fold" */ './BelowFold.vue'
  );
  const HomeModal = () => import(
    /* webpackChunkName: "modal" */ './HomeModal.vue'
  );

  export default {
    data() {
      return {
        show: false
      }
    },
    components: {
      HomeModal,
      BelowFold
    }
  }
</script>複製代碼

HomeModal.vue:

<template>
    <modal v-model="show" effect="fade">...</modal>
</template>
<script>
  import Modal from 'vue-strap/src/Modal.vue';
  export default {
    props: ['show'],
    components: {
        Modal
    }
  }
</script>複製代碼

注意我在模態框上加了 v-if。布爾值 show 用來開啓/關閉模態框,而且它也用來判斷是否渲染模態框自己。由於初始化頁面時 showfalse,只有當模態框打開時,纔會下載代碼。

這很合適,由於若是用戶沒有打開模態框,那這塊代碼是不會下載的。惟一的缺點是:它有很小的用戶體驗成本,當用戶按下按鈕後必須等待文件下載完成。

再次編譯,下面是如今的輸出結果:

啊哈,咱們又節省了5KB的首屏流量...

結論

除了以上三種代碼分割的方法,我相信必定還有其餘方法去實現,只要你運用本身的想象力!

本文譯者:餘震(Freak)
譯文出處:Rockjins Blog
版權聲明:本博客全部文章除特別聲明外,均採用 CC BY-NC-SA 3.0 CN許可協議。轉載請註明出處!

相關文章
相關標籤/搜索