vue项目的webpack打包优化

2023-11-12

前言

我第一次从搭建项目环境,到打包准备上线测试,vue对开发者来说学习成本不高,带来了很多的便利。没有经过如何优化,直接打包出来,打开页面时就看到无尽的加载中。。。

啥???是网络不好了???

等了半分钟时间页面终于出现了。我第一次打包,所以百度做功课,原来是vue打包出来文件体积太大,而且会影响到首屏加载。

那么,如何做到优化?

分析打包结果

借助webpack-bundle-analyzer插件,可以看到打包后每个文件的内容的大小。

第一步:安装webpack-bundle-analyzer 

npm install webpack-bundle-analyzer --save-dev  

第二步:在vue.config.js文件中引入

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin

第三步:在webpack配置中使用该插件

module.exports = {
    configureWebpack: config => {
        config.plugins.push(
            new BundleAnalyzerPlugin()
        )
    },
}

 第四步:运行

npm run build

 自动打开浏览器显示一个项目打包分析图,便于直观各个文件的大小

 可以看到最大vendors文件达到了2.37M,下面开始瘦身。

一、关闭生产环境的sourceMap

vue项目打包之后js文件夹中,会自动生成一些map文件,是方便于运行时报错可以准确的输出是哪一行哪一列有错,但map文件占用一部分空间。

关闭生产环境,如下配置:

module.exports = {
    // 生产环境是否生成 sourceMap 文件
    productionSourceMap: false,
}

关闭生产环境对比,减少了很大体积

前:dist大小为13.9MB

后:dist大小为3.44MB

二、路由懒加载

在router.js文件中,原来的静态引用方式

import Echarts from '../views/Echarts.vue'

const routes = [
  {
    path: "/echarts",
    name: "Echarts",
    component: Echarts,
  },
];

改为

const routes = [
  {
    path: "/echarts",
    name: "Echarts",
    component: () => import('../views/Echarts.vue')
  },
];

如果没有应用懒加载,打包会非常大,影响首屏页面加载,加载的内容过多,时间过长,会出长时间的白屏。而能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。 

三、ant-design组件按需加载

首屏需要加载的依赖包,其中ant-design整整占了1.03MB。

首先安装babel-plugin-import

npm install babel-plugin-import --save-dev

 然后在babel.config.js文件配置

module.exports = {
  presets: ["@vue/cli-plugin-babel/preset"],
  plugins: [
    [ "import", {
      "libraryName": "ant-design-vue",
      "libraryDirectory": "es",
      "style": "css"
    } ]
  ]
};

然后在main.js中引入需要的部分组件

import { Button } from 'ant-design-vue';

const app = createApp(App);
app.use(Button).mount('#app');

注意:有一些组件的引入方式有所不同,具体的参照ant-design官网介绍。

import { message } from 'ant-design-vue';
const app = createApp(App);
app.config.globalProperties.$message = message;

再运行npm run build,查看项目打包的分析图

 可以看到vendors减少到了1.31MB。

四、外部引入模块(CDN)

我们可以把第三方库通过cdn的方式引入项目,这样vendor.js会减少,并且大大提升首屏加载速度。

在vue.config.js配置

const isProduction = process.env.NODE_ENV === 'production';

const cdn = {
    css: [
        'https://cdnjs.cloudflare.com/ajax/libs/ant-design-vue/2.2.8/antd.min.css'
    ],
    js: [
        'https://unpkg.com/vue@3.2.20/dist/vue.runtime.global.prod.js',
        'https://cdnjs.cloudflare.com/ajax/libs/vue-router/4.0.0/vue-router.global.prod.min.js',
        'https://cdnjs.cloudflare.com/ajax/libs/vuex/4.0.0/vuex.global.prod.min.js',
        'https://cdnjs.cloudflare.com/ajax/libs/ant-design-vue/2.2.8/antd.min.js',
        'https://cdnjs.cloudflare.com/ajax/libs/echarts/4.8.0/echarts.min.js'
    ]
}

