vue单页项目优化
vue-cli 打包时抽离项目相关配置文件
当使用vue-cli进行开发时时常需要动态配置一些设置,比如接口的请求地址(axios.defaults.baseURL)
这些设置可能需要在项目编译后再进行设置的,(方便运维部署人员自己配置接口IP)
所以在vue-cli里我们需要对这些配置文件进行抽离,不让webpack把配置文件也进行编译。
// public/js/index.js
window.global = {
api: "https://www.baidu.com",
url: "http://10.10.10.210",
axios_outtime:1500
};
在 public/index.html 文件中引入
在项目中使用时,直接使用window.global去调用这个配置文件的内容。
<script src="/js/config.js"></script>
vue-cli 开启 Gzip 压缩
- 安装压缩插件 cnpm i compression-webpack-plugin@6.1.1 --save-dev
注意,这里不能直接下载,需要下载低版本的。直接下载就是最新版的了,vue脚手架暂时不支持最新版的,所以就会报错
- vue.config.js使用
// 引入gzip压缩插件
const CompressionPlugin = require('compression-webpack-plugin');
// 暴露配置项,会被合并到webpack中去
module.exports = {
chainWebpack(config) {
// ......
},
configureWebpack: config => {
// 开发环境不配置 生产环境才去配置
if (process.env.NODE_ENV !== 'production') return
return {
plugins: [
//此插件不能使用太高的版本,否则报错:TypeError: Cannot read property 'tapPromise' of undefined
new CompressionPlugin({
// filename: "[path][base].gz", // 这种方式是默认的,多个文件压缩就有多个.gz文件,建议使用下方的写法
filename: '[path].gz[query]', // 使得多个.gz文件合并成一个文件,这种方式压缩后的文件少,建议使用
algorithm: 'gzip', // 官方默认压缩算法也是gzip
// 使用正则给匹配到的文件做压缩,这里是给html、css、js以及字体(.ttf和.woff和.eot)做压缩
test: /\.js$|\.css$|\.html$|\.ttf$|\.eot$|\.woff$/,
threshold: 10240, //以字节为单位压缩超过此大小的文件,使用默认值10240吧
minRatio: 0.8, // 最小压缩比率,官方默认0.8
// 是否删除原有静态资源文件,即只保留压缩后的.gz文件,建议这个置为false,还保留源文件。以防:
// 假如出现访问.gz文件访问不到的时候,还可以访问源文件双重保障
deleteOriginalAssets: false
})
]
}
},
};
- 这里配置完以后,暂时还不能使用,还需要后端做一下配置,这里后端以nginx为例
server {
listen 80;
server_name localhost;
location / {
try_files $uri $uri/ /index.html;
root C:/nginx-1.18.0/html/gzip/dist;
index index.html index.htm;
}
location /api/ {
proxy_pass http://localhost:6666/;
}
# 主要是下方的gizp配置
gzip on; # 开启gzip压缩
gzip_min_length 4k; # 小于4k的文件不会被压缩,大于4k的文件才会去压缩
gzip_buffers 16 8k; # 处理请求压缩的缓冲区数量和大小,比如8k为单位申请16倍内存空间;使用默认即可,不用修改
gzip_http_version 1.1; # 早期版本http不支持,指定默认兼容,不用修改
gzip_comp_level 2; # gzip 压缩级别,1-9,理论上数字越大压缩的越好,也越占用CPU时间。实际上超过2的再压缩,只能压缩一点点了,但是cpu确是有点浪费。因为2就够用了
# 压缩的文件类型 MIME类型, # css # xml # 识别php # 图片
gzip_types text/plain application/x-javascript application/javascript text/javascript text/css application/xml application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/x-woff font/ttf;
# text # 早期js # js # js的另一种写法 # .eot字体 # woff字体 # ttf字体
gzip_vary on; # 是否在http header中添加Vary: Accept-Encoding,一般情况下建议开启
}
图片压缩配置
- 安装 cnpm i image-webpack-loader@7.0.1 --save-dev
使用 cnpm 安装,如果使用npm 可能有些安装会报错;
chainWebpack: (config) => {
// 图片压缩;
config.module
.rule("images")
.test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
.use("image-webpack-loader")
.loader("image-webpack-loader")
.options({ bypassOnDebug: false });
},
cdn 配置
在生产环境中 将常见的依赖通过 cdn 引入;
// 生产环境不打包这些包
const externals = {
vue: "Vue",
"vue-router": "VueRouter",
vuex: "Vuex",
axios: "axios",
};
// CDN 外链,会插入到 index.html 中
const cdn = {
// 开发环境
dev: {
css: [],
js: [],
},
// 生产环境
build: {
css: ["https://cdn.jsdelivr.net/npm/ant-design-vue@1.7.8/dist/antd.min.css",],
js: [
"https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.min.js",
"https://cdn.jsdelivr.net/npm/vue-router@3.2.0/dist/vue-router.min.js",
"https://cdn.jsdelivr.net/npm/axios@0.21.1/dist/axios.min.js",
"https://cdn.jsdelivr.net/npm/vuex@3.4.0/dist/vuex.min.js",
"https://cdn.jsdelivr.net/npm/moment@2.29.1/moment.min.js", // 必须先引入moment,否则报错“TypeError: Cannot read property 'default' of undefined”
"https://cdn.jsdelivr.net/npm/moment@2.29.1/locale/zh-cn.js", // 需同步引入语言包,否则日期选择控件等将默认显示为英文
"https://cdn.jsdelivr.net/npm/ant-design-vue@1.7.6/dist/antd.min.js",
],
},
};
module.exports = {
chainWebpack: (config) => {
// 添加 CDN 参数到 htmlWebpackPlugin 配置中
config.plugin("html").tap((args) => {
if (process.env["NODE_ENV"] == "production") {
args[0].cdn = cdn.build;
args[0].title = "评价系统"; //设置 index.html 页面的title;
} else {
args[0].cdn = cdn.dev;
args[0].title = "评价系统"; //设置 index.html 页面的title;
}
return args;
});
},
configureWebpack:(config)=>{
// 只在生产环境使用 cdn
if (process.env["NODE_ENV"] == "production") {
// 忽略 vue 和 vuex,vueRouter 等模块
config.externals = externals;
}
}
// public/index.html 文件中 index.html 引入
<% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %>
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="preload" as="style" />
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet" />
<% } %>
<!-- 使用 CDN 加速的 JS 文件,配置在 vue.config.js 下 -->
<% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>
<script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
<% } %>
}
删除 Prefetch 优化配置
/*
* <link rel="prefetch"> 是一种 resource hint,用来告诉浏览器在页面加载完成后,利用空闲时间提前获取用户未来可能会访问的内容。
* 删除 Prefetch 或者 修改 Prefetch
*
*/
chainWebpack: (config) => {
// 移除 prefetch 插件
config.plugins.delete("prefetch");
}
devServer开发代理服务器配置
module.exports = {
productionSourceMap: false,
// https://cli.vuejs.org/zh/config/?#publicpath
publicPath: "/",
// 当运行 vue-cli-service build 时生成的生产环境构建文件的目录。注意目标目录的内容在构建之前会被清除 (构建时传入 --no-clean 可关闭该行为)。
outputDir: process.env.VUE_APP_outputDir,
// 是否使用包含运行时编译器的 Vue 构建版本。设置为 true 后你就可以在 Vue 组件中使用 template 选项了,但是这会让你的应用额外增加 10kb 左右。
runtimeCompiler: true,
devServer: {
open: true, // 是否打开浏览器;
hotOnly: true, // 是否热更新;
proxy: {
"/api": {
// 路径中有 /api 的请求都会走这个代理 , 可以自己定义一个,下面移除即可
target: "http://10.10.10.211",
secure: false,
changeOrigin: true, // 开启代理,在本地创建一个虚拟服务端
ws: true, // 是否启用 websockets;
pathRewrite: {
// 去掉 路径中的 /api 的这一截
"^/api": "",
},
},
},
},
}
// .env 文件
VUE_APP_API = "/api"
// axios.js
let HTTP = axios.create({
baseURL:process.env.VUE_APP_API,
timeout: 15000,
headers: {
"Content-Type": "application/json;charset=UTF-8",
},
});
vue.config.js 全部的完整配置代码
const externals = {
vue: "Vue",
"vue-router": "VueRouter",
vuex: "Vuex",
axios: "axios",
};
// CDN 外链,会插入到 index.html 中
const cdn = {
// 开发环境
dev: {
css: [],
js: [],
},
// 生产环境
build: {
css: ["https://cdn.jsdelivr.net/npm/ant-design-vue@1.7.6/dist/antd.min.css"],
js: [
"https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.min.js",
"https://cdn.jsdelivr.net/npm/vue-router@3.2.0/dist/vue-router.min.js",
"https://cdn.jsdelivr.net/npm/axios@0.21.1/dist/axios.min.js",
"https://cdn.jsdelivr.net/npm/vuex@3.4.0/dist/vuex.min.js",
"https://cdn.jsdelivr.net/npm/moment@2.29.1/moment.min.js", // 必须先引入moment,否则报错“TypeError: Cannot read property 'default' of undefined”
"https://cdn.jsdelivr.net/npm/moment@2.29.1/locale/zh-cn.js", // 需同步引入语言包,否则日期选择控件等将默认显示为英文
"https://cdn.jsdelivr.net/npm/ant-design-vue@1.7.6/dist/antd.min.js",
],
},
};
const CompressionPlugin = require("compression-webpack-plugin");
module.exports = {
productionSourceMap: false,
publicPath: "/", //
outputDir: process.env.VUE_APP_outputDir,
runtimeCompiler: true, //是否使用包含运行时编译器的 Vue 构建版本。设置为 true 后你就可以在 Vue 组件中使用 template 选项了,但是这会让你的应用额外增加 10kb 左右。
devServer: {
open: true, // 是否打开浏览器;
hotOnly: true, // 是否热更新;
proxy: {
"/api": {
// 路径中有 /api 的请求都会走这个代理 , 可以自己定义一个,下面移除即可
target: urlList[1],
secure: false,
changeOrigin: true, // 开启代理,在本地创建一个虚拟服务端
ws: true, // 是否启用 websockets;
pathRewrite: {
// 去掉 路径中的 /api 的这一截
"^/api": "",
},
},
},
},
chainWebpack: (config) => {
// 图片压缩;
config.module
.rule("images")
.test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
.use("image-webpack-loader")
.loader("image-webpack-loader")
.options({ bypassOnDebug: false });
/*
* <link rel="prefetch"> 是一种 resource hint,用来告诉浏览器在页面加载完成后,利用空闲时间提前获取用户未来可能会访问的内容。
* 删除 Prefetch 或者 修改 Prefetch
* */
// 移除 prefetch 插件
config.plugins.delete("prefetch");
// 添加 CDN 参数到 htmlWebpackPlugin 配置中
config.plugin("html").tap((args) => {
if (process.env["NODE_ENV"] == "production") {
args[0].cdn = cdn.build;
args[0].title = "评价系统";
} else {
args[0].cdn = cdn.dev;
args[0].title = "评价系统";
}
return args;
});
},
configureWebpack: (config) => {
// gzip压缩配置
config.plugins.push(
new CompressionPlugin({
algorithm: "gzip", // 使用gzip压缩
test: /\.js$|\.html$|\.css$/, // 匹配文件名
filename: "[path][base].gz", // 压缩后的文件名(保持原文件名,后缀加.gz)
minRatio: 1, // 压缩率小于1才会压缩
threshold: 10240, // 对超过10k的数据压缩
deleteOriginalAssets: false, // 是否删除未压缩的源文件,谨慎设置,如果希望提供非gzip的资源,可不设置或者设置为false(比如删除打包后的gz后还可以加载到原始资源文件)
})
);
// 只在生产环境使用 cdn
if (process.env["NODE_ENV"] == "production") {
// 不打包 vue 和 vuex,vueRouter 等模块
config.externals = externals;
}
},
};
去除 console.log()
1. 安装 npm i babel-plugin-transform-remove-console --save-dev
2. babel.config.js 中配置下面代码
const plugins = ["@vue/babel-plugin-transform-vue-jsx"];
// 去除 环境中 移除console
if (process.env.NODE_ENV === "production") {
plugins.push("transform-remove-console");
}
module.exports = {
plugins: plugins,
presets: ["@vue/cli-plugin-babel/preset"],
};