vue打包篇-分析包数据再进行CDN配置图片文件压缩等优化

前言

vue程序代码写完了,不做任何优化,发现包有点大,为此我们需要分析打包文件中都有些什么。才能对症下药。主要是因为博主当初的服务器才1M带宽........1M

该Demo为vue3.0的~

查看包文件

  • 这个没有优化过的包

vue打包篇-分析包数据再进行CDN配置图片文件压缩等优化_第1张图片

  • 首先,修改我们的 package.json 文件

vue打包篇-分析包数据再进行CDN配置图片文件压缩等优化_第2张图片

  • 然后执行打包命令

npm run build

vue打包篇-分析包数据再进行CDN配置图片文件压缩等优化_第3张图片

  • 我们会发现多了一个 report.html,打开他

vue打包篇-分析包数据再进行CDN配置图片文件压缩等优化_第4张图片

  • 加载时长

vue打包篇-分析包数据再进行CDN配置图片文件压缩等优化_第5张图片

分析

vue-cli的打包策略是将node_module中的包打包成一个chunk-vendors.js 其他的js 如assets中的打包成app.js。

现在我们需要:

1、尽量减小打包的大小,可采用CDN方式加载;

2、将包打包成压缩包并且配置好nginx压缩功能;

  • configureWebpack 通过操作对象的形式,来修改默认的webpack配置,该对象将会被 webpack-merge 合并入最终的 webpack 配置
  • chainWebpack 通过链式编程的形式,来修改默认的webpack配置
/*
 * @Author: Penk
 * @LastEditors: Penk
 * @LastEditTime: 2020-11-05 10:09:37
 * @FilePath: \penk-web-master\Vue.config.js
 */
