vue项目打包优化

首先第一步通过浏览器看首次加载的问题大小,时间跨度等方面入手

1. Coverage观察
Coverage是chrome开发者工具的一个新功能,从字面意思上可以知道它是可以用来检测代码在网站运行时有哪些js和css是已经在运行,而哪些js和css是还没有用到的,如图,这是我在打开csdn网页时,所显示的已运行和尚未运行的代码情况。

最右边显示的是我们加载的css和js文件数量,红色区域表示已运行的代码,而青色表示已加载但未运行的代码。可用来发现页面中尚未用到的js 和 css代码,你可以为用户只提供必要的代码,这样就可以提升页面的性能。这对于找出可以进行拆分的脚本以及延迟加载非关键脚本来说非常有用。
在这里插入图片描述

上面录制的数据中,最大的文件是 vendor.js,如果某个文件覆盖率低(即未使用代码比例很高),通常意味着用户加载了太多不必要的代码(要么真的是无用代码,要么是当前时点还没执行到的代码),有性能常识的同学不难推断出,这会导致页面的完全加载时间、或单页应用的启动时间变慢,在慢速网络下的性能损耗会尤其明显;此外,更多代码的解析、编译也就意味着更多的硬件资源消耗,在低端设备上也会存在明显的性能问题。
以 Coverage 数据为参考,我们能了解页面重无用代码的比例到底有多大。现实世界中,很多工程师可能是在遗留代码库上工作,并且遗留代码库存在的时间还很长,那么很可能这个代码库中存在大量的无用代码,但是谁也不敢删除他们,因为 JS 这门语言的动态性,你不能粗暴的把哪些看起来“没有被使用”的代码直接删掉,除非你很清楚所有的代码执行路径,很显然这对于大型应用或者遗留代码库来说是不现实的。
怎么移除死代码呢?我们可以依赖打包工具,比如 UglifyJS 在压缩代码时支持直接删除死代码的配置项。而 Webpack 2 中引入了 Tree Shaking 的特性,能够自动把项目中没有用到的代码从打包中去掉,但是这种优化仅限于被 export 的代码。总而言之,死代码要尽可能想办法去掉,Coverage 工具能提供一个判断基准。

2. webpack-bundle-analyzer:查看资源树

cnpm i webpack-bundle-analyzer
chainWebpack: config => {
 config
        .plugin('webpack-bundle-analyzer')
        .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
 }

运行 npm run build --report
在这里插入图片描述

基本上可以看到整个项目包结构,接下来针对我们的项目开始进行瘦身减肥操作

1. productionSourceMap:false
如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建,如果特殊情况,生产环境上面报错了,为了方便定位问题,可以设置为true,他可以打包出一份源码出来,方便我们定位生产环境上面的问题。不过一般情况下是false

 productionSourceMap: process.env.NODE_ENV !== 'production', 

2. 路由懒加载

import ShowBlogs from '@/components/ShowBlogs'
routes:[ path: 'Blogs', name: 'ShowBlogs', component: ShowBlogs ]

 routes:[ path: 'Blogs',name: 'ShowBlogs',component: () => import('./components/ShowBlogs.vue')

3. 将打包的文件进行切割分包,方便加载的时候能多路加载

// 源(asset)和入口起点超过指定文件限制 会有警告 打包时可以 去掉这个提示
      config.performance = {
        // 入口起点的最大体积
        maxEntrypointSize: 5000000,
        // 生成文件的最大体积
        maxAssetSize: 3000000,
        // hints: 'warning',   // 超出大小之后的警告
        hints: false
      }

4. webpack ContextReplacementPlugin插件
如果项目里面涉及到momen locale zh-cn等可以通过webpack ContextReplacementPlugin插件
webpack 打包momentjs时会把所有语言包都打包,这样会使打包文件很大。此插件可以帮助我们只打包需要的语言包,大大减小打包文件大小。

 config.plugins.push(new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /zh-cn/))

5.开启缓存,多线程编译

