使用vue-cli开发项目,免不了需要做些配置。特别是项目比较复杂时。这里列出一些有用的配置。当然,每个项目需求不同,或许对你来说,这并不实用。
这里所用的都是基于vue-cli3的配置哦。vue是2.x的。还在用vue-cli2的童鞋,该换新了,比较vue3都出来了,当然了,老项目可能没办法(我说的是没办法去升级成vue-cli3,可能因为时间成本,想要这些配置,也是可以的,只是写法和这里有区别罢了),至于vue3的,还没去研究额,再说vue3多了个vite。
基本路径 publickPath
如果你的项目部署在根目录下,这或许不用去管。但是,如果项目部署在子路径下,那就得改下咯
配置代码示例:
module.exports={
publicPath: '/system/',
}
其中,system是访问项目的子路径,这里是和服务器对应的。也就是前端浏览器通过输入http://test.com/system/类似的路径访问项目首页
生产环境自动删除console.log
应该 有很多程序员像我一样,喜欢用console.log调试吧。额,虽然有人推荐debug,或者其他工具。但是习惯了console.log,也还没到必须改的时候。但是,生产环境下,如果打印一大堆console.log,那体验是不好的。当然如果你习惯看完就删除或者注释,也很好。这里说的是针对比较懒的那种人,比如我,不想动手,那就只能动代码咯。
配置有多种方法,这里使用TerserPlugin插件
配置代码示例:
const TerserPlugin=require('terser-webpack-plugin')
const isProduction = process.env.NODE_ENV === 'production'
module.exports={
configureWebpack: config => {
if (isProduction) {
// 为生产环境修改配置...
config.plugins.push(
//生产环境自动删除console
new TerserPlugin({
terserOptions: {
ecma: undefined,
warnings: false,
parse: {},
compress: {
drop_console: true,
drop_debugger: false,
pure_funcs: ['console.log'] // 移除console
}
},
sourceMap: false,
parallel: true,
})
)
)
}
}
}
这里要注意的是terser-webpack-plugin版本,版本通常不能太高,插件没有做向下兼容,我这里vue版本是2.6,terser-webpack-plugin版是 "^3.1.0",反正如果你已经安装了以来,弄上去,报错莫名其妙说什么东西没有,那就是版本不兼容,通常需要降级。
开启gip压缩
开启gzp压缩是优化代码体积用的,如果项目不大,那也没必要。开启gip压缩需要后端配合才能生效,这里之说前端的配置。
使用 CompressionWebpackPlugin 插件
配置代码示例:
const CompressionWebpackPlugin = require('compression-webpack-plugin')
const isProduction = process.env.NODE_ENV === 'production'
module.exports={
configureWebpack: config => {
if (isProduction) {
// 开启gzp压缩
config.plugins.push(
new CompressionWebpackPlugin({
// 正在匹配需要压缩的文件后缀
test: /\.(js|css|svg|woff|ttf|json|html)$/,
// 大于10kb的会压缩
threshold: 10240
// 其余配置查看compression-webpack-plugin
})
)
}
}
}
这里要注意的是CompressionWebpackPlugin版本,版本通常不能太高,插件没有做向下兼容,我这里vue版本是2.6,CompressionWebpackPlugin版是 "^5.0.0"。反正如果你已经安装了以来,弄上去,报错莫名其妙说什么东西没有,那就是版本不兼容,通常需要降级。
生成zip文件
懒人的福音,打包后,是不是要弄成压缩包发给后端或者运营部署?可是就是不想动手!那就只能动代码呗。当然,这可能带来的后果就是,打包需要 更多的时间,因为需要处理文件,弄成zip。
需要使用两个插件,BundleAnalyzerPlugin和FileManagerPlugin,结合node-cmd插件,并定义一个自己打开文件夹的类OpenFolderPlugin。很暖心有木有,文件夹都给你打开了,还想怎样???
配置代码示例:
const cmd = require("node-cmd")
const FileManagerPlugin = require("filemanager-webpack-plugin");
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin
const OUTPUT_FILE_NAME='my-zip-file-test' //这里定义最终打包的zip文件名,和文件夹名称
class OpenFolderPlugin {
apply(compiler) {
compiler.hooks.done.tap("Open Folder Plugin", function() {
cmd.run("start .\\dist");
});
}
}//这是打开文件夹的类
module.exports={
// 输出文件目录
outputDir: `dist/${OUTPUT_FILE_NAME}`,
configureWebpack: config => {
if (["build", "build-dev"].includes(process.env.npm_lifecycle_event)) {
const outputFile = `./dist/${OUTPUT_FILE_NAME}.zip`;
config.plugins.push(
new BundleAnalyzerPlugin({
analyzerMode: "disabled",
generateStatsFile: true,
statsFilename: "../stats.json"//这里是生成代码分析文件,可以查看代码性能哟。当然主要针对包模块体积
}),
new FileManagerPlugin({
events:{
onStart:{
delete: ['./dist/'],
},
onEnd: {
archive: [
{
source: `./dist/${OUTPUT_FILE_NAME}`,
destination: outputFile
}
]
}
}
}),//这个webpack插件的功能挺多的,这里只用两个,开始打包事件和打包结束事件,我们打包后的文件依然放在dist文件夹里面,只是里面多了分析文件,zip文件,还有吧未压缩的生产环境用的文件单独放在一个文件夹里面
new OpenFolderPlugin()
);
}
}
}
同样,这里也要注意版本问题,因为这些插件到一定版本后,就会不兼容之前的版本。这里着实想吐槽一下,不过人家肯定也有难言之隐不是。我们就自己小心点了。
filemanager-webpack-plugin和webpack-bundle-analyzer,我这里都是用4.4.0版本哦。高了会报错的,不兼容。
build和build-dev是打包运行的命令,这里是监听命令的,因为我们只需要在打包时采用这个配置,通常来说,都是npm run build,如果你改了命令,这里也要做相应的更改。
微前端——乾坤 qiankun.js子项目配置
如果项目中使用了微前端,并且是使用qiankun开发的,那么这里就用上了。当然,只需要配置子项目,主项目不需要这个配置。
配置代码示例:
const {name} = require('./package')
module.exports={
devServer: {
port:6661,//因为主项目需要通过访问地址去访问子项目,所以端口最好不要配置成容易被占用的,否则一旦你启动多个项目,可能就得该代码里面的访问路径
// 允许被主应用跨域fetch请求到,这里是必须的,不然跨越无法访问
headers: {
'Access-Control-Allow-Origin':'*'
},
},
//需要配置打包模式,不然qiankun无法获取。不要问为什么,qiankun要求的,可以问问qiankun为啥要这么做。当然这里要说的是,qiankun会通过package里面的包名去读取文件,所以name必须是package的包名,不然获取文件会失败
configureWebpack: config=>{
// console.log(config)
config.output.library=name
config.output.libraryTarget= 'umd'
config.output.jsonpFunction=`webpackJsonp_${name}`
}
}
反向代理配置
什么时候需要配置反向代理?
开发换跨越,那是肯定出现的,因为是前后端分离项目,但是生产环境下,又不跨越,因为访问域名和api请求域名是一致的了(当然如果不一致,也会跨越,但是这不是前端能解决的了)。这种情况下,我们不需要后端小伙伴或者运维去解决,前端配置反向代理就好了,而且用起来也省心,因为不需要在请求接口的时候加上域名。
通常来说,一个项目的请求域名,只有一个,如果项目使用hash模式,那么就简单很多,直接在proxy那里写上api域名即可。
如果使用了history模式,就不能这样了,这会和服务器冲突的,必须要匹配路径去配置。这里示例一下history模式的配置。
//因为可能会有很多个路径匹配,这里不想写一大串if语句,所以,搞了个函数,使用循环。
//其中,/code,/admin,/auth是api请求除去域名的部分的开头,例如请求api路径是 http://test.com/admin/user/add-user-info
let proxys=function (){
let apiPathArr=['/code','/auth','/admin']
let proxys={}
for(let i=0;i<apiPathArr.length;i++){
proxys[apiPathArr[i]]={
target: 'http://10.2.100.20',
ws: false,
changeOrigin: true,
pathRewrite:{
[`^${apiPathArr[i]}`]:apiPathArr[i]
}
}
}
return proxys
}()
module.exports={
devServer: {
proxy:proxys,// 配置多个代理
},
}
暂时就这些了,下面给个完整的代码
const cmd = require("node-cmd")
const {name} = require('./package')
const CompressionWebpackPlugin = require('compression-webpack-plugin')
const TerserPlugin=require('terser-webpack-plugin')
const isProduction = process.env.NODE_ENV === 'production'
const FileManagerPlugin = require("filemanager-webpack-plugin");
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin
const OUTPUT_FILE_NAME='loudi-wisdom-construction-site'
class OpenFolderPlugin {
apply(compiler) {
compiler.hooks.done.tap("Open Folder Plugin", function() {
cmd.run("start .\\dist");
});
}
}
let proxys=function (){
let apiPathArr=['/code','/auth','/admin']
let proxys={}
for(let i=0;i<apiPathArr.length;i++){
proxys[apiPathArr[i]]={
target: 'http://10.2.100.20',
ws: false,
changeOrigin: true,
pathRewrite:{
[`^${apiPathArr[i]}`]:apiPathArr[i]
}
}
}
return proxys
}()
module.exports = {
// 基本路径
publicPath: '/system/',
// 输出文件目录
outputDir: `dist/${OUTPUT_FILE_NAME}`,
configureWebpack: config => {
config.output.library=name
config.output.libraryTarget= 'umd'
config.output.jsonpFunction=`webpackJsonp_${name}`
if (isProduction) {
// 为生产环境修改配置...
config.plugins.push(
//生产环境自动删除console
new TerserPlugin({
terserOptions: {
ecma: undefined,
warnings: false,
parse: {},
compress: {
drop_console: true,
drop_debugger: false,
pure_funcs: ['console.log'] // 移除console
}
},
parallel: true,
})
)
// 开启gzp压缩
config.plugins.push(
new CompressionWebpackPlugin()
)
}
if (["build", "build-dev"].includes(process.env.npm_lifecycle_event)) {
const outputFile = `./dist/${OUTPUT_FILE_NAME}.zip`;
config.plugins.push(
new BundleAnalyzerPlugin({
analyzerMode: "disabled",
generateStatsFile: true,
statsFilename: "../stats.json"
}),
new FileManagerPlugin({
events:{
onStart:{
delete: ['./dist/'],
},
onEnd: {
archive: [
{
source: `./dist/${OUTPUT_FILE_NAME}`,
destination: outputFile
}
]
}
}
}),
new OpenFolderPlugin()
);
}
},
devServer: {
open: false, //配置自动启动浏览器,想自动打开就设为true
port:6661,
// 允许被主应用跨域fetch请求到
headers: {
'Access-Control-Allow-Origin':'*'
},
proxy:proxys,// 配置多个代理
},
}