vuecli3多页应用配置与优化

项目背景

  • 公司的活动项目太多,每一个项目都要单独配置部署环境太麻烦,所以创建了一个仓库,src/pages/下面的每一个文件夹都是是一个项目
  • 优点是
     * 这样就可以使用一个git仓库,一个jenkins配置,很方便
     * 不需要多次配置域名和nginx服务
  • 缺点是
     * 该仓库下的任何一个项目发布,其他的项目如果有变更也会一起发布了。这需要在发布项目前,review代码,减少马虎改写了其他项目的代码,引起不必要的线上bug
     * 修改了配置文件,发布后可能会影响src/pages/下的其他的线上项目,所以修改公共文件,配置文件都要注意,可以全局搜索下该文件被哪些项目引用,如果其他地方也引用了该文件,修改该文件就要慎重且通知测试来测试这块改动。如utils文件下的公共js,很多项目都引用了。如果修改的是这类文件,review代码的人也需要注意这块代码的改动
     * 针对上面的问题,其实有些公共文件可以抽取出来,放在git仓库,使用tag引用,这样就能减少上面的问题

项目准备

  • 技术框架:vue-cli3
  • 按照vue-cli3官方文档搭建项目
  • 添加vue.config.js修改打包配置,满足多页面打包要求
  • 添加.env.development、.env.test、.env.beta、.env.production文件(环境变量)
  • 修改后的框架代码可以参考 vue-cli3-mpa-spa
  • 详细说明可以看REANDE.md里面的说明

第一版的vue.vonfig.js里面的代码如下

let path = require('path')
let glob = require('glob')
 
function resolve (dir) {
    return path.join(__dirname, dir)
}
 
let pageNum=0
 
//配置pages多页面获取当前文件夹下的html和js
function getEntry(globPath) {
    let [entries,basename]=[{},'']

    glob.sync(globPath).forEach(function(entry,i) {
        basename = path.basename(entry, path.extname(entry));
        pathname = basename; // 正确输出js和html的路径
 
        let filename=entry.split('./src/pages/')[1]
        let middlePath=filename.split('/index.html')[0]
        let dirList=middlePath.split("/")
 

        entries[i+'-'+dirList[dirList.length-1]] = {
            entry: 'src/pages/' + middlePath + '/main.js',
            template: 'src/pages/' + middlePath + '/index.html',
            filename,
        }
  pageNum=i
    })
 
    return entries
}
 
let pages = getEntry('./src/pages/**/index.html');
 
module.exports = {
    css: {
        // 是否使用css分离插件 ExtractTextPlugin
        extract: true,
        // 开启 CSS source maps?
        sourceMap: false,
        // css预设器配置项
        loaderOptions: {},
        // 启用 CSS modules for all css / pre-processor files.
        modules: false
    },
 
    devServer: {
        disableHostCheck: true
    },
 
    chainWebpack: (config)=>{
        config.resolve.alias
            .set('@', resolve('src'))
            .set('assets',resolve('src/assets'))
            .set('components',resolve('src/components'))
            .set('utils',resolve('src/utils'))
            .set('api',resolve('src/api'))
    },
 
    pages
    
}

出现的问题

1、图片过大,影响访问速度,如src/pages/mpa-one/detail/App.vue里面引入的图片,源文件是12MB,dist/img/map-one-details.png还是12MB

先看下vue-cli3默认对图片做了哪些处理

执行npm run inspect或npm run inspectwebpack(package.json的srcipt字段里面配置的命令)

/* npm run inspect操作和npm run inspectwebpack的区别是前者将webpack文件打印在命令行里,后者将webpack文件打印在output.js(没有该文件会自动创建并将内容写入output.js)里面*/
/* 执行命令完成后,可以看到webapck打包文件,在module.rules里面看到关于image的配置,代码如下,没有做压缩配置*/
/* config.module.rule('images') */
{
    test: /\.(png|jpe?g|gif|webp)(\?.*)?$/,    
    use: [
        /* config.module.rule('images').use('url-loader') */
        {
            loader: 'url-loader',
            options: {
                limit: 4096,
                fallback: {
                    loader: 'file-loader',
                    options: {
                        name: 'img/[name].[hash:8].[ext]'
                    }
                }
            }
        }
    ]
}

解决方案:

a、对于项目中的图片(尤其是大图片)可以使用压缩网站先压缩一下
b、添加图片压缩配置,执行npm install image-webpack-loader --save-dev,在vue.config.js里面的chainWebpack字段里添加如下配置
先在命令行安装插件npm i image-webpack-loader --D

config.module
    .rule('images')
    .use('image-webpack-loader')
    .loader('image-webpack-loader')

添加上述配置后再执行npm run build后看下dist里面的图片发现从12MB降到2.88MB
将src/pages/mpa-one/detail/App.vue里面的图片在网站上压缩一下(从12MB到1.71MB),在src/pages/mpa-one/list/App.vue里面引入,再执行npm run build 发现从1.71MB降到1.54MB

注意图片的引用问题

在 JavaScript 被导入或在 template/CSS 中通过相对路径(./或../或@(别名,其他别名在vue.config.js里面添加)/)被引用。这类引用会被 webpack 处理。
放置在 public 目录下或通过绝对路径(/或http:xxxxx)被引用。这类资源将会直接被拷贝,而不会经过 webpack 的处理。
demo在src/mpa-one/detail/index.html

