-
Notifications
You must be signed in to change notification settings - Fork 6
Open
Labels
Description
vue.config.js
const path = require('path');
const utils = require('./utils');
const swigLoader = require('swig-loader');
const SpriteLoaderPlugin = require('svg-sprite-loader/plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const analyze = false;
// 注入配置
swigLoader.resourceQueryCustomizer(function(resourceQuery, templatepath) {
resourceQuery.config = { env: utils.env };
return resourceQuery;
});
const pages = utils.htmlPlugin();
const pageKeys = Object.keys(pages);
function resolve(dir) {
return path.join(__dirname, dir);
}
utils.printEnvLog();
module.exports = function() {
const config = {
publicPath: `${utils.env.PUBLIC_PATH}`,
outputDir: utils.outputDir(),
lintOnSave: false,
productionSourceMap: false,
pages: pages,
configureWebpack: {
output: {
filename: 'assets/js/[name].js?v=[hash:8]',
chunkFilename: 'assets/js/[name].js?v=[hash:8]',
},
performance: {
hints: utils.env.ENV === 'production' ? 'warning' : false,
maxEntrypointSize: 300000,
maxAssetSize: 300000,
},
plugins: [new SpriteLoaderPlugin()],
},
transpileDependencies: ['vue-echarts', 'resize-detector'],
chainWebpack: (config) => {
// 修复热更新失效
config.resolve.symlinks(true);
// 打包分析
if (analyze) {
config.plugin('webpack-report').use(BundleAnalyzerPlugin, [{ analyzerMode: 'static' }]);
}
// 别名
config.resolve.alias
.set('@', resolve('src'))
.set('api', resolve('src/api'))
.set('assets', resolve('src/assets'))
.set('components', resolve('src/components'))
.set('config', resolve('src/config'))
.set('filters', resolve('src/filters'))
.set('mixins', resolve('src/mixins'))
.set('pages', resolve('src/pages'))
.set('utils', resolve('src/utils'))
.set('mock', resolve('src/mock'))
.set('directives', resolve('src/directives'))
.set('store', resolve('src/store'))
.set('styles', resolve('src/styles'));
config.module
.rule('html')
.test(/\.html$/)
.use('swig-loader')
.loader('swig-loader')
.end();
// 压缩图片
config.module
.rule('images')
.use('image-webpack-loader')
.loader('image-webpack-loader')
.options({
// mozjpeg: { progressive: true, quality: 65 },
mozjpeg: { enabled: false, progressive: true, quality: 65 },
optipng: { enabled: false },
pngquant: { enabled: false, quality: [0.65, 0.9], speed: 4 },
// pngquant: { quality: [0.65, 0.9], speed: 4 },
gifsicle: { interlaced: false },
webp: { enabled: false, quality: 75 },
});
config.module
.rule('images')
.use('url-loader')
.loader('url-loader')
.tap((options) => {
options.limit = 10;
options.fallback = {
loader: 'file-loader',
options: {
name: 'assets/images/[name].[ext]?v=[hash:8]',
publicPath: utils.env.PUBLIC_PATH,
},
};
return options;
})
.end();
// 单独处理assets/images/*.svg格式的文件的URL
config.module
.rule('svg')
.exclude.add(resolve('src/assets/svg/icons'))
.end()
.use('file-loader')
.loader('file-loader')
.options({
name: 'assets/svg/[name].[ext]?v=[hash:8]',
publicPath: utils.env.PUBLIC_PATH,
})
.end();
// set fonts
config.module
.rule('fonts')
.test(/\.(woff2?|eot|ttf|otf)(\?.*)?$/)
.use('url-loader')
.loader('url-loader')
.options({
limit: 100,
name: 'assets/fonts/[name].[ext]?v=[hash:8]',
publicPath: utils.env.PUBLIC_PATH,
})
.end();
// set svg-sprite-loader
config.module
.rule('svg')
.exclude.add(resolve('src/assets/svg/icons'))
.end();
config.module
.rule('icons')
.test(/\.svg$/)
.include.add(resolve('src/assets/svg/icons'))
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: '[name]',
})
.end();
// set preserveWhitespace
config.module
.rule('vue')
.use('vue-loader')
.loader('vue-loader')
.tap((options) => {
options.compilerOptions.preserveWhitespace = true;
return options;
})
.end();
// set chunks
config.optimization.splitChunks({
cacheGroups: {
theme: {
name: 'chunk-vue-ecology',
test: /[\\/]node_modules\/_?(vue|vuex|vue-router)(@.*)?[\\/]/,
chunks: 'all',
priority: -1,
enforce: true,
},
vendors: {
name: 'chunk-vendors',
priority: -10,
chunks: 'initial',
minChunks: 2,
test: /[\\/]node_modules[\\/]/,
enforce: true,
},
...pageKeys.map((key) => ({
name: `chunk-${key}-vendors`,
priority: -11,
chunks: (chunk) => chunk.name === key,
test: /[\\/]node_modules[\\/]/,
enforce: true,
})),
common: {
name: 'chunk-common',
priority: -20,
chunks: 'initial',
minChunks: 2,
reuseExistingChunk: true,
enforce: true,
},
},
});
// html插件
console.log('\n\n');
for (const name in pages) {
config.plugins.delete(`preload-${name}`);
config.plugins.delete(`prefetch-${name}`);
config.plugin(`html-${name}`).tap((options) => {
options[0].minify = false;
console.log(options);
return options;
});
}
console.log('\n\n');
config
.when(
process.env.NODE_ENV === 'development',
// https://webpack.js.org/configuration/devtool/#development
(config) => config.devtool('cheap-module-eval-source-map')
)
.end();
},
css: {
extract: {
filename: 'assets/css/[name].css?v=[hash:8]',
chunkFilename: 'assets/css/sytle-[name].css?v=[hash:8]',
},
sourceMap: false,
requireModuleExtension: true,
},
devServer: {
overlay: {
warnings: false,
errors: true,
},
host: 'localhost',
port: 8080,
https: false,
open: true,
hotOnly: true,
proxy: {
api: {
target: 'https://test-b-fat.pingan.com.cn',
changeOrigin: true,
pathRewrite: {
'^/api': ''
},
}
},
},
};
return config;
};utils.js
const glob = require('glob');
const chalk = require('chalk');
const RSB_API = process.env.VUE_APP_API_DOMAIN;
const CDN_DOMAIN = process.env.VUE_APP_CDN_DOMAIN;
const PUBLIC_PATH = process.env.VUE_APP_PUBLIC_PATH;
const APP_ENV = process.env.VUE_APP_ENV;
const ENV = process.env.NODE_ENV;
const TIME_STAMP = Date.now();
exports.env = {
APP_ENV,
RSB_API,
CDN_DOMAIN,
PUBLIC_PATH,
TIME_STAMP,
ENV,
};
exports.outputDir = function() {
if (APP_ENV === 'production') {
return './release/prd';
}
if (APP_ENV === 'staging') {
return './release/stg';
}
};
// 生成pages
exports.htmlPlugin = function() {
const pages = {};
glob.sync('./src/pages/**/main.js').forEach((filepath) => {
const fileName = filepath.substring('./src/pages/'.length, filepath.indexOf('/main.js'));
pages[fileName] = {
entry: `src/pages/${fileName}/main.js`,
template: filepath.split('/main.js')[0] + '/index.html',
filename: `${fileName}.html`,
chunks: [
'chunk-vue-ecology',
'chunk-vendors',
`chunk-${fileName}-vendors`,
'chunk-common',
fileName,
],
};
});
return pages;
};
exports.printEnvLog = function() {
console.log(chalk.blue('Hello!', chalk.green(' The current environment:')));
console.log(
chalk.green(
'\n NODE_ENV ' +
chalk.red.underline.bold(`${process.env.NODE_ENV}`) +
'\n APP_ENV ' +
chalk.red.underline.bold(`${APP_ENV}`) +
'\n RSB_API ' +
chalk.red.underline.bold(`${RSB_API}`) +
'\n PUBLIC_PATH ' +
chalk.red.underline.bold(`${PUBLIC_PATH}`) +
'\n CDN_DOMAIN ' +
chalk.red.underline.bold(`${CDN_DOMAIN}`) +
'\n'
)
);
};
exports.parseParams = function(data = {}) {
try {
var tempArr = [];
for (var i in data) {
var key = encodeURIComponent(i);
var value = encodeURIComponent(data[i]);
tempArr.push(key + '=' + value);
}
var urlParamsStr = tempArr.join('&');
return urlParamsStr;
} catch (err) {
return '';
}
};Reactions are currently unavailable