vue-cli3 脚手架搭建完成后,项目目录中没有 vue.config.js 文件,需要手动创建
vue.config.js 是一个可选的配置文件,如果项目的 (和 package.json 同级的) 根目录中存在这个文件,那么它会被 @vue/cli-service 自动加载。你也可以使用 package.json 中的 vue 字段,但是注意这种写法需要你严格遵照 JSON 的格式来写。
const path = require('path');
const webpack = require('webpack');
let pkg = require('./package.json');
let env = ''
if (process.env.VUE_APP_MODE === 'development') {
env = 'dev' // 开发环境
} else if (process.env.VUE_APP_MODE === 'test') {
env = 'test' // 测试环境
} else {
env = 'prod' // 生产环境
}
const isProd = env === 'prod';
function resolve(dir) {
return path.join(__dirname, dir);
}
const vueConfig = {
entry: {
app: './src/main.js',
},
};
vueConfig.base = {
//路由前缀
publicPath: '/' + pkg.name + '/views/',
//打包输出路径
outputDir: 'dist/' + pkg.name + '/views',
//主页输出路径,相对于outputDir
indexPath: 'index.html',
//使用vue的运行编译版本 // 使用带有浏览器内编译器的完整构建版本 这会让你的应用额外增加 10kb 左右
runtimeCompiler: false,
//文件名加哈希值
filenameHashing: true,
//开启eslint代码规范检测
lintOnSave: true,
//打包生成生产环境sourceMap文件 设置为 false 以加速生产环境构建
productionSourceMap: env === 'prod' ? false : true,
//需要bable编译的npm模块 // babel-loader 默认会跳过 node_modules 依赖。 // 通过这个选项可以显式转译一个依赖。
transpileDependencies: [],
// 放置静态资源的地方 (js、css、img、fonts) 从生成的资源覆写 filename 或 chunkFilename 时,assetsDir 会被忽略。
// assetsDir: '',
};
//设置别名
vueConfig.alias = {
config: 'src/config/index.js',
store: 'src/store/index.js',
router: 'src/router/index.js',
};
//webpack环境变量
const webpackEnv = {
MODULE_NAME: JSON.stringify(pkg.name),
APP_VERSION: JSON.stringify(pkg.version),
SERVER_URL: JSON.stringify(''),
};
// 开发环境
vueConfig.dev = {
css: {
//提取组件css为单独文件
//MiniCssExtractPlugin暂不支持热更新, 开发模式不提取
extract: false,
// 是否开启 CSS source map?
sourceMap: true,
},
};
//生产环境
vueConfig.prod = {
css: {
//提取组件css为单独文件
extract: {
filename: 'css/[name].[contenthash:10].css',
chunkFilename: 'css/[name].[contenthash:10].css',
},
sourceMap: false,
},
isGzip: true,
//生产打包删除console.log
delConsoleLog: true,
};
const buildFile = (config) => {
// 打包后自动生成 压缩部署文件
const FileManagerPlugin = require('filemanager-webpack-plugin');
const nowTime = require('moment')().format('YYYYMMDDHHmm');
const outPutPath = resolve('dist') + '/' + pkg.name;
const zipOutPutPath = `${outPutPath}_${env}_${nowTime}`;
// 将文件夹打包成压缩文件
config.plugins.push(
new FileManagerPlugin({
onEnd: [{
move: [
//将当前打包环境的配置覆盖configuration.js
{
source: `${outPutPath}/views/configuration_${env}.js`,
destination: `${outPutPath}/views/configuration.js`,
},
],
},
{
// 删除其他环境的配置文件
delete: [`${outPutPath}/views/configuration_*.js`],
},
{
copy: [{
source: `${outPutPath}`,
destination: `${zipOutPutPath}/${pkg.name}`,
}, ],
archive: [{
source: zipOutPutPath,
destination: `${zipOutPutPath}.zip`,
}, ],
delete: [zipOutPutPath],
},
],
}),
);
};
const configEnv = isProd ? vueConfig.prod : vueConfig.dev;
module.exports = Object.assign({
devServer: {
//浏览器控制台输出
clientLogLevel: 'warning',
//开启gzip压缩
compress: false,
hot: true,
// host: '0.0.0.0',
// 配置是否是https
// https: false,
port: 8086,
useLocalIp: true,
//自动打开浏览器
open: true,
// 启动热更新
hotOnly: true,
overlay: {
warnings: false,
errors: true,
},
watchOptions: {
poll: false,
},
//跨域请求代理
proxy: {
'/json': {
target: 'http://192.168.90.177:8080/',
changeOrigin: true,
},
'/zzt/fcgi/common.fcgi': {
target: 'https://webtest.ciccwm.com/',
changeOrigin: true,
},
},
},
css: Object.assign({
// 向 CSS 相关的 loader 传递选项 支持的 loader 有:css-loader postcss-loader sass-loader less-loader stylus-loader
loaderOptions: {
less: {
lessOptions: {
modifyVars: {
hack: `true; @import "${resolve('src/assets/css/vantself.less')}";`,
},
javascriptEnabled: true,
},
},
},
},
configEnv.css,
),
configureWebpack: (config) => {
//入口文件
config.entry = vueConfig.entry;
config.plugins.push(new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/));
//webpack环境变量
config.plugins.push(new webpack.DefinePlugin(webpackEnv));
//把webpack runtime 插入index.html中,减少请求
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');
config.plugins.push(
new ScriptExtHtmlWebpackPlugin({
inline: /(runtime|styles)\..*\.js$/,
}),
);
// 开启代码压缩
//js压缩-minimizer选项
//webpack4后已改为使用terser-webpack-plugin插件
//vuecli3默认的压缩配置在依赖中:@vue/cli-service/lib/config/terserOptions
Object.assign(config.optimization.minimizer[0].options.terserOptions.compress, {
warnings: false,
drop_debugger: true,
drop_console: configEnv.delConsoleLog,
// pure_funcs: ['console.log']
// exclude: /\/plugins/,
});
// 分割代码 相同代码放一块
Object.assign(config.optimization, {
//把webpack runtime单独提取出来
runtimeChunk: 'single',
splitChunks: {
automaticNameDelimiter: '-', // 自定义连接符 例如index-detail.js
// .async对动态加载的模块进行拆分
// .initial只拆分入口文件的模块 (会禁止非入口文件的模块拆分)
// .all对所有类型的模块进行拆分。 (一般我们都会配置这个选项)
chunks: 'all',
//拆分文件大小下限(未压缩前的js文件大小)
// 拆分文件大小下限(未压缩前的js文件大小)
minSize: 60000, // 提取出来的chunk需要满足的最小size,单位是bytes
maxSize: 600000, // maxSize比maxInitialRequest/maxAsyncRequests有更高的优先级。优先级顺序为maxInitialRequest/maxAsyncRequests < maxSize < minSize。
cacheGroups: {
default: false,
vendor: {
test: /[\\/]node_modules[\\/].+(?<!css)$/,
name: 'vendor',
priority: 40,
chunks: 'initial',
reuseExistingChunk: true,
},
common: {
name: 'common',
minChunks: 2,
priority: -10,
chunks: 'initial',
reuseExistingChunk: true,
},
styles: {
test: (module) =>
module.nameForCondition &&
/\.(s?css|vue|less)$/.test(module.nameForCondition()) &&
!/^javascript/.test(module.type),
name: 'styles',
chunks: 'all',
priority: 1,
enforce: true,
reuseExistingChunk: true,
},
},
},
});
//gzip压缩
if (configEnv.isGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin');
config.plugins.push(
new CompressionWebpackPlugin({
filename: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp('\\.(' + ['js', 'css', 'html'].join('|') + ')$'),
threshold: 2048,
minRatio: 0.8,
cache: true,
deleteOriginalAssets: false,
}),
);
}
if (process.env.NODE_ENV === 'production') buildFile(config);
// npm run build --report 构建加上参数 --report生成包文件分析页面
if (process.env.npm_config_report) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
config.plugins.push(new BundleAnalyzerPlugin());
}
},
chainWebpack: (config) => {
//移除 prefetch 插件
//如果有需要 prefetch, 可以在路由引入时,用内联注释方式注明
//import(/* webpackPrefetch: true */ './someAsyncComponent.vue')
config.plugins.delete('prefetch');
config.plugin('html').tap((options) => {
options.excludeChunks = ['runtime', 'styles'];
return options;
});
//webpack runtime插入index.html后,删除预加载runtime文件
config.plugin('preload').tap((options) => {
Object.assign(options[0], {
fileBlacklist: [/\.map$/, /hot-update\.js$/, /runtime\S*\.js$/, /styles\S*\.js$/],
});
return options;
});
//设置别名
for (let key in vueConfig.alias) {
config.resolve.alias.set(key, resolve(vueConfig.alias[key]));
}
},
},
vueConfig.base,
);