module.exports = {
    chainWebpack: (config) => {
        // 生产环境配置
        if (isProduction || devNeedCdn) {
            // 生产环境注入cdn
            config.plugin('html')
                .tap(args => {
                    args[0].cdn = cdn;
                    return args;
                });
        }
    },
    configureWebpack: config => {
        // 用cdn方式引入,则构建时要忽略相关资源
        if (isProduction || devNeedCdn) config.externals = cdn.externals;

        if (isProduction) {
            config.externals = {
                'vue': 'Vue',
                'vue-router': 'VueRouter',
                'vuex': 'Vuex',
                'ant-design-vue': 'antd',
                'echarts': 'echarts'
            }
        }
    },
}

说明

这里配置externals字段,是将第三方库抽取出来。

config.externals = {
    'vue': 'Vue',
    'vue-router': 'VueRouter',
    'vuex': 'Vuex',
    'ant-design-vue': 'antd',
    'echarts': 'echarts'
}

 以打包ant-design-vue为例,"ant-design-vue" 指的是你import语句中import Antd from 'ant-design-vue'中的'ant-design-vue', "antd"是ant-design-vue这个库暴露出来的全局对象。这个对象你可以从cdn资源的源码中找到或者根据需要引用的文件去node_modules文件夹下去寻找。下面我从node_modules文件夹下的源码找一下ant-design-vue,vue-router和vuex暴露出的全局对象,以下是各源码的截图:

 如果没有按需加载,以echarts为例,import * as echarts from “echarts”的echarts是全局对象,如下:

做完这些之后,在public/index.html文件中引入cdn链接,如下:

<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title><%= htmlWebpackPlugin.options.title %></title>
    <!-- 使用CDN的CSS文件 -->
    <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %>
      <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet">
    <% } %>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
    <!-- 使用CDN加速的JS文件,配置在vue.config.js下 -->
    <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js) { %>
      <script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
    <% } %>
  </body>
</html>

再运行npm run build,查看项目打包的分析图

  可以看到vendors减少到了400kb。

五、gzip

安装compression-webpack-plugin

npm install compression-webpack-plugin --save-dev

如果打包时候出现Cannot read property 'tapPromise' of undefined 这个报错,是compression-webpack-plugin版本问题,通过降低版本就可以解决此类问题。 

在 vue.congig.js中引入并修改webpack配置,如下:

const CompressionWebpackPlugin = require('compression-webpack-plugin');
const CompressionPlugin = require("compression-webpack-plugin");
const productionGzipExtensions = ['js', 'css'];

module.exports = {
    configureWebpack: (config) => {
        if (isProduction) {
            config.plugins.push(
                new CompressionWebpackPlugin({
                    algorithm: 'gzip',
                    test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
                    threshold: 10240,
                    minRatio: 0.8
                }),

                new CompressionPlugin({
                    test: /\.(js|css)(\?.*)?$/i,//需要压缩的文件正则
                    threshold: 10240,//文件大小大于这个值时启用压缩
                    deleteOriginalAssets: false//压缩后保留原文件
                })
            );
        };
    },
}

服务器也要开gzip优化性能,请自行百度,我不做演示了。

项目开启gzip压缩和性能优化【亲测可用】

六、图片的压缩

请自行百度:图好快。

七、使用uglifyjs-webpack-plugin插件去除console.log打印以及注释

npm install uglifyjs-webpack-plugin --save-dev

const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const isProduction = process.env.NODE_ENV === 'production';

configureWebpack: config => {
   const plugins = [];
   if (isProduction) {
      plugins.push(
        new UglifyJsPlugin({
          uglifyOptions: {
            output: {
              comments: false, // 去掉注释
            },
            warnings: false,
            compress: {
              drop_console: true,
              drop_debugger: false,
              pure_funcs: ['console.log']//移除console
            }
          }
        })
      )
   }
},

 虽然congsole.log()以及注释不会占用太多体积(也就几kb,甚至几十kb)。

八、完整配置

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const CompressionWebpackPlugin = require('compression-webpack-plugin');
const CompressionPlugin = require("compression-webpack-plugin")
const productionGzipExtensions = ['js', 'css'];
const isProduction = process.env.NODE_ENV === 'production';

