vue发布部署优化及问题
概述
近期公司OA系统即将到期,公司决定根据自己的业务做一套OA系统。在起初的架构选型中采用的是纯HTML 由于人员变动前台小哥哥单飞了;项目就由我接手了 恰巧前段时间刚学习了Vue对它也是情有独钟就提出采用Vue全家桶来构建一个单页面应用,在开发过程中也是磕磕碰碰遇到了不少的问题在此进行总结记录;
哪里说的不对或您有更好的建议欢迎留言指正;
初次部署问题浮现
开发工程中一直使用的是本机或者内网环境并没有感觉有什么问题;当部署到正常环境通过域名解析进来的时候浏览器会出现一段白屏,发现是打包后的文件达到了4M多当通过外网访问时会占用带宽产生流量从而导致久久不能加载,下面来优化一下
使用版本
记录版本避免以后升级造成误导
Vue项目的构建可以参考 vue-cli2 或者 vue-cli3 本文采用cli2
webpack打包优化
打包后的js文件达到4M多大小占用过多的流量,项目中所有使用到了的框架中js/css全部打包进来了不大才怪,知道问题了就晓得该针对什么去优化了,那就是尽可能的压缩打包后的js文件大小
我的写在了 webpack.pro.config.js 如果没有可以新建一个专门用于生产打包
1. 排除第三方框架(使用cdn引入)
externals 排除外部框架;这种方式不用改动任何已有的代码
externals: {
'vue': 'Vue',
'vue-router': 'VueRouter',
'vuex': 'Vuex',
'element-ui': 'ELEMENT',
'axios': 'axios',
'lodash': '_',
'mockjs': 'mockjs',
'moment': 'moment',
'store': 'store',
'crypto-js': 'CryptoJS',
'vue-quill-editor': 'VueQuillEditor',
'html2canvas': 'html2canvas'
}
使用cdn方式映入(这里是使用到了 html-webpack-plugin 插件)
<% for (var i in htmlWebpackPlugin.options.cdn.css) { %>
<link href="<%= htmlWebpackPlugin.options.path %><%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet">
<% } %>
<% for (var i in htmlWebpackPlugin.options.cdn.js) { %>
<script src="<%= htmlWebpackPlugin.options.path %><%= htmlWebpackPlugin.options.cdn.js[i] %>" charset="utf-8"></script>
<% } %>
1. css提取
将打包到js中的css全部抽取出来,让它在瘦一点 需要使用 extract-text-webpack-plugin 插件
- 安装 (这里使用到的版本是当前最新的3.0.2)
$ npm i -D extract-text-webpack-plugin
- 示例
- 修改webpack配置文件
项目中配置支持css、less、scss那么我这里分别提取到不同的文件中
const ExtractTextPlugin = require("extract-text-webpack-plugin")
const extractCSS = new ExtractTextPlugin("css/[name].[contenthash].css")
const extractLSS = new ExtractTextPlugin("css/[name].[contenthash].css")
const extractSCSS = new ExtractTextPlugin("css/[name].[contenthash].css")
module.exports = {
module:{
{
test: /\.css$/,
use: extractCSS.extract({
fallback: "style-loader",
use: ["css-loader", "postcss-loader"],
publicPath: './../'
})
},
{
test: /\.less$/,
loader: extractLSS.extract({
fallback: "style-loader",
use: ["css-loader", "postcss-loader", "less-loader"],
publicPath: './../'
})
},
{
test: /\.scss$/,
loader: extractSCSS.extract({
fallback: "style-loader",
use: ["css-loader", "postcss-loader", "sass-loader"],
publicPath: './../'
})
}
}
plugins:[extractCSS,extractLSS,extractSCSS]
}
你可能发现我这里有使用一个postcss-loader的加载器,这个是用来优化css的,自动添加内核前缀,如果你觉得没有用剔除就好否则需要安装
2.执行build
抽取后的css有1M多我的天啊!点开发现把框架中的css也抽取出来了,我不是排除了么?
检查发现只要是通过import导入了css那么这些都会被检查到并提取出来
解决办法:将项目中所有import导入的css全部注释
3. 使用webpack-bundle-analyzer查看文件大小
webpack-bundle-analyzer 可以可视化清楚的看到打包后的文件依赖情况
- 安装(这里使用到的版本是当前最新的 3.0.3)
$ npm i -D webpack-bundle-analyzer
- 示例
1.添加到webpack配置中
const {BundleAnalyzerPlugin} = require('webpack-bundle-analyzer');
module: {
plugins:[
new BundleAnalyzerPlugin()
]
}
2.package.json中添加脚本
"analyz": "cross-env NODE_ENV=production npm_config_report=true npm run build"
3.执行
$ npm run analyz
analyzer默认会启动8888端口
4.压缩js,css
压缩js/css应该是发布上线的基本操作,也是优化手段之一,压缩后文件可以减小到50%
-
压缩前:
-
压缩后:
项目打包压缩可以使用webpack自带的 UglifyJsPlugin插件
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
comments: false,
compress: {
warnings: false
}
})
第三框架尽可能的使用压缩后的如果没有的可以自己手动压缩一下,我这里手动压缩工具使用的是在线压缩,没有找到好的压缩工具,麻烦留言推荐
到这里我的项目文件最大的只有300多KB了,加载还是要2-4秒 3G环境下4-6秒还是会出现短暂的白屏 然后就想要不加个初始化loading吧
5.添加加载loading
这个可以根据个人业务情况来决定是否需要初始化loading,这也不是唯一的解决办法
nginx静态代理
每次刷新页面加载速度还要3秒左右,开始怀疑是不是服务器配置或者带宽的问题看了服务器的配置不低,然后在人家的网页上逛发现自己的页面没有使用到浏览器缓存,每次都是去服务器取最新的;
不应该啊!也没有什么地方禁用缓存,找啊找啊找啊找… 发现是项目中使用到了spring security导致浏览器缓存失效,暂时没有找到原因是哪里操作不对;一开始的部署是我同事负责的我门的开发环境的页面是直接放在网关的而他直接使用这种形式发布了。我们的项目本来就是前后台分离的可以分开部署那么发布还是不建议直接放入程序中关联推荐使用nginx或者apached等; 我这里使用的是nginx
nginx.cnf
server {
listen 4020;
server_name www.xxx.com;
root html;
index index.html;
location / {
alias html/oa-user-ui/dist/;
index index.html;
expires 7d;
autoindex on;
}
location /admin {
alias html/manamger/dist/;
index index.html;
expires 7d;
autoindex on;
}
location /api {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Authorization $http_authorization;
proxy_pass http://localhost:4030;
}
error_page 404 /404.html;
location = /404.html {
root html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
注意问题 root 和 alias 区别
当我使用root配置后访问出现404错误Not found. 上网查了一下原因,是配置不对。因为我是有两个web项目目录一个用户目录,一个管理员目录,这两个目录在不同的位置上。所有就想配置两个location来标记不同的入口
- root
location /test{
root /html;
}
当客户端请求 /test/index.html 的时候, nginx把请求映射为/html/test/index.html 会将匹配的URI拼接在后面
- alias
location /test{
root /html/;
}
当客户端请求 /test/index.html 的时候, nginx把请求映射为/html/index.html
alias会把location后面配置的路径丢弃掉,把当前匹配到的目录指向到指定的目录。如果一个请求的URI是/test/index.html时,将会指向服务器上的/html/index.html。
- 使用alias时,目录名后面一定要加"/"。
- alias可以指定任何名称。
- alias在使用正则匹配时,必须捕捉要匹配的内容并在指定的内容处使用。
- alias只能位于location块中。
6. 开启gzip
代码压缩后js/css大小能减少50%,开启gzip后还能在压缩的基础上在减去50%;开启gzip是优化网页的必经之路啊!
- 开启gzip响应:
在3G情况下加载速度平均1秒左右,基本是秒开;在图中可以看到响应头中Content-Encoding=gzip代表我们使用了gzip进行传输
- nginx配置:
gzip on;
gzip_static on;
gzip_min_length 100k;
gzip_buffers 4 16k;
gzip_comp_level 6;
gzip_http_version 1.0;
gzip_types
application/atom+xml
application/javascript
application/json
application/ld+json
application/manifest+json
application/rss+xml
application/vnd.geo+json
application/vnd.ms-fontobject
application/x-font-ttf
application/x-web-app-manifest+json
application/xhtml+xml
application/xml
font/opentype
image/bmp
image/svg+xml
image/x-icon
text/cache-manifest
text/css
text/plain
text/vcard
text/vnd.rim.location.xloc
text/vtt
text/x-component
application/octet-stream
text/x-cross-domain-policy;
gzip_vary off;
gzip_disable "MSIE [1-6]\.";
开启 nginx 的 gzip_static on; 选项,如果 gzip_static 设置为 on, 那么就会使用相同名称的.gz 文件,不会占用服务器的 CPU 资源去压缩。
- 前端压缩gzip包
1.安装 compression-webpack-plugin
npm install --save-dev [email protected]
2.如果是通过vue脚手架生成的项目config/index.js那有一个productionGzip选项设置为true开启gzip压缩
摘要vue生成 webpack.prod.conf.js 文件代码如下:
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin')
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
)
}
这个时候我们在打包编译会发现dist目录多了很多.gzip的文件,要比源文件大约小50%
如果无法搭建nginx环境,那么可以通过node express 快速启动一个服务
1.安装
npm i express compression
2.新建一个server.js
var express = require('express')
var app = express()
// 开启 gzip 压缩
var compression = require('compression')
app.use(compression())
app.use(express.static('dist'))
app.listen(8000,function () {
console.log('server is runing on http://localhost:8000')
})
3.执行server.js
$ node server.js
开启gzip遇到的问题
- 前台问题
通过 npm install compression-webpack-plugin 安装compression插件使用的过程中出现如下错误:
ValidationError: Comperssion Plugin Invalid Options
百度帖子都说将asset替换为filename就好了,替换后出现了新的错误如下图
然后整个人都凌乱了,吃完饭回来一想是不是我的版本不对,因为我使用的是 npm install 直接安装的默认会安装最新的版本,然后将当前版本2.x 降 到 1.x
$ npm uni compression-webpack-plugin
$ npm i compression-webpack-plugin1.1.11
- nginx问题
1.使用gzip_static 异常
原因是在安装nginx的时候没有选择对应的编译模块,解决办法:
gzip依赖–with-http_gzip_static_module模块
1.查看nginx编译模块是否编译 --with-http_gzip_static_module
2.将–with-http_gzip_static_module编译进去
2.nginx开启gzip不生效
一切配置就绪后gzip无效,参考文章 Nginx gzip参数详解及常见问题 貌似说通讯协议没有统一,配置 gzip_http_version 1.0; 解决问题
./configure --with-http_gzip_static_module
其他参数可以参考 官网 或 centos7安装nginx
element打包异常
element-ui打包异常
之前一直好好的不知道是怎么了element打包就异常了,然后看了一下报错的文件是element中使用了es6的语法
修改前配置:
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
options: {
plugins: ['syntax-dynamic-import']
}
}
修改后配置:
/* exclude: /node_modules/,*/
include: [
resolve('src'),
resolve('test'),
//解决element-ui打包异常问题
resolve('node_modules/element-ui/src'),
resolve('node_modules/element-ui/packages')
]