const path = require('path');
const webpack = require('webpack');
​
function resolve(dir) {
    return path.join(__dirname, dir)
}
//config/index.js
const os = require('os');
​
// 动态设置IP,多网卡,需要配置正则表达式 如下方
// (/^192.168.1.*&/).test(alias.address)) 即表示192.168.1.1 网段
function getNetworkIp() {
    let needHost = ''; // 打开的host
    try {
        // 获得网络接口列表
        let network = os.networkInterfaces();
        for (let dev in network) {
            let iface = network[dev];
            console.log(iface)
            for (let i = 0; i < iface.length; i++) {
                let alias = iface[i];
                if (alias.family === 'IPv4' &&
                    alias.address !== '127.0.0.1' &&
                    !alias.internal &&
                    (/^192.168.1.(\d+)$/).test(alias.address)) {
                    needHost = alias.address;
                }
            }
        }
    } catch (e) {
        needHost = 'localhost';
    }
    return needHost;
}
​
// 代码压缩
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
​
// gzip压缩
const CompressionWebpackPlugin = require('compression-webpack-plugin')
​
// 是否为生产环境
const isProduction = process.env.NODE_ENV !== 'development'
​
// 本地环境是否需要使用cdn
const devNeedCdn = true;
​
// cdn链接
const cdn = {
    // cdn:模块名称和模块作用域命名(对应window里面挂载的变量名称)
    // externals中的key是用于import,
    // value表示的在全局中访问到该对象,就是window.echarts
    externals: {
        vue: 'Vue',
        vuex: 'Vuex',
        'vue-router': 'VueRouter',
        'element-ui': 'ELEMENT',
        'echarts': 'echarts',
        'moment': 'moment',
        'mavon-editor': 'MavonEditor',
        'jquery': '$',
        'tinymce': 'tinymce',
    },
    // cdn的css链接
    css: [,
        'https://unpkg.com/[email protected]/lib/theme-chalk/index.css',
        'https://unpkg.com/[email protected]/lib/theme-chalk/display.css',
        'https://unpkg.com/[email protected]/dist/css/index.css',
        'https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.7.2/animate.min.css'
    ],
    // cdn的js链接
    js: [
        'https://cdn.staticfile.org/vue/2.6.11/vue.min.js',
        'https://cdn.staticfile.org/vuex/3.1.2/vuex.min.js',
        'https://cdn.staticfile.org/vue-router/3.1.5/vue-router.min.js',
        'https://unpkg.com/[email protected]/lib/index.js',
        'https://unpkg.com/[email protected]/dist/echarts.min.js',
        'https://cdn.bootcss.com/moment.js/2.20.1/moment.min.js',
        'https://cdn.bootcss.com/moment.js/2.20.1/locale/zh-cn.js',
        'https://unpkg.com/[email protected]/dist/mavon-editor.js',
        'https://cdn.bootcss.com/jquery/3.5.1/jquery.min.js',
        'https://cdn.bootcss.com/tinymce/5.2.0/tinymce.min.js'
    ]
}
​
module.exports = {
    pwa: {
        iconPaths: {
            favicon32: 'favicon.ico',
            favicon16: 'favicon.ico',
            appleTouchIcon: 'favicon.ico',
            maskIcon: 'favicon.ico',
            msTileImage: 'favicon.ico'
        }
    },
    productionSourceMap: process.env.NODE_ENV === 'production' ? false : true,
    publicPath: process.env.NODE_ENV === 'production' ? './' : '/',
    outputDir: 'penk-web-master-dist',
    lintOnSave: false, //是否开启eslint保存检测 ,它的有效值为 true || false || 'error'\
    css: {
        extract: false
    },
    devServer: {
        open: true,
        host: getNetworkIp(),
        port: 8886,
        proxy: {
            '/server': { //这里最好有一个 /
                // target: 'http://192.168.1.150:3000', // 后台接口域名
                target: 'http://localhost:9500', // 后台接口域名
                ws: true, //如果要代理 websockets,配置这个参数
                // secure: false, // 如果是https接口,需要配置这个参数
                changeOrigin: true, //是否跨域
                pathRewrite: {
                    '^/server': ''
                }
            }
        }
    },
    chainWebpack: config => {
        // ============压缩图片 start============
        config.module
            .rule('images')
            .test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
            .use('image-webpack-loader')
            .loader('image-webpack-loader')
            .options({
                bypassOnDebug: true
            })
            .end()
​
        // ============压缩图片 end============
​
        // ============注入cdn start============
        config.plugin('html').tap(args => {
            // 生产环境或本地需要cdn时,才注入cdn
            if (isProduction || devNeedCdn) args[0].cdn = cdn
            return args
        })
        // ============注入cdn start============
​
        // ============别名 start============
        config.resolve.alias
            .set('@', resolve('src'))
        // ============别名 start============
    },
    configureWebpack: config => {
​
        config.devtool = 'source-map'
​
        // 全局引入JQuery
        config.plugins.push(
            new webpack.ProvidePlugin({
                $: "jquery",
                jQuery: "jquery",
                jquery: "jquery",
                "windows.jQuery": "jquery",
                "windows.jquery": "jquery"
            })
        )
​
        // 用cdn方式引入,则构建时要忽略相关资源
        if (isProduction || devNeedCdn) config.externals = cdn.externals
​
        // 生产环境相关配置
        if (isProduction) {
            // 代码压缩
            config.plugins.push(
                new UglifyJsPlugin({
                    uglifyOptions: {
                        //生产环境自动删除console
                        compress: {
                            drop_debugger: true,
                            drop_console: true,
                            pure_funcs: ['console.log']
                        },
                        warnings: false, // 若打包错误,则注释这行
                    },
                    sourceMap: process.env.NODE_ENV === 'production' ? false : true,
                    parallel: true
                })
            )
​
            // gzip压缩
            const productionGzipExtensions = ['html', 'js', 'css']
            config.plugins.push(
                new CompressionWebpackPlugin({
                    // filename: '[path].gz[query]',
                    algorithm: 'gzip',
                    test: new RegExp(
                        '\\.(' + productionGzipExtensions.join('|') + ')$'
                    ),
                    threshold: 10240, // 只有大小大于该值的资源会被处理 10240
                    minRatio: 0.8, // 只有压缩率小于这个值的资源才会被处理
                    deleteOriginalAssets: false // 删除原文件,不用删除也可以,会优先传递压缩文件
                })
            )
​
            // 公共代码抽离
            config.optimization = {
                splitChunks: {
                    cacheGroups: {
                        vendor: {
                            chunks: 'all',
                            test: /node_modules/,
                            name: 'vendor',
                            minChunks: 1,
                            maxInitialRequests: 5,
                            minSize: 0,
                            priority: 100
                        },
                        common: {
                            chunks: 'all',
                            test: /[\\/]src[\\/]js[\\/]/,
                            name: 'common',
                            minChunks: 2,
                            maxInitialRequests: 5,
                            minSize: 0,
                            priority: 60
                        },
                        styles: {
                            name: 'styles',
                            test: /\.(sa|sc|c)ss$/,
                            chunks: 'all',
                            enforce: true
                        },
                        runtimeChunk: {
                            name: 'manifest'
                        }
                    }
                }
            }
        }
    }
}

比较

通过下图,可发现各包体积减小了

 vue打包篇-分析包数据再进行CDN配置图片文件压缩等优化_第6张图片

部分包已经采用CDN方式加载

vue打包篇-分析包数据再进行CDN配置图片文件压缩等优化_第7张图片

本地加载的包,已经通过压缩的方式传递

vue打包篇-分析包数据再进行CDN配置图片文件压缩等优化_第8张图片

额外Bug(图片压缩)

npm安装的image-webpack-loader会报错,哪怕你用了nrm设置了国内镜像~~~

# 使用npm安装的 image-webpack-loader在编译的时候会有问题,不信可以试试
npm install --save-dev  image-webpack-loader
npm run build
​
# 安装cnpm
npm install cnpm -g --registry=https://registry.npm.taobao.org
​
# cnpm : 无法加载文件 D:\nodejs\node_global\cnpm.ps1,因为在此系统上禁止运行脚本
# 运行cnpm会产生问题,所以需要配置一下权限
# 打开powershell
​
# 管理员授权
Start-Process powershell -Verb runAs
# 继续重新执行set-ExecutionPolicy RemoteSigned 选择 Y
​
# 安装
cnpm install --save-dev  image-webpack-loader
# 编译
npm run build

vue打包篇-分析包数据再进行CDN配置图片文件压缩等优化_第9张图片

你可能感兴趣的:(vue,vue.js,webpack)