Laravel框架中縮小Vue應用的體積

這兩天寫一個很小的Laravel+Vue的先後端分離應用,前端的代碼文件並很少,但webpack打包生成的app.js竟然有3M,生成的production版也有1.4M,放到本身的服務器上,那速度徹底沒法忍受。因而探究起如何縮小應用體積。css

定位致使應用體積大的緣由

這裏使用webpack-bundle-analyzer,該插件能夠將內容束顯示爲很直觀的樹狀圖,讓你明白構建包中真正引入的內容。藉助這個插件能夠了解應用有哪些模塊組成,找到不合時宜的存在,而後進行優化。前端

  1. 安裝:npm install --save-dev webpack-bundle-analyzer
  2. 修改webpack.mix.js,注意Laravel自帶的webpack-mix的配置方式與日常的webpack配置略有不一樣
    const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
    
    mix.webpackConfig({
      plugins: [
        new BundleAnalyzerPlugin(),
      ],
    }).js('resources/assets/js/app.js', 'public/js')
      .sass('resources/assets/sass/app.scss', 'public/css');
    複製代碼

修改完以後像日常同樣使用npm run devnpm run production打包應用,打包完成後,會自動打開http://127.0.0.1:8888來展現結果。 vue

分析結果

解決辦法

從上面的這張圖能夠分析出致使應用體積變大的緣由就是在於引用不少第三方庫,這些庫會被webpack一塊兒打包到應用內,因此減少應用體積的最有效方法就是將這些庫分離出去,別將它們與咱們本身寫的應用代碼打包到一塊兒。大部分有名的第三方庫在公共CDN都有存放,如bootcss, unpkg等,速度飛快,能夠直接引用。node

webpack的選項有一個externals,能夠指定哪些包不參與打包,即忽略掉相應import XXX from package,而代碼中依舊能夠經過CMD、AMD或window/global全局的方式訪問。webpack

mix.webpackConfig({
  plugins: [
    new BundleAnalyzerPlugin(),
  ],
  externals: {
    'element-ui': 'Element',
    'axios': 'axios',
    'vue': 'Vue',
    'vuex': 'Vuex',
    'vue-router': 'VueRouter',
    'vue-chartjs': 'VueChartJs',
    'lodash': '_',
  }
}).js('resources/assets/js/app.js', 'public/js')
 .sass('resources/assets/sass/app.scss', 'public/css')
 .styles(['node_modules/element-ui/lib/theme-chalk/index.css'], 'public/css/element-ui.css');
複製代碼

在blade文件中加入外鏈ios

<head>
    ...
    <script src="//cdn.bootcss.com/vue/2.5.13/vue.min.js"></script>
    <script src="//cdn.bootcss.com/vuex/3.0.1/vuex.min.js"></script>
    <script src="//cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js"></script>
    <script src="//cdn.bootcss.com/element-ui/2.0.11/index.js"></script>
    <script src="//cdn.bootcss.com/axios/0.17.1/axios.min.js"></script>
    <script src="//cdn.bootcss.com/lodash.js/4.17.4/lodash.min.js"></script>
    <script src="//unpkg.com/vue-chartjs@2.8.7/dist/vue-chartjs.full.min.js"></script>
    <link href="https://cdn.bootcss.com/element-ui/2.0.11/theme-chalk/index.css" rel="stylesheet">
    ...
</head>
複製代碼

而後從新打包應用,最後生成的應用只有幾十K了,這大小已經不成問題了laravel

進一步優化

這裏將第三方庫徹底改成外鏈,在生成環境內是沒問題,但咱們在開發時,並不但願每次都是從網絡獲取第三方庫,網絡加載始終不會有本地加載來的快,本地加載並不須要考慮大小問題。web

咱們能夠經過使用環境變量來控制要不要使用外鏈。vue-router

在.env中添加一個變量MIX_EXTERNAL=true (注意:若是要在App應用裏使用這個變量,這裏必須是以 MIX_ 開頭,參考 Mix 環境變量vuex

Laravel自帶的webpack-mix默認不加載.env文件,但已經帶有dotenv包,加載便可。

最後的webpack.mix.js文件以下

let mix = require('laravel-mix');
require('dotenv').config();

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

let externals = undefined;
if (process.env.MIX_EXTERNAL === 'true') {
  externals = {
    'element-ui': 'Element',
    'axios': 'axios',
    'vue': 'Vue',
    'vuex': 'Vuex',
    'vue-router': 'VueRouter',
    'vue-chartjs': 'VueChartJs',
    'lodash': '_',
  };
}

mix.webpackConfig({
  plugins: [
    // new BundleAnalyzerPlugin(),
  ],
  externals,
})
  .js('resources/assets/js/app.js', 'public/js')
  .sass('resources/assets/sass/app.scss', 'public/css')
  .styles(['node_modules/element-ui/lib/theme-chalk/index.css'], 'public/css/element-ui.css');
複製代碼

blade文件:

@if (env('MIX_EXTERNAL'))
    <script src="//cdn.bootcss.com/vue/2.5.13/vue.min.js"></script>
    <script src="//cdn.bootcss.com/vuex/3.0.1/vuex.min.js"></script>
    <script src="//cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js"></script>
    <script src="//cdn.bootcss.com/element-ui/2.0.11/index.js"></script>
    <script src="//cdn.bootcss.com/axios/0.17.1/axios.min.js"></script>
    <script src="//cdn.bootcss.com/lodash.js/4.17.4/lodash.min.js"></script>
    <script src="//unpkg.com/vue-chartjs@2.8.7/dist/vue-chartjs.full.min.js"></script>
    <link href="https://cdn.bootcss.com/element-ui/2.0.11/theme-chalk/index.css" rel="stylesheet">
@else
    <link rel="stylesheet" href="css/element-ui.css">
@endif
複製代碼

應用內有些代碼須要針對外鏈作區別處理,如ElementUI,若是使用import方式引入,須要加入Vue.use(ElementUI),但若是使用外鏈時,這句會出錯,因此能夠加入判斷

if (process.env.MIX_EXTERNAL !== 'true') { // **注意是字符串**
  Vue.use(Element);
}
複製代碼

在app內使用process.env.MIX_XXXXX環境變量時,這些變量實際在打包過程當中已經被替換爲變量值(就像C裏面的宏定義同樣),不會在運行求值,也不存在process對象,上面的if語句在打包後變成if (false) Vue.use(Element)

至此優化完畢,只需在.env裏修改一下變量,便可在兩種打包方式間切換,能夠愉快地繼續開發了。

參考:

Webpack 打包優化之體積篇

相關文章
相關標籤/搜索