2、dist/js/chunk-vendor.js和chunk-common.js过大的问题

该问题是公司的项目中发现的,代码就不贴出来了,vue.config.js里面的代码是一样的,src/pages/里面的内容不一样,打包结果会以截图的形式展示出来,项目里有单页面应用也有多页面应用,所以,下面的案例都会选这两种案例展示说明

单页面路由页面(总的js大小为256.3KB)

多页面(总的js大小为196.3KB)

可以看到这两个项目都引入了chunk-vendor.js(177KB)和chunk-common.js(8.6KB)

chunk-vendor.js(177KB)和chunk-common.js(8.6KB)是什么?chunk-vendor.js为什么这个大?

原因:

上面的项目背景已经给大家说明了,因为这个仓库的src/pages/下面的每一个文件夹都是一个活动项目,项目很多,vue.config.js里面除了将单页面入口改为多页面入口,添加了图片压缩,其他的打包机制都没有修改
现有的打包机制适用单页面应用,会将src/pages/下面所有的html页面使用到的满足条件的第三方的静态资源(node_modules)打包到dist/js/chunk-vendor.js里面,和将满足条件的除了打到chunk-vendor.js里面的其他静态模块(node_modules和其他的项目中的文件如utils文件资源)打到dist/js/chunk-common.js里面,最后将每个页面剩下的js逻辑打到dist/js/xxx(页面的名字).js每个页面引入的是chunk-vendor.js、chunk-common.js和xxx(页面的名字).js,如果是单页面路由页面,使用了路由懒加载,页面还会有一些模块js如(dist/js/chunk-xxx.js)。

仓库里面放置的不是一个项目,所以随着项目越来越大,chunk-vendor.js和chunk-common.js会越来越大,每个页面引入的多余的代码会越来越多,所以对于这个问题,做了多页面打包的处理。修改内容为,将每个页面都引入的第三方库作为提取到dist/js/chunk-vendor.js,删除chunk-common.js(去掉默认配置common),将每个页面剩余的js打包到dist/js/xxx(页面的名字).js。这样页面就不会引入多余的js文件了

针对这个问题,对vue.config.js的chainWebpack字段添加下面的代码

做如下修改

 // 公共资源提取,
 // vendors提取的是第三方公共库(满足提取规则的node_modules里面的且页面引入的),这些文件会打到dist/js/chunk-vendors.js里面
 // 提取规则是每个页面都引入的才会打到chunk-vendors.js里面(如vue.js)
 // 控制条件是minChunks字段,所以该字段的值是当前activity/src/projects里面的html的个数
 // common提取的应该是除了vendors提取后,剩余的满足条件的公共静态模块
 // 我们的项目不需要common,所以将common置为{},覆盖默认common配置
 config.optimization.splitChunks({
    cacheGroups: {
        vendors: {
            name: 'chunk-vendors',
            minChunks: pageNum,
            test: /node_modules/,
            priority: -10,
            chunks: 'initial'
        },
        common: {}
     }
});

再次执行打包命令

单页面路由页面(总的js大小为161.6KB)

多页面(总的js大小为167.9KB)

可以看到优化后的页面总资源大小比没有优化之前的小了

spa页面js(256.3KB => 161.6KB)
mpa页面js(196.3KB => 167.9KB)

经过优化,页面的js还是挺大的,查看项目,发现spa页面有引入vconsole工具,用于调试的,所以配置下在生产环境不引入该工具
spa和mpa都引入了一个modal的组件(弹框),该组件里面有引入jquery,用的jquery很少,所以可以将jquery去掉,用原生的代码实现

vconsole优化:由于每个页面测试环境都需要引入该包用于调试,在每个页面引入很麻烦,所以,可以在vue.config.js里面配置,代码如下
先在命令行里面安装npm install vconsole-webpack-plugin --save-dev
  

  const vConsolePlugin = require('vconsole-webpack-plugin');
  //开发环境
  let pluginsDev = [
    //移动端模拟开发者工具
    new vConsolePlugin({
      filter: [], // 需要过滤的入口文件
      enable: true 
    }),
  ];

  
  if(process.env.NODE_ENV !== 'production') {
    config.plugins = [...config.plugins, ...pluginsDev];
  }

再将页面的jquery去掉,改用原生js写法,再执行npm run build打包部署到服务器后

spa页面

mpa页面

可以看到优化后的页面总资源大小比没有优化之前的小了

经过上面的优化,页面的js总资源数字如下
spa页面js(161.6KB => 106.2KB)
mpa页面js(167.9KB => 137.9KB)

上面两次优化后

spa页面js(256.3KB => 106.2KB)减少了150KB
mpa页面js(196.3KB => 137.9KB)减少了60KB

另外访问我们公司的集成环境和beta环境(非生产环境)发现js文件都是很大的,不是gzip包

生产环境的js不大,因为服务器配置的问题,生产环境配置了使用gzip的文件,如图response header里面的content-encoding的值是gzip,非生产环境没有这个字段,如果服务器配置了,是会有的

上面所述如有问题,评论里帮我指出,呃呃....第一次写博客,写博客也挺累的啊

原文地址:https://www.cnblogs.com/HYZhou2018/p/10419703.html