<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          總結(jié)幾個(gè) webpack 打包優(yōu)化的方法,前端項(xiàng)目必備

          共 5194字,需瀏覽 11分鐘

           ·

          2021-01-29 00:09

          為什么要優(yōu)化打包?

          • 項(xiàng)目越做越大,依賴包越來(lái)越多,打包文件太大

          • 單頁(yè)面應(yīng)用首頁(yè)白屏?xí)r間長(zhǎng),用戶體驗(yàn)差

          我們的目的

          • 減小打包后的文件大小

          • 首頁(yè)按需引入文件

          • 優(yōu)化 webpack 打包時(shí)間

          優(yōu)化方式

          1、 按需加載

          1.1 路由組件按需加載

          const router = [
          {
          path: '/index',
          component: resolve => require.ensure([], () => resolve(require('@/components/index')))
          },
          {
          path: '/about',
          component: resolve => require.ensure([], () => resolve(require('@/components/about')))
          }
          ]

          1.2 第三方組件和插件。按需加載需引入第三方組件

          // 引入全部組件
          import ElementUI from 'element-ui'
          import 'element-ui/lib/theme-chalk/index.css'
          Vue.use(ElementUI)

          // 按需引入組件
          import { Button } from 'element-ui'
          Vue.component(Button.name, Button)

          1.3 對(duì)于一些插件,如果只是在個(gè)別組件中用的到,也可以不要在 main.js 里面引入,而是在組件中按需引入

          // 在main.js引入
          import Vue from vue
          import Vuelidate from 'vuelidate'
          Vue.use(Vuelidate)

          // 按組件按需引入
          import { Vuelidate } from 'vuelidate'

          2、優(yōu)化 loader 配置

          • 優(yōu)化正則匹配

          • 通過(guò) cacheDirectory 選項(xiàng)開(kāi)啟緩存

          • 通過(guò) include、exclude 來(lái)減少被處理的文件。

          module: {
          rules: [
          {
          test: /\.js$/,
          loader: 'babel-loader?cacheDirectory',
          include: [resolve('src')]
          }
          ]
          }

          3、優(yōu)化文件路徑

          • extension 配置之后可以不用在 require 或是 import 的時(shí)候加文件擴(kuò)展名,會(huì)依次嘗試添加擴(kuò)展名進(jìn)行匹配。

          • mainFiles 配置后不用加入文件名,會(huì)依次嘗試添加的文件名進(jìn)行匹配

          • alias 通過(guò)配置別名可以加快 webpack 查找模塊的速度。

            resolve: {
          extensions: ['.js', '.vue', '.json'],
          alias: {
          'vue$': 'vue/dist/vue.esm.js',
          '@': resolve('src'),
          }
          },

          4、生產(chǎn)環(huán)境關(guān)閉 sourceMap

          • sourceMap 本質(zhì)上是一種映射關(guān)系,打包出來(lái)的 js 文件中的代碼可以映射到代碼文件的具體位置,這種映射關(guān)系會(huì)幫助我們直接找到在源代碼中的錯(cuò)誤。

          • 打包速度減慢,生產(chǎn)文件變大,所以開(kāi)發(fā)環(huán)境使用 sourceMap,生產(chǎn)環(huán)境則關(guān)閉。

          5、代碼壓縮

          • UglifyJS: vue-cli 默認(rèn)使用的壓縮代碼方式,它使用的是單線程壓縮代碼,打包時(shí)間較慢

          • ParallelUglifyPlugin: 開(kāi)啟多個(gè)子進(jìn)程,把對(duì)多個(gè)文件壓縮的工作分別給多個(gè)子進(jìn)程去完成

          兩種方法使用如下:

          plugins: [
          new UglifyJsPlugin({
          uglifyOptions: {
          compress: {
          warnings: false
          }
          },
          sourceMap: true,
          parallel: true
          }),

          new ParallelUglifyPlugin({
          //緩存壓縮后的結(jié)果,下次遇到一樣的輸入時(shí)直接從緩存中獲取壓縮后的結(jié)果并返回,
          //cacheDir 用于配置緩存存放的目錄路徑。
          cacheDir: '.cache/',
          sourceMap: true,
          uglifyJS: {
          output: {
          comments: false
          },
          compress: {
          warnings: false
          }
          }
          })
          ]

          6、提取公共代碼

          • 相同資源重復(fù)被加載,浪費(fèi)用戶流量,增加服務(wù)器成本。

          • 每個(gè)頁(yè)面需要加載的資源太大,導(dǎo)致網(wǎng)頁(yè)首屏加載緩慢,影響用戶體驗(yàn)。

          webpack3 使用 CommonsChunkPlugin 的實(shí)現(xiàn):

          plugins: [
          new webpack.optimize.CommonsChunkPlugin({
          name: 'vendor',
          minChunks: function(module, count) {
          console.log(module.resource, `引用次數(shù)${count}`)
          //"有正在處理文件" + "這個(gè)文件是 .js 后綴" + "這個(gè)文件是在 node_modules 中"
          return module.resource && /\.js$/.test(module.resource) && module.resource.indexOf(path.join(__dirname, './node_modules')) === 0
          }
          }),
          new webpack.optimize.CommonsChunkPlugin({
          name: 'common',
          chunks: 'initial',
          minChunks: 2
          })
          ]

          webpack4 使用 splitChunks 的實(shí)現(xiàn):

          module.exports = {
          optimization: {
          splitChunks: {
          cacheGroups: {
          vendor: {
          priority: 1, //添加權(quán)重
          test: /node_modules/, //把這個(gè)目錄下符合下面幾個(gè)條件的庫(kù)抽離出來(lái)
          chunks: 'initial', //剛開(kāi)始就要抽離
          minChunks: 2 //重復(fù)2次使用的時(shí)候需要抽離出來(lái)
          },
          common: {
          //公共的模塊
          chunks: 'initial',
          minChunks: 2
          }
          }
          }
          }
          }

          7、CDN 優(yōu)化

          • 隨著項(xiàng)目越做越大,依賴的第三方 npm 包越來(lái)越多,構(gòu)建之后的文件也會(huì)越來(lái)越大。

          • 再加上又是單頁(yè)應(yīng)用,這就會(huì)導(dǎo)致在網(wǎng)速較慢或者服務(wù)器帶寬有限的情況出現(xiàn)長(zhǎng)時(shí)間的白屏。

          1、將 vue、vue-router、vuex、element-ui 和 axios 這五個(gè)庫(kù),全部改為通過(guò) CDN 鏈接獲取,在 index.html 里插入 相應(yīng)鏈接。





          <div id="app">div>
          <script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js">script>
          <script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.min.js">script>
          <script src="https://cdn.bootcss.com/vuex/3.1.0/vuex.min.js">script>
          <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.min.js">script>
          <script src="https://cdn.bootcss.com/element-ui/2.6.1/index.js">script>

          2、在 webpack.config.js 配置文件

          module.exports = {
          ···
          externals: {
          'vue': 'Vue',
          'vuex': 'Vuex',
          'vue-router': 'VueRouter',
          'element-ui': 'ELEMENT',
          'Axios':'axios'
          }
          },

          3、卸載依賴的 npm 包,npm uninstall axios element-ui vue vue-router vuex

          4、修改 main.js 文件里之前的引包方式

          // import Vue from 'vue'
          // import ElementUI from 'element-ui'
          // import 'element-ui/lib/theme-chalk/index.css'
          // import VueRouter from 'vue-router'

          import App from './App.vue'
          import routes from './router'
          import utils from './utils/Utils'

          Vue.use(ELEMENT)
          Vue.use(VueRouter)

          const router = new VueRouter({
          mode: 'hash', //路由的模式
          routes
          })

          new Vue({
          router,
          el: '#app',
          render: h => h(App)
          })

          8、使用 HappyPack 多進(jìn)程解析

          • 由于運(yùn)行在 Node.js 之上的 Webpack 是單線程模型的,所以 Webpack 需要處理的事情需要一件一件的做,不能多件事一起做。

          • HappyPack 就能讓 Webpack 把任務(wù)分解給多個(gè)子進(jìn)程去并發(fā)的執(zhí)行,子進(jìn)程處理完后再把結(jié)果發(fā)送給主進(jìn)程。

          • HappyPack 對(duì) file-loader、url-loader 支持的不友好,所以不建議對(duì)該 loader 使用。

          使用方法如下:

          1、HappyPack 插件安裝: npm i -D happypack
          2、webpack.base.conf.js 文件對(duì) module.rules 進(jìn)行配置

          module: {
          rules: [
          {
          test: /\.js$/,
          use: ['happypack/loader?id=babel'],
          include: [resolve('src'), resolve('test')],
          exclude: path.resolve(__dirname, 'node_modules')
          },
          {
          test: /\.vue$/,
          use: ['happypack/loader?id=vue']
          }
          ]
          }

          3、在生產(chǎn)環(huán)境 webpack.prod.conf.js 文件進(jìn)行配置

          const HappyPack = require('happypack')
          // 構(gòu)造出共享進(jìn)程池,在進(jìn)程池中包含5個(gè)子進(jìn)程
          const HappyPackThreadPool = HappyPack.ThreadPool({ size: 5 })
          plugins: [
          new HappyPack({
          // 用唯一的標(biāo)識(shí)符id,來(lái)代表當(dāng)前的HappyPack是用來(lái)處理一類特定的文件
          id: 'babel',
          // 如何處理.js文件,用法和Loader配置中一樣
          loaders: ['babel-loader?cacheDirectory'],
          threadPool: HappyPackThreadPool
          }),
          new HappyPack({
          id: 'vue', // 用唯一的標(biāo)識(shí)符id,來(lái)代表當(dāng)前的HappyPack是用來(lái)處理一類特定的文件
          loaders: [
          {
          loader: 'vue-loader',
          options: vueLoaderConfig
          }
          ],
          threadPool: HappyPackThreadPool
          })
          ]

          總結(jié)

          1. 比較實(shí)用的方法: 按需加載,優(yōu)化loader配置,關(guān)閉生產(chǎn)環(huán)境的sourceMap,CDN優(yōu)化。

          2. vue-cli已做的優(yōu)化: 代碼壓縮,提取公共代碼,再優(yōu)化空間不大。

          3. 根據(jù)項(xiàng)目實(shí)際需要和自身開(kāi)發(fā)水平選擇優(yōu)化方法,必須避免因?yàn)閮?yōu)化產(chǎn)生bug。



          筆者的年終總結(jié)在這里,希望能帶給你一點(diǎn)啟發(fā)。


          瀏覽 36
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲一区二区三区污污污 | 亚洲第一男人天堂 | a在线免费观看视频 | 69国产精品成人无码 | 日本中文字幕亚洲 |