頻道欄目
首頁 > 程序開發 > web前端 > HTML/CSS > 正文
[打包優化]從0到1搭建element后臺框架優化篇-前端小東西-SegmentFault思否
2019-05-11 22:05:10           
收藏   我要投稿

前言

hello,咱又見了~~嘻嘻。本次主要來說說這個打包優化的問題。一個vue項目從開發到上線必須得經歷打包過程,一個項目的打包優化與否都決定了你這個項目的運行速度以及用戶體驗。本次主要是針對vue.config,js的配置進行優化。項目地址

開發環境與生產環境

開發環境與生產環境的配置也是開發中的必不可少的一環。本項目是由vue-cli3開發,vue-cli3深度集成了webpack,如果不熟悉vue-cli3可以先去官網看看相關配置。

開發環境

在項目根目錄下新建.env.development文件表明是開發環境。

    VUE_APP_CURRENTMODE ="development" //當前的環境
    VUE_APP_LOGOUT_URL="http://localhost:3000/" //開發環境的地址

生產環境

在項目根目錄下新建.env.production文件表明是生產環境。

    VUE_APP_CURRENTMODE ="development" //當前的環境
    VUE_APP_LOGOUT_URL="xxx" //生產環境的地址

當然你也可以自己創建一個測試環境.env.test,同樣可以像上邊一樣配置。

環境運用

那么接下來我們怎么用它呢?這里不得不說一下的是package.json里面的兩個命令serve,build,其實對應的是全命令是vue-cli-service serve --mode development,vue-cli-service build --mode production,如果你想要在構建命令中使用開發環境變量,那么可以加入

    "dev-build": "vue-cli-service build --mode development"

接下來在vue.config.js運用它。

    config.plugin('define').tap(args => {
          args[0]['process.env'].VUE_APP_LOGOUT_URL = JSON.stringify(process.env.VUE_APP_LOGOUT_URL)
          console.log(args[0])
          return args;
    });

這里有必要說下,這段代碼是寫在chainWebpack配置項下面。這段代碼其實運用了兩個webpack插件webpack-chain允許配置鏈式操作,以及webpack.DefinePlugin。

webpack-chain:嘗試通過提供可鏈式或順流式的 API 創建和修改webpack 配置。了解更多 webpack.DefinePlugin:它的作用是定義全局常量,是常量。即在模塊用它定義的全局常量,那么你就不能改變它。也就是說我定義了一個process.env.VUE_APP_LOGOUT_URL常量,在src文件夾下面都可以使用。了解更多

分包(code splitting)

首先思考,我們引入的第三方包與我們的業務代碼一起打包會產生什么問題?

顧名思義,我們的業務代碼變動比較頻繁,而我們引入的第三方包基本上不會變動。瀏覽器會有緩存,沒有變動的文件會直接從緩存中讀取,這也間接的優化了網站的訪問速速。
接下來配置vue.config.js,

分割第三方庫

    //代碼分割
    config.optimization.minimize(true);
    config.optimization.splitChunks({
      chunks: 'all',
      cacheGroup:{
        //vue2-editor單獨打一個包
          vueEdior: {
            name: 'vueEdior',
            test: /[\\/]node_modules[\\/]vue2-editor[\\/]/,
            priority: 10  // 優先級要大于 vendors 不然會被打包進 vendors
          },
          //其余的第三方包打進vendor
          vendors: {
            test: /[\\/]node_modules[\\/]/,
            priority: -10
          }
      }
    })

分割共用文件

組件是vue項目的重要組成部分。相當一部分組件都可以公用,在不同的文件中引入,因此我們可以將這部分公用的組件直接分割出來。

    config.optimization.minimize(true);
    config.optimization.splitChunks({
      chunks: 'all',
      cacheGroup:{
          vueEdior: {
            name: 'vueEdior',
            test: /[\\/]node_modules[\\/]vue2-editor[\\/]/,
            priority: 10  // 優先級要大于 vendors 不然會被打包進 vendors
          },
          public: {
            name: 'public',
            test: resolve('src/components'),
            minSize: 0, //表示在壓縮前的最小模塊大小,默認值是 30kb
            minChunks: 2, // 最小公用次數
            priority: 5, // 優先級
            reuseExistingChunk: true // 公共模塊必開啟
          },
          //其余的第三方包打進vendor
          vendors: {
            test: /[\\/]node_modules[\\/]/,
            priority: -10
          }
      }
    })

打包完后會發現dist/static/js,多了一個vueEditor和public文件,這就表明分割完成。

map文件處理和別名設置(alias)

map文件

我們可以進一步優化,打包默認生成map文件,從而導致包的體積過大,這時我們需要設定一個屬性來關閉它。

productionSourceMap: false

別名設置

alias運用的好處在于不用一級級的去找,而是直接鎖定位置,從而減少文件搜索時間。

    //設置別名
    config.resolve.alias
      .set('@', resolve('src'))
      .set('@api', resolve('src/api/api'))//接口地址
      .set('@assets', resolve('src/assets'))

gzip壓縮與去console插件

如果上面的方式都編寫了,文件依舊過大,這個時候不得不考慮代碼壓縮和去掉console插件了,可以說為了優化項目,“無所不用其極”。

gzip壓縮

首先安裝開始安裝

    cnpm install compression-webpack-plugin --save-dev

然后在configureWebpack里面配置它

    const CompressionWebpackPlugin = require('compression-webpack-plugin')
    new CompressionWebpackPlugin({
        filename: '[path].gz[query]',
        algorithm: 'gzip',
        test: new RegExp(
          '\\.(' +
          ['js', 'css'].join('|') +
          ')$',
        ),
        threshold: 10240,
        minRatio: 0.8,
      }),