config.optimization.minimizer.push(
        new UglifyJsPlugin({
          uglifyOptions: {
            warnings: false,
            cache: true, // 开启缓存
            parallel: true, // 开启多线程编译
            compress: {
              drop_console: true,
              pure_funcs: ['console.log']
            }
          }
        })
      )

6. 对打包文件进行切割,控制加载文件个数,缓存已经打包的文件,避免重复打包

config.optimization.splitChunks({
      chunks: 'all', // async异步代码分割 initial同步代码分割 all同步异步分割都开启
      minSize: 30000, // 字节引入的文件大于30kb才进行分割
      // maxSize: 50000,         //50kb,尝试将大于50kb的文件拆分成n个50kb的文件
      minChunks: 1, // 模块至少使用次数
      maxAsyncRequests: 5, // 同时加载的模块数量最多是5个,只分割出同时引入的前5个文件
      maxInitialRequests: 3, // 首页加载的时候引入的文件最多3个
      automaticNameDelimiter: '~', // 缓存组和生成文件名称之间的连接符
      name: true, // 缓存组里面的filename生效,覆盖默认命名
      cacheGroups: {
        // 缓存组,将所有加载模块放在缓存里面一起分割打包
        common: {
          // 默认打包模块
          priority: 1,
          reuseExistingChunk: true // 模块嵌套引入时,判断是否复用已经被打包的模块
          // filename: 'common.js'
        },
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: 2
          // filename: 'vendors.js'
        }
      }
    })

7. 关闭Prefetch
因为vuecli 3默认开启prefetch(预先加载模块),提前获取用户未来可能会访问的内容
在首屏会把这十几个路由文件,都一口气下载了
所以我们要关闭这个功能,在vue.config.js中设置

// 移除 preload 插件 (去除默认预加载)
    config.plugins.delete('preload')
config.plugins.delete('prefetch')

8. 针对图片进行优化,大于10kb的正常加载,小于10kb的进行baseurl转换,可以提升浏览器初始化加载的效率

// 编译图片
    config.module
      .rule('images')
      .test(/\.(png|jpeg|gif|jpg)$/)
      .use('url-loader')
      .loader('url-loader')
      .options({
        limit: 1024 * 10, // 小于10k的图片采用baseurl,大于和等于10k的就正常打包成图片
        name: 'static/[name].[ext]'
      })

9. 针对css是否开始source map

 sourceMap: process.env.NODE_ENV === 'production', // 是否为 CSS 开启 source map。设置为 true 之后可能会影响构建的性能

10. 配置babel.config.js文件进行按需加载

 plugins: [
    "@babel/plugin-proposal-optional-chaining", // 可选链 ?.
    '@babel/plugin-proposal-nullish-coalescing-operator',  //空值合并 ??
    [
      "import",
      {
        libraryName: ["ant-design-vue"],
        libraryDirectory: "es",
        style: "css"
      },
    ]
  ]

11. 对发布生产环境的时候开启gzip压缩

 if (process.env.NODE_ENV === 'production') {
      config.plugin('compressionPlugin').use(
        new CompressionPlugin({
          test: /\.(js|css|less|html)$/, // 匹配文件名
          threshold: 10240, // 对超过10k的数据压缩
          deleteOriginalAssets: false, // 不删除源文件
          algorithm: 'gzip',
          minRatio: 0.8
        })
      )
    }

下面是整个vue.config.js的配置代码

