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,
);