【原创】webpack如何优化vue项目

前言javascript

平常开发中,Vue框架一般都会使用Webpack进行构建,随着项目不断迭代,项目逐渐变得庞大,然而项目的构建速度随之变得缓慢,因而对Webpack构建进行优化变得刻不容缓。经过适当的方法优化后,项目的构建速度提升了50%。现将相关优化方法进行总结分享。css

一.优化loader配置html

因为Loader对文件的转换操做很耗时,因此须要让尽量少的文件被Loader处理。咱们能够经过如下3方面优化Loader配置:(1)优化正则匹配(2)经过cacheDirectory选项开启缓存(3)经过include、exclude来减小被处理的文件。实践以下:前端

项目原配置:vue

{
  test: /\.js$/,
  loader: 'babel-loader',
  include: [resolve('src'), resolve('test')]
},复制代码

优化后配置:
java

{
  // 1、若是项目源码中只有js文件,就不要写成/\.jsx?$/,以提高正则表达式的性能
  test: /\.js$/,
  // 2、babel-loader支持缓存转换出的结果,经过cacheDirectory选项开启
  loader: 'babel-loader?cacheDirectory',
  // 3、只对项目根目录下的src 目录中的文件采用 babel-loader
  include: [resolve('src')]
},复制代码

二.优化UglifyJS插件node

webpack默认提供了UglifyJS插件来压缩JS代码,可是它使用的是单线程压缩代码,也就是说多个js文件须要被压缩,它须要一个个文件进行压缩。因此说在正式环境打包压缩代码速度很是慢(由于压缩JS代码须要先把代码解析成用Object抽象表示的AST语法树,再去应用各类规则分析和处理AST,致使这个过程耗时很是大)。webpack

所以咱们须要能够并行处理多个子任务,多个子任务完成后,再将结果发到主进程中,有了这个思想后,所以 ParallelUglifyPlugin 插件就产生了,当webpack有多个JS文件须要输出和压缩时候,原来会使用UglifyJS去一个个压缩而且输出,可是ParallelUglifyPlugin插件则会开启多个子进程,把对多个文件压缩的工做分别给多个子进程去完成,可是每一个子进程仍是经过UglifyJS去压缩代码。无非就是变成了并行处理该压缩了,并行处理多个子任务,效率会更加的提升。ios

安装 webpack-parallel-uglify-plugin 插件web

而后在webpack.config.js 配置代码以下:

// 引入 ParallelUglifyPlugin 插件const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');​module.exports = {  plugins: [    // 使用 ParallelUglifyPlugin 并行压缩输出JS代码    new ParallelUglifyPlugin({      // 传递给 UglifyJS的参数以下:      uglifyJS: {        output: {          /*           是否输出可读性较强的代码,即会保留空格和制表符,默认为输出,为了达到更好的压缩效果,           能够设置为false          */          beautify: false,          /*           是否保留代码中的注释,默认为保留,为了达到更好的压缩效果,能够设置为false          */          comments: false        },        compress: {          /*           是否在UglifyJS删除没有用到的代码时输出警告信息,默认为输出,能够设置为false关闭这些做用           不大的警告          */          warnings: false,          /*           是否删除代码中全部的console语句,默认为不删除,开启后,会删除全部的console语句          */          drop_console: true,          /*           是否内嵌虽然已经定义了,可是只用到一次的变量,好比将 var x = 1; y = x, 转换成 y = 5, 默认为不           转换,为了达到更好的压缩效果,能够设置为false          */          collapse_vars: true,          /*           是否提取出现了屡次可是没有定义成变量去引用的静态值,好比将 x = 'xxx'; y = 'xxx'  转换成           var a = 'xxxx'; x = a; y = a; 默认为不转换,为了达到更好的压缩效果,能够设置为false          */          reduce_vars: true        }      }    }),  ]}复制代码

打包对比基本上大小能相差30%!!!!

三.减小冗余代码

babel-plugin-transform-runtime 是Babel官方提供的一个插件,做用是减小冗余的代码 。 Babel在将ES6代码转换成ES5代码时,一般须要一些由ES5编写的辅助函数来完成新语法的实现,例如在转换 class extent 语法时会在转换后的 ES5 代码里注入 extent 辅助函数用于实现继承。babel-plugin-transform-runtime会将相关辅助函数进行替换成导入语句,从而减少babel编译出来的代码的文件大小