const cdn = {
    css: [
        'https://cdnjs.cloudflare.com/ajax/libs/ant-design-vue/2.2.8/antd.min.css'
    ],
    js: [
        'https://unpkg.com/vue@3.2.20/dist/vue.runtime.global.prod.js',
        'https://cdnjs.cloudflare.com/ajax/libs/vue-router/4.0.0/vue-router.global.prod.min.js',
        'https://cdnjs.cloudflare.com/ajax/libs/vuex/4.0.0/vuex.global.prod.min.js',
        'https://cdnjs.cloudflare.com/ajax/libs/ant-design-vue/2.2.8/antd.min.js',
        'https://cdnjs.cloudflare.com/ajax/libs/echarts/4.8.0/echarts.min.js'
    ]
}

// 本地环境是否需要使用cdn
const devNeedCdn = false

module.exports = {
    // 基本路径
    publicPath: './',
    // 输出文件目录
    outputDir: 'dist',
    // eslint-loader 是否在保存的时候检查
    lintOnSave: false,
    // 生产环境是否生成 sourceMap 文件
    productionSourceMap: false,
    chainWebpack: (config) => {
        // 生产环境配置
        if (isProduction || devNeedCdn) {
            // 生产环境注入cdn
            config.plugin('html')
                .tap(args => {
                    args[0].cdn = cdn;
                    return args;
                });
        }
    },
    configureWebpack: config => {
        // 用cdn方式引入,则构建时要忽略相关资源
        if (isProduction || devNeedCdn) config.externals = cdn.externals;

        if (isProduction) {
            config.externals = {
                'vue': 'Vue',
                'vue-router': 'VueRouter',
                'vuex': 'Vuex',
                'ant-design-vue': 'antd',
                'echarts': 'echarts'
            },
            config.plugins.push(
                new CompressionWebpackPlugin({
                    algorithm: 'gzip',
                    test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
                    threshold: 10240,
                    minRatio: 0.8
                }),

                new CompressionPlugin({
                    test: /\.(js|css)(\?.*)?$/i,//需要压缩的文件正则
                    threshold: 10240,//文件大小大于这个值时启用压缩
                    deleteOriginalAssets: false//压缩后保留原文件
                })
            );
        }

        // 关于打包后包资源各部分占比的配置相关
        // config.plugins.push(
        //     new BundleAnalyzerPlugin()
        // )
    },
    devServer: {
        overlay:{
            warning:false,
            errors:false
        },
        open: process.platform === 'darwin',
        host: 'localhost',
        port: 80,
        https: false,
        hotOnly: false,
        proxy: '', 
    },
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

vue项目的webpack打包优化 的相关文章

随机推荐

  • musescore 构建入门

    musescore 1 QT上面开发 2 Qt由于版本更新 更新到QT6了 构建器由qmake 更换到cmake musescore 在QT是用cmake 构建桌面软件包 3 底层依赖库 几乎都是音频相关的库 下面是windows 系统下面
  • 求无冲突矢量集合

    在PRNET中 i发送的分组能被j正确接收的充要条件是 1 存在i j的链路 2 当i发送时 没有其他节点k发送 即不存在k j 广播形式的也算 3 i发给j时 j只处于接收状态 即j不能发给其他节点 除了上述这些原则 还有一些在做题的时候
  • Linux Ubuntu apt-get安装mysql

    自从转前端以后好久都没有和数据库打过交道了 最近在写一个node项目需要用到mysql 但是又不想在本地安装数据库 就想着在云服务器上安装了 网上百度了安装方法 大多都是去mysql官网下载官方编译好的二进制文件 这个至少都是几百M大小的安
  • 用BeanFactoryAware接口,用BEAN的名称来获取BEAN对象

    用BeanFactoryAware接口 用BEAN的名称来获取BEAN对象 applicationContext beans xml
  • Docker----Dockerfile中执行pip install 命令报 Failed to establish a new connection 错误的解决办法

    原文链接 Docker Dockerfile中执行pip install 命令报 Failed to establish a new connection 错误的解决办法 问题 在Dockerfile文件中通过RUN pip install
  • 计算机视觉2021年3月28最新论文

    编辑 AI速递 计算机视觉 3月28日 1 USB Universal Scale Object Detection Benchmark 标题 USB 万能物体检测基准 链接 https arxiv org abs 2103 14027 2
  • Connected to the target VM, address:XXXX, transport: socket

    问题 1 Connected to the target VM address 127 0 0 1 65604 transport socket 排查方案 我是最近半年多次遇到这个问题 这个就是用debug模式启动程序 方便调试 运行一半直
  • Ablation Study消融研究

    作者 飘哥 链接 https www zhihu com question 291655038 answer 683038545 来源 知乎 著作权归作者所有 商业转载请联系作者获得授权 非商业转载请注明出处 术语 消融研究 通常用于神经网
  • Python解释器验证器工具类

    需求背景 现需要实现一个工具类 功能为验证给定路径是否为有效的 Python 解释器可执行文件 不一定是主程序所使用的解释器 并获取该解释器版本信息 是否安装某模块 包等信息 该工具类将赋予主程序类似 PyCharm 中选取 Python
  • C#的架构、框架、设计模式

    建立层务必使用类库选项 不要使用文件夹 没错 说的就是我自己 一 两层架构 1 架构概述 两层架构适合小型 中小型项目 名称 标识 用途 数据访问对象 DAL 模型服务 需要添加Models引用 实体对象 Models 模型 用户界面 UI
  • SpringMVC @RequestBody 自动转json Http415错误

    项目中想用 RequestBody直接接收json串转成对象 网上查了使用方法 看着非常简单 不过经过测试很快发现页面直接报415错误 h1 HTTP Status 415 h1 hr size 1 p b type b Status re
  • React的几种路由配置方法

    1 标签 常用 import IndexRoute from react router const Dashboard React createClass render return div Welcome to the app div R
  • python内置array模块,与numpy中的array和list之间的转换

    numpy中matrix类型与array类型的转换 如何让 M matrix 1 2 3 4 如何转变为 array 1 2 3 4 比较优雅的办法 x matrix arange 12 reshape 3 4 gt gt gt x mat
  • 全国计算机等级考试题库二级C操作题100套(第76套)

    第76套 给定程序中 函数fun的功能是 计算下式前n项的和作为函数值返回 例如 当形参n的值为10时 函数返回 0 204491 请在程序的下划线处填入正确的内容并把下划线删除 使程序得出正确的结 果 注意 源程序存放在考生文件夹下的BL
  • 使用Fiddler修改请求参数

    1 下载比较新版的Fiddler 2 进入到调试的页面 并填写好参数 以获取短信验证码接口为例 3 先清空Fiddler列表中已经存在的请求 以便观察 4 打开断点调试 下面两种方式都可以 F11是快捷键 按F11 键盘快捷键 或者如下图勾
  • Qt在嵌入式系统QNX的HMI应用方案

    author 锋影 扣扣 174176320 e mail 174176320 qq com 黑莓推出了其全新的黑莓10平台QT的智能手机和平板电脑 它产生了大量的兴趣在QT上移动 黑莓10是基于QNX1操作系统的黑莓 也许不是很出名 是Q
  • lightGBM 调参

    文章目录 1 概述 1 lgb cv函数使用方法 1 参数 2 param需要填写的参数 2 GridSearchCV调参 第一步 学习率和迭代次数 第二步 确定max depth和num leave 第三步 确定min data in l
  • Mac配置与下载安卓SDK,配置adb命令

    所以如果想要单独下载SDK 参考如下步骤 文章目录 配置步骤 1 首先需要安装java的JDK 2 解压上面下载好的文件 3 补充SDK内容 4 配置环境变量 5 测试adb命令 其他信息 配置步骤 1 首先需要安装java的JDK 首先登
  • Linux查看磁盘空间

    如何查看磁盘空间 1 查看内存空间 dever iZ2zeewvm4yos65shrzg3wZ free total used free shared buff cache available Mem 7724300 1528996 300
  • vue项目的webpack打包优化

    前言 我第一次从搭建项目环境 到打包准备上线测试 vue对开发者来说学习成本不高 带来了很多的便利 没有经过如何优化 直接打包出来 打开页面时就看到无尽的加载中 啥 是网络不好了 等了半分钟时间页面终于出现了 我第一次打包 所以百度做功课