项目背景
- 公司的活动项目太多,每一个项目都要单独配置部署环境太麻烦,所以创建了一个仓库,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,非生产环境没有这个字段,如果服务器配置了,是会有的
上面所述如有问题,评论里帮我指出,呃呃....第一次写博客,写博客也挺累的啊