值得注意的是gzip壓縮文件需要后端來配合支持,如果后端沒有支持那么項目加載的依舊是沒有壓縮的文件。

去console插件

首先安裝

    cnpm install uglifyjs-webpack-plugin --save-dev

然后在configureWebpack里面配置它

    const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
    new UglifyJsPlugin({
        uglifyOptions: {
          compress: {
            warnings: false,
            drop_debugger: true,
            drop_console: true,
          },
        },
        sourceMap: false,
        parallel: true,
      }),

cdn引入

有的同學說后端沒有支持gzip壓縮加載,那怎么辦?那只有涼拌咯~~~。
這里給大家介紹一個cdn引入的方式,有的第三方插件太大,導致單獨分包后還是挺大的,這個時候可以考慮用cdn的方式引入文件。

無插件引入cdn

首先我們不讓webpack打包用cdn引入的文件

    //對一些不經常改動的庫,可以通過cdn引入,webpack不對他們打包  
    let externals = {
      'vue': 'Vue',
      'axios': 'axios',
      'element-ui': 'ELEMENT',
      'vue-router': 'VueRouter',
      'vuex': 'Vuex',
      'echarts': 'echarts',
      'vue2-editor': 'VueEditor'
    }

然后配置cdn

    const cdn = {
      css: [
        //element-ui css
        'https://unpkg.com/element-ui/lib/theme-chalk/index.css'
      ],
      js: [
        //vue
        'https://unpkg.com/[email protected]/dist/vue.min.js',
        //axios
        'http://cdn.staticfile.org/axios/0.19.0-beta.1/axios.min.js',
        //vuex
        'https://unpkg.com/[email protected]/dist/vuex.min.js',
        //vue-router
        'https://unpkg.com/[email protected]/dist/vue-router.min.js',
        //element
        'https://unpkg.com/[email protected]/lib/index.js',
        //echarts
        'https://cdn.jsdelivr.net/npm/[email protected]/dist/echarts.min.js',
        //vue2-editor
        "https://unpkg.com/[email protected]/dist/vue2-editor.js"
      ]
    }

接下來在chainWebpack配置

    process.env.VUE_APP_CURRENTMODE === 'production') {
      config.externals(externals)//忽略打包
      config.plugin('html')
        .tap(args => {
          args[0].cdn = cdn;
          return args
        })
    }

這里需要解釋的是config.plugin('html')其實是運用了 html-webpack-plugin插件在其實例化的options掛載cdn對象,然后通過ejs模板語法,讀取相關cdn。
緊接著我們需要在public/index.html中讀取相關cdn

    <% if (process.env.VUE_APP_CURRENTMODE === 'production') { %>
      <% for(var css of htmlWebpackPlugin.options.cdn.css) { %>
        <link rel="stylesheet" href="<%=css%>" as="style">
      <% } %>
      <% for(var js of htmlWebpackPlugin.options.cdn.js) { %>
        <script src="<%=js%>"></script>
      <% } %>
    <% } %>

至此cdn引入完成

插件引入cdn

由于手動引入cdn太過麻煩,而且擔心版本變化,每次都需要手動去更改,所以為了更好的開發體驗,引入了自動匹配cdn插件,webpack-cdn-plugin。接下來開始安裝

    cnpm install webpack-cdn-plugin --save

實例化插件

    const cdnPlugin = require('webpack-cdn-plugin')

接下來開始在configureWebpack中引用

    new cdnPlugin({
        modules: [
          { name: 'vue', var: 'Vue', path: 'dist/vue.min.js' },
          { name: 'axios', var: 'axios', path: 'dist/axios.min.js' },
          { name: 'vuex', var: 'Vuex', path: 'dist/vuex.min.js' },
          { name: 'element-ui', var: 'ELEMENT', path: 'lib/index.js', style: 'lib/theme-chalk/index.css' },
          { name: 'echarts', var: 'echarts', path: 'dist/echarts.min.js' },
          { name: 'vue2-editor', var: 'VueEditor', path: 'dist/vue2-editor.js' },
          { name: 'vue-router', var: 'VueRouter', path: 'dist/vue-router.min.js' },
        ],
        publicPath: '/node_modules'
      })
name:插件名 var :項目中實例化的名字 path:路徑名稱 style:css路徑名稱

更多了解請參考官方文檔。

總體來說引入第三方cdn確實能帶來不錯的效果,但是有可能不穩定,因此建議大家在實際開發中自己去申請一個專屬的cdn域名,將網站所要用到庫直接上傳上去。

結語

本期的打包優化就到這里啦!感覺有很多廢話。哈哈~~,最后感謝大家閱讀,如果有問題以及錯誤請及時指正。

相關文章

從0到1搭建element后臺框架

從0到1搭建element后臺框架之權限篇

點擊復制鏈接 與好友分享!回本站首頁
相關TAG標簽
上一篇:ES6專題—class與面向對象編程-體驗javascript之美-SegmentFault思否
下一篇:webpack4js構建速度優化-flashback-SegmentFault思否
相關文章
圖文推薦
點擊排行

關于我們 | 聯系我們 | 廣告服務 | 投資合作 | 版權申明 | 在線幫助 | 網站地圖 | 作品發布 | Vip技術培訓 | 舉報中心

版權所有: 紅黑聯盟--致力于做實用的IT技術學習網站

加拿大28火车判定方法