const path = require('path')
const CompressionPlugin = require('compression-webpack-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const webpack = require('webpack')
const UselessFile = require('useless-files-webpack-plugin')
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i
function resolve(dir) {
  return path.join(__dirname, dir)
}

module.exports = {
  outputDir: 'dist', // 目录的内容在构建之前会被清除
  publicPath: '/', //根路径 cli3.0以上使用publicPath替代baseUrzl,解决build后找不到静态资源的问题
  productionSourceMap: process.env.NODE_ENV !== 'production', // 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。
  lintOnSave: process.env.NODE_ENV !== 'production', //生产构建时禁用 eslint-loader,它的有效值为 'warning' | 'default' | 'error'
  assetsDir: 'assets', // 放置生成静态资源的目录
  configureWebpack: config => {
    config.plugins.push(new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /zh-cn/))
    // 为生产环境修改配置
    if (process.env.NODE_ENV === 'production') {
      config.mode = 'production'
      // 源(asset)和入口起点超过指定文件限制 会有警告 打包时可以 去掉这个提示
      config.performance = {
        // 入口起点的最大体积
        maxEntrypointSize: 50000000,
        // 生成文件的最大体积
        maxAssetSize: 30000000,
        hints: 'warning', // 超出大小之后的警告
        //hints: false
        assetFilter: function (assetFilename) {
          return assetFilename.endsWith('.js')
        }
      }
      config.optimization.minimizer.push(
        new UglifyJsPlugin({
          uglifyOptions: {
            warnings: false,
            cache: true, // 开启缓存
            parallel: true, // 开启多线程编译
            compress: {
              // drop_console: true, // 移除console
              drop_debugger: true // 删除debug
              // pure_funcs: ['console.log']
            }
          },
          sourceMap: false, // 缩小打包体积
          parallel: true, // 使用多进程压缩
          cache: true, // 启用缓存
          extractComments: true // 抽离注释,单独抽出成一个文件
        })
      )
    }
  },
  chainWebpack: config => {
    // 移除prefetch插件,此插件是用来告诉浏览器在页面加载完成后,利用空闲时间提前获取用户未来可能会访问的内容
    //因为vuecli 3默认开启prefetch(预先加载模块),提前获取用户未来可能会访问的内容在首屏会把这十几个路由文件,都一口气下载了
    config.plugins.delete('prefetch')
    config.resolve.alias
      .set('@$', resolve('src'))
      .set('@api', resolve('src/api'))
      .set('@assets', resolve('src/assets'))
      .set('@comp', resolve('src/components'))
      .set('@views', resolve('src/views'))
    // .set('@ant-design/icons/lib/dist$', resolve('src/icons.js'))
    config.optimization.splitChunks({
      chunks: 'all', // async异步代码分割 initial同步代码分割 all同步异步分割都开启
      minSize: 30000, // 字节引入的文件大于30kb才进行分割
      // maxSize: 50000,         //50kb,尝试将大于50kb的文件拆分成n个50kb的文件
      minChunks: 1, // 模块至少使用次数
      maxAsyncRequests: 5, // 同时加载的模块数量最多是5个,只分割出同时引入的前5个文件
      maxInitialRequests: 3, // 首页加载的时候引入的文件最多3个
      automaticNameDelimiter: '~', // 缓存组和生成文件名称之间的连接符
      name: true, // 缓存组里面的filename生效,覆盖默认命名
      cacheGroups: {
        // 缓存组,将所有加载模块放在缓存里面一起分割打包
        common: {
          // 默认打包模块
          priority: 1,
          reuseExistingChunk: true // 模块嵌套引入时,判断是否复用已经被打包的模块
          // filename: 'common.js'
        },
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: 2
          // filename: 'vendors.js'
        }
      }
    })

    // 移除 preload 插件 (去除默认预加载)
    config.plugins.delete('preload')
    // 移除 prefetch 插件 (去除默认预加载)
    config.plugins.delete('prefetch')
    // 生产环境,开启js\css压缩
    if (process.env.NODE_ENV === 'production') {
      // 查看线上打包文件大小
      // config
      //   .plugin('webpack-bundle-analyzer')
      //   .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
      config.plugin('compressionPlugin').use(
        new CompressionPlugin({
          test: productionGzipExtensions, // 匹配文件名
          threshold: 10240, // 对超过10k的数据压缩
          deleteOriginalAssets: false, // 不删除源文件
          algorithm: 'gzip',
          minRatio: 0.8
        })
      )
    }

    // 检测项目是否存在多余的文件
    // config.plugin('uselessFile').use(
    //   new UselessFile({
    //     root: './src', // 项目目录
    //     out: './fileList.json', // 输出文件列表
    //     clean: false, // 是否删除文件,
    //     exclude: [/node_modules/] // 排除文件列表
    //   })
    // )

    // 配置 webpack 识别 markdown 为普通的文件
    config.module
      .rule('markdown')
      .test(/\.md$/)
      .use()
      .loader('file-loader')
      .options({
        name: 'img/[name].[hash:8].[ext]',
        esModule: false // 这里设置为false
      })
      .end()

    // 编译vxe-table包里的es6代码,解决IE11兼容问题
    config.module
      .rule('vxe')
      .test(/\.js$/)
      .include.add(resolve('node_modules/vxe-table'))
      .add(resolve('node_modules/vxe-table-plugin-antd'))
      .end()
      .use()
      .loader('babel-loader')
      .end()

    // 编译图片
    config.module
      .rule('images')
      .test(/\.(png|jpeg|gif|jpg)$/)
      .use('url-loader')
      .loader('url-loader')
      .options({
        limit: 1024 * 10, // 小于10k的图片采用baseurl,大于和等于10k的就正常打包成图片
        name: 'static/[name].[ext]',
        esModule: false // 处理图片引用不出来的问题
      })
  },

  css: {
    sourceMap: false, // process.env.NODE_ENV === 'production', // 是否为 CSS 开启 source map。设置为 true 之后可能会影响构建的性能
    loaderOptions: {
      less: {
        modifyVars: {
          /* less 变量覆盖,用于自定义 ant design 主题 */
          'primary-color': '#F5222D',
          'link-color': '#F5222D',
          'border-radius-base': '4px'

          // 'primary-color': '#1890FF',
          // 'link-color': '#1890FF',
          // 'border-radius-base': '4px'
        },
        javascriptEnabled: true
      }
    }
  },

  devServer: {
    // 设置让浏览器 overlay 同时显示警告和错误
    overlay: {
      warnings: true,
      errors: true
    },
    port: 10086,
    proxy: {
      /* 注意:jeecgboot前端做了改造,此处不需要配置跨域和后台接口(只需要改.env相关配置文件即可)issues/3462 很多人此处做了配置,导致刷新前端404问题,请一定注意 */
      [process.env.VUE_API_FIX]: {
        // target: process.env.VUE_APP_API_BASE_URL,
        target: 'http://172.16.1.211:10081',
        ws: false,
        changeOrigin: true
      }
    }
  }
}
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
对于Vue项目打包速度优化,可以尝试以下几种方法: 1. 使用CDN:将一些常用的第三方库(如VueVuex、Vue Router等)从本地打包中移除,改为通过CDN引入。这样可以减少打包体积和加快打包速度。 2. 按需引入组件:在使用UI组件库时,可以考虑按需引入组件,而不是全部引入。这可以通过babel-plugin-component等工具来实现,减少不必要的打包和编译时间。 3. 代码拆分:将大型的代码块拆分成更小的模块,利用Webpack的代码分割功能(如异步加载、按需加载)来实现懒加载。这样可以减少初始加载时间,提升用户体验。 4. 优化图片:对于项目中的图片资源,可以使用压缩工具来减小图片大小,如使用imagemin-webpack-plugin等插件进行图片压缩。 5. 缓存和持久化:合理利用浏览器缓存和服务端缓存,减少不必要的请求和加载时间。另外,可以考虑使用localStorage或IndexedDB等技术进行数据持久化,减少数据加载时间。 6. 使用Tree Shaking:通过配置Webpack的tree shaking功能,可以剔除项目中未使用的代码,减少打包体积和提升加载速度。 7. 配置合理的Webpack:根据项目需求,合理配置Webpack的各项参数,如使用cache-loader、thread-loader等插件来提升构建速度。 需要注意的是,优化策略要根据具体项目情况进行选择,不同的项目可能有不同的瓶颈和优化空间。可以通过Webpack Bundle Analyzer等工具来分析打包结果,找出优化的重点。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浪里个浪里个浪里个浪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值