使用Webpack提升Vue.js應用程式的4種方法(翻譯)

jerrysun發表於2021-09-09

本文翻譯自,翻譯技巧不太好,不喜勿碰 :

眾所周知,webpack 是 開發 vue.js 單頁面應用程式的必備工具,透過管理複雜的構建步驟,它可以使您的開發工作流程更加簡單,並且可以最佳化應用程式的大小和效能。
在本文中,我將解釋Webpack增強Vue應用程式的四種方法,包括:

Single file components  單檔案元件
Optimising the Vue build  
Browser cache management
Code splitting

關於 vue-cli

如果您使用模板從vue-cli構建應用程式,那麼將提供預製的Webpack配置。它們已經過最佳化,沒有任何改進建議!
但是,由於它們開箱即用的效果非常好,您可能對它們的實際功能並不太瞭解,對嗎?
考慮一下本文,對vue-cli模板中使用的Webpack配置進行概述,因為它們包含了我在這裡討論的相同最佳化。

1. Single file components

Vue的特有功能之一是將HTML用於元件模板。但是,這些帶有一個固有的問題:要麼您的HTML標記需要使用笨拙的JavaScript字串,要麼您的模板和元件定義必須位於單獨的檔案中,從而使其難以使用。

Vue有一個優雅的解決方案,稱為“單個檔案元件(SFC)”,該檔案將模板,元件定義和CSS都包含在一個簡單的.vue檔案中:

<template>
  <div id="my-component">...</div>
</template>
<script>
  export default {...}
</script>
<style>
  #my-component {...}
</style>

vue-loader Webpack外掛使SFC成為可能。該載入器拆分SFC語言塊並將每個管道透過管道傳輸到適當的載入器,例如指令碼塊轉到babel-loader,而模板塊轉到Vue自己的vue-template-loader,後者將模板轉換為JavaScript渲染函式。
vue-loader的最終輸出是一個JavaScript模組,準備將其包含在Webpack捆綁包中。
vue-loader的典型配置如下:

module: {
  rules: [
    {
      test: /.vue$/,
      loader: 'vue-loader',
      options: {
        loaders: {
          // Override the default loaders
        }
      }
    },
  ]
}

2. Optimising the Vue build

如果僅在Vue應用程式*中使用渲染功能,而沒有HTML模板,則不需要Vue的模板編譯器。您可以透過從Webpack構建中省略編譯器來減小捆綁包的大小。
請記住,單個檔案元件模板已在開發中預編譯以呈現功能!
Vue.js庫只有執行時版本,其中包含Vue.js的所有功能,但模板編譯器稱為vue.runtime.js。它比完整版本小20KB,因此如果可以的話值得使用。

預設情況下,僅使用執行時構建,因此,每次使用 import vue from ‘vue’ 時,都將使用它。在您的專案中,這就是您所得到的。但是,您可以使用alias 別名配置選項更改為其他版本:

resolve: {
  alias: {
    'vue$': 'vue/dist/vue.esm.js' // Use the full build
  }
},

Stripping out warnings and error messages in production

減小Vue.js構建大小的另一種方法是刪除生產中的任何錯誤訊息和警告。這些使用不必要的程式碼使輸出包大小膨脹,並且還導致您最好避免執行時開銷

如果您檢查Vue原始碼,則會看到警告塊取決於環境變數process.env.NODE_ENV的值,例如:

if (process.env.NODE_ENV !== 'production') {
  warn(("Error in " + info + ": "" + (err.toString()) + """), vm);
}

如果將process.env.NODE_ENV設定為生產,那麼在構建過程中,minifier可以自動將此類警告塊從程式碼中剝離。

您可以使用DefinePlugin來設定process.env.NODE_ENV的值,並使用UglifyJsPlugin來減少程式碼並去除未使用的塊:

if (process.env.NODE_ENV === 'production') {
  module.exports.plugins = (module.exports.plugins || []).concat([
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"production"'
      }
    }),
    new webpack.optimize.UglifyJsPlugin()
  ])
}

3. Browser cache management

使用者的瀏覽器將快取您網站的檔案,以便僅在該瀏覽器尚無本地副本或本地副本已過期時才下載。

如果您所有的程式碼都在一個檔案中,那麼進行微小的更改就意味著需要重新下載整個檔案。

理想情況下,您希望使用者下載得儘可能少,因此將應用程式很少更改的程式碼與頻繁更改的程式碼分開是明智的。

Vendor file

