总结几个webpack打包优化的方法

为何要优化打包?

  • 项目越作越大,依赖包愈来愈多,打包文件太大
  • 单页面应用首页白屏时间长,用户体验差

咱们的目的

  • 减少打包后的文件大小
  • 首页按需引入文件
  • 优化 webpack 打包时间

优化方式

一、 按需加载

1.1 路由组件按需加载javascript

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

1.2 第三方组件和插件。按需加载需引入第三方组件css

// 引入所有组件
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 对于一些插件,若是只是在个别组件中用的到,也能够不要在 main.js 里面引入,而是在组件中按需引入html

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

// 按组件按需引入
import { Vuelidate } from 'vuelidate'
复制代码

二、优化 loader 配置

  • 优化正则匹配
  • 经过 cacheDirectory 选项开启缓存
  • 经过 include、exclude 来减小被处理的文件。
module: {
  rules: [
    {
      test: /\.js$/,
      loader: 'babel-loader?cacheDirectory',
      include: [resolve('src')]
    }
  ]
}
复制代码

三、优化文件路径——省下搜索文件的时间

  • extension 配置以后能够不用在 require 或是 import 的时候加文件扩展名,会依次尝试添加扩展名进行匹配。
  • mainFiles 配置后不用加入文件名,会依次尝试添加的文件名进行匹配
  • alias 经过配置别名能够加快 webpack 查找模块的速度。
resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
    }
  },
复制代码

四、生产环境关闭 sourceMap

  • sourceMap 本质上是一种映射关系,打包出来的 js 文件中的代码能够映射到代码文件的具体位置,这种映射关系会帮助咱们直接找到在源代码中的错误。
  • 打包速度减慢,生产文件变大,因此开发环境使用 sourceMap,生产环境则关闭。

五、代码压缩

  • UglifyJS: vue-cli 默认使用的压缩代码方式,它使用的是单线程压缩代码,打包时间较慢
  • ParallelUglifyPlugin: 开启多个子进程,把对多个文件压缩的工做分别给多个子进程去完成

两种方法使用以下:前端

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

  new ParallelUglifyPlugin({
    //缓存压缩后的结果,下次遇到同样的输入时直接从缓存中获取压缩后的结果并返回,
    //cacheDir 用于配置缓存存放的目录路径。
    cacheDir: '.cache/',
    sourceMap: true,
    uglifyJS: {
      output: {
        comments: false
      },
      compress: {
        warnings: false
      }
    }
  })
]
复制代码

打包速度和打包后的文件大小啊对比vue

方法 文件大小 打包速度
不用插件 14.6M 32s
UglifyJsPlugin 12.9M 33s
ParallelUglifyPlugi 7.98M 17s

六、提取公共代码

  • 相同资源重复被加载,浪费用户流量,增长服务器成本。
  • 每一个页面须要加载的资源太大,致使网页首屏加载缓慢,影响用户体验。

webpack3 使用 CommonsChunkPlugin 的实现:java

plugins: [
  new webpack.optimize.CommonsChunkPlugin({
    name: 'vendor',
    minChunks: function(module, count) {
      console.log(module.resource, `引用次数${count}`)
      //"有正在处理文件" + "这个文件是 .js 后缀" + "这个文件是在 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 的实现:node

module.exports = {
  optimization: {
    splitChunks: {
      cacheGroups: {
        vendor: {
          priority: 1, //添加权重
          test: /node_modules/, //把这个目录下符合下面几个条件的库抽离出来
          chunks: 'initial', //刚开始就要抽离
          minChunks: 2 //重复2次使用的时候须要抽离出来
        },
        common: {
          //公共的模块
          chunks: 'initial',
          minChunks: 2
        }
      }
    }
  }
}
复制代码

七、CDN 优化

  • 随着项目越作越大,依赖的第三方 npm 包愈来愈多,构建以后的文件也会愈来愈大。
  • 再加上又是单页应用,这就会致使在网速较慢或者服务器带宽有限的状况出现长时间的白屏。

一、将 vue、vue-router、vuex、element-ui 和 axios 这五个库,所有改成经过 CDN 连接获取,在 index.html 里插入 相应连接。webpack

<head>
  <link rel="stylesheet" href="https://cdn.bootcss.com/element-ui/2.0.7/theme-chalk/index.css" />
</head>
<body>
  <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>
  <!-- built files will be auto injected -->
</body>
复制代码

二、在 webpack.config.js 配置文件ios

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

三、卸载依赖的 npm 包,npm uninstall axios element-ui vue vue-router vuexweb

四、修改 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)
})
复制代码

八、使用 HappyPack 多进程解析和处理文件

  • 因为运行在 Node.js 之上的 Webpack 是单线程模型的,因此 Webpack 须要处理的事情须要一件一件的作,不能多件事一块儿作。
  • HappyPack 就能让 Webpack 把任务分解给多个子进程去并发的执行,子进程处理完后再把结果发送给主进程。
  • HappyPack 对 file-loader、url-loader 支持的不友好,因此不建议对该 loader 使用。

使用方法以下:

  1. HappyPack 插件安装: npm i -D happypack
  2. webpack.base.conf.js 文件对 module.rules 进行配置
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']
    }
  ]
}
复制代码
  1. 在生产环境 webpack.prod.conf.js 文件进行配置
const HappyPack = require('happypack')
// 构造出共享进程池,在进程池中包含5个子进程
const HappyPackThreadPool = HappyPack.ThreadPool({ size: 5 })
plugins: [
  new HappyPack({
    // 用惟一的标识符id,来表明当前的HappyPack是用来处理一类特定的文件
    id: 'babel',
    // 如何处理.js文件,用法和Loader配置中同样
    loaders: ['babel-loader?cacheDirectory'],
    threadPool: HappyPackThreadPool
  }),
  new HappyPack({
    id: 'vue', // 用惟一的标识符id,来表明当前的HappyPack是用来处理一类特定的文件
    loaders: [
      {
        loader: 'vue-loader',
        options: vueLoaderConfig
      }
    ],
    threadPool: HappyPackThreadPool
  })
]
复制代码

总结

  1. 比较实用的方法: 按需加载,优化loader配置,关闭生产环境的sourceMap,CDN优化。
  2. vue-cli已作的优化: 代码压缩,提取公共代码,再优化空间不大。
  3. 根据项目实际须要和自身开发水平选择优化方法,必须避免由于优化产生bug。

相关文章

相关文章
相关标签/搜索