四.DllPlugin分包

经过DllPlugin插件分离出第三方包

  • 新建webpack.dll.conf.js

const path = require('path');
const webpack = require('webpack');
const CleanWebpackPlugin = require("clean-webpack-plugin");

module.exports = {
  entry: {
    vendor: [
      'vue',
      'vue-router',
      'vuex',
      'axios',
      'element-ui',
      'echarts'
    ]
  },
  output: {
    filename: '[name]_dll_[hash:6].js', // 产生的文件名
    path: path.resolve(__dirname, '../static/dll'),
    library: '[name]_dll_[hash:6]'
  },
  plugins: [
    new CleanWebpackPlugin({
      root: path.resolve(__dirname, '../static/dll'),
      dry: false // 启用删除文件
    }),
    new webpack.DllPlugin({
      name: '[name]_dll_[hash:6]',
      path: path.resolve(__dirname, '../static/dll', '[name].dll.manifest.json')
    })
  ]
};复制代码
  • 修改webpack.prod.conf.js

使用add-asset-html-webpack-plugin动态添加dll.jshtml

须要注意

  1. add-asset-html-webpack-plugin要在HtmlWebpackPlugin后引入;

  2. html-webpack-plugin依赖包版本4.0.0-alpha会出个问题,添加上去的路径会变成undefined须要是3.2.0版本

const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');
...
plugins: [
  // 插入dll json
  new webpack.DllReferencePlugin({
    context: path.join(__dirname),
    manifest: require('../static/dll/vendor.dll.manifest.json')
  }),
  new HtmlWebpackPlugin(),
  // 插入 dll js
  new AddAssetHtmlPlugin([{
    publicPath: config.build.assetsPublicPath + 'static/dll/',  // 注入到html中的路径
    outputPath: 'static/dll/', // 输出文件目录
    filepath: resolve('static/dll/*.js'), // 文件路径
    includeSourcemap: false,
    typeOfAsset: "js"
  }])
]复制代码

五.按需加载代码

经过vue写的单页应用时,可能会有不少的路由引入。当打包构建的时候,javascript包会变得很是大,影响加载。若是咱们能把不一样路由对应的组件分割成不一样的代码块,而后当路由被访问的时候才加载对应的组件,这样就更加高效了。这样会大大提升首屏显示的速度,可是可能其余的页面的速度就会降下来。
项目中路由按需加载(懒加载)的配置:

const Foo = () => import('./Foo.vue')
const router = new VueRouter({
  routes: [
    { path: '/foo', component: Foo }
  ]
})复制代码

六.提取公共代码

若是每一个页面的代码都将这些公共的部分包含进去,则会形成如下问题 :
• 相同的资源被重复加载,浪费用户的流量和服务器的成本。
• 每一个页面须要加载的资源太大,致使网页首屏加载缓慢,影响用户体验。
若是将多个页面的公共代码抽离成单独的文件,就能优化以上问题 。Webpack内置了专门用于提取多个Chunk中的公共部分的插件CommonsChunkPlugin。
项目中CommonsChunkPlugin的配置:
// 全部在 package.json 里面依赖的包,都会被打包进 vendor.js 这个文件中。

new webpack.optimize.CommonsChunkPlugin({
  name: 'vendor',
  minChunks: function(module, count) {
    return (
      module.resource &&
      /\.js$/.test(module.resource) &&
      module.resource.indexOf(
        path.join(__dirname, '../node_modules')
      ) === 0
    );
  }
}),
// 抽取出代码模块的映射关系
new webpack.optimize.CommonsChunkPlugin({
  name: 'manifest',
  chunks: ['vendor']
}),复制代码

总结:

在现实项目中,项目上线后无疑就会要进行优化,特别是使用webpack打包后的项目,若是没有进行优化,仅靠通常的脚手架搭建默认的配置,打包出来的项目性能堪忧,最直接体现的就是首屏加载速度,也是前端面试中常常考验的哦,不慌,通过本文以上六种(包括但不限于)优化,打包从30分钟,到2分钟不到,总体还有优化空间,可使用其余cdn等再进行优化方式,快去试试吧!

------------------------------------------------------------------------------------------------

相关文章
相关标签/搜索