Common Chunks外掛可以將您的 vendor 程式碼(例如,不太可能經常更改的Vue.js庫之類的依賴項)與您的應用程式程式碼(每次部署可能更改的程式碼)分離。
您可以配置外掛以檢查依賴項是否來自node_modules資料夾,如果是,則將其輸出到單獨的檔案vendor.js中:

new webpack.optimize.CommonsChunkPlugin({
  name: 'vendor',
  minChunks: function (module) {
    return module.context && module.context.indexOf('node_modules') !== -1;
  }
})

如果這樣做,您現在在構建輸出中將有兩個單獨的檔案,這些檔案將由瀏覽器獨立快取:

<script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="vendor.js" charset="utf-8"></script>
<script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="app.js" charset="utf-8"></script>

Fingerprinting

當構建檔案更改時,我們如何破壞瀏覽器的快取?
預設情況下,僅當快取的檔案到期時,或者當使用者手動清除快取時,瀏覽器才會再次從伺服器請求檔案。
如果伺服器指示檔案已更改,則將重新下載該檔案(否則伺服器返回HTTP 304 Not Modified)。
為了節省不必要的伺服器請求,我們可以在每次檔案內容更改時更改其名稱,以強制瀏覽器重新下載該檔案。一個簡單的系統可以透過在檔名後附加一個雜湊來為檔名新增“指紋”:
圖片描述
Common Chunks外掛會發出“ chunkhash”,如果檔案內容已更改,則將對其進行更新。 Webpack可以在輸出檔名時將此雜湊附加到檔名中:

output: {
  filename: '[name].[chunkhash].js'
},

執行此操作時,您將看到輸出的檔案將具有類似app.3b80b7c17398c31e4705.js的名稱。

Auto inject build files

當然,如果新增雜湊,則必須更新索引檔案中對該檔案的引用,否則瀏覽器將不知道該雜湊:

<script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="app.3b80b7c17398c31e4705.js"></script>

手動完成這項工作非常繁瑣,因此請使用HTML Webpack外掛為您完成。該外掛可以在捆綁過程中自動將對構建檔案的引用注入到HTML檔案中。
首先刪除對構建檔案的引用:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>test-6</title>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files should go here, but will be auto injected -->
  </body>
</html>

並將HTML Webpack外掛新增到您的Webpack配置中:

new HtmlWebpackPlugin({
  filename: 'index.html'
  template: 'index.html',
  inject: true,
  chunksSortMode: 'dependency'
}),

現在,帶有雜湊的構建檔案將自動新增到索引檔案中。另外,您的index.html檔案現在將包含在捆綁輸出中,因此您可能需要告訴Web伺服器其位置已更改

4. Code splitting

預設情況下,Webpack會將所有應用程式程式碼輸出到一個大捆綁包中。但是,如果您的應用有多個頁面,則拆分程式碼會更有效,因此每個單獨的頁面程式碼都位於單獨的檔案中,並且僅在需要時才載入
Webpack具有一項稱為“程式碼拆分”的功能。在Vue.js中實現此功能還需要非同步元件,並且透過Vue Router變得更加容易。

Async components

非同步元件沒有將定義物件作為第二個引數,而是具有一個Promise函式來解析該定義物件,例如:

Vue.component('async-component', function (resolve, reject) {
  setTimeout(() => {
    resolve({
      // Component definition including props, methods etc.
    });
  }, 1000)
})

Vue僅在元件實際需要渲染時才呼叫該函式。它還會快取結果以供將來重新渲染。
如果我們設計應用程式,使每個“頁面”都是一個元件,並且將定義儲存在伺服器上,那麼我們就完成了程式碼拆分的一半。

require

要從伺服器載入非同步元件的程式碼,請使用Webpack require語法
這將指示Webpack在構建時將async-component捆綁在一個單獨的bundle中,更好的是,Webpack將使用AJAX處理此bundle的載入,因此您的程式碼可以像這樣簡單:

Vue.component('async-component', function (resolve) {
  require(['./AsyncComponent.vue'], resolve)
});

Lazy loading

在Vue.js應用程式中,vue-router通常是您用於將SPA組織到多個頁面中的模組。延遲載入是使用Vue和Webpack實現程式碼拆分的一種形式化方法。

const HomePage = resolve => require(['./HomePage.vue'], resolve);

const rounter = new VueRouter({
  routes: [
    {
      path: '/',
      name: 'HomePage',
      component: HomePage
    }
  ]
})

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/151/viewspace-2823844/,如需轉載,請註明出處,否則將追究法律責任。

相關文章