//考虑用,parallel-webpack 并发打包加快打包速度
const path = require('path')
const webpack = require('webpack')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
// const CopyWebpackPlugin = require('copy-webpack-plugin')
//运行打包命令的时候就可以看到每个loader 和插件执行耗时
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const utils = require('./utils')
const packageConfig = require('../package.json')
const vueLoaderConfig = require('./vue-loader.conf')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
//读取.evn 对应的文件,写入环境变量
var dotenv = require('dotenv').config({ path: resolve('.env.' + process.env.NODE_ENV) });
var cfg = { ...Object.fromEntries(Object.entries(process.env).filter(([k]) => /^VITE_/.test(k))) }
let evnConfig = {}
for (let key in cfg) {
evnConfig[key] = '"' + cfg[key] + '"'
}
//路径转换
function resolve(dir) {
return path.join(__dirname, '..', dir)
}
//语法验证
const createLintingRule = () => ({
test: /\.(js|vue|dtvevt)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter'),
emitWarning: true
}
})
const useEslint = true;
//project 这个目录是暂时命名,当用hivui create 创建时候 会根据用户输入确定
const projectName = packageConfig.name == 'hi-vui-template' ? 'project' : packageConfig.name;
const smp = new SpeedMeasurePlugin();
module.exports = smp.wrap({
//指定目录,默认的值就是项目的根目录
// context: resolve(projectName),
//编译入口 String||Array
// entry: '',
//没有指定入口文件时,按目录搜索 对应的package.json所在的入口
entry() {
// 初始化入口配置
const entry = {}
// 所有模块的列表
const moduleToBuild = require('./module-conf').getModuleToBuild() || []
// 根据传入的待打包目录名称,构建多入口配置
for (let module of moduleToBuild) {
// entry[module] = `${module}/index.js`
let name = module.replace(/\//gi, '_');
entry[name] = `${module}/index.js`
}
return entry
},
//输出路径
output: {
path: resolve('dist'),
filename: 'static/js/[name].js',
//指定打包后的资源目录 相对于dist 下
publicPath: './'
},
// output: {
// filename:'static/js/[name].[chunkhash].js',
// chunkFilename: 'static/js/[id].[chunkhash].js'
// },
//如何寻找模块所对应的文件
resolve: {
// 配置省略文件路径后缀名,引入文件的时候可以不用写文件的后缀名
extensions: ['.css', '.less', '.js', '.jsx', '.vue', '.json'],
//指定引用别名
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve(projectName),
'@main': resolve(projectName + '/hivuiMain'),
}
},
//排除不打包
externals: {
// jquery: "jQuery",
},
//解析模块的规则
module: {
rules: [
// ...(useEslint ? [createLintingRule()] : []),
...(utils.styleLoaders({
sourceMap: false,
extract: true,
usePostCSS: true
})),
{
test: /\.(vue)$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.(js|jsx)$/,
loader: 'babel-loader',
exclude: /node_modules/
// exclude: [
// /node_modules\/(webpack|html-webpack-plugin)\//,
// ],
},
// element amdin src/icons使用
// {
// test: /\.svg$/,
// loader: 'svg-sprite-loader',
// include: [resolve('src/icons')],
// options: {
// symbolId: 'icon-[name]'
// }
// },
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: 'static/img/[name].[hash:7].[ext]'
// publicPath:"../img/", //替换CSS引用的图片路径 可以替换成爱拍云上的路径
// outputPath:"static/img/" //生成之后存放的路径
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: 'static/media/[name].[hash:7].[ext]'
// publicPath:"../media/", //替换CSS引用的图片路径 可以替换成爱拍云上的路径
// outputPath:"static/media/" //生成之后存放的路径
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: "[hash:8].[name].[ext]",
publicPath: "../fonts/", //替换CSS引用的图片路径 可以替换成爱拍云上的路径
outputPath: "static/fonts/" //生成之后存放的路径
// name: 'static/fonts/[name].[hash:7].[ext]'
}
}
]
},
devtool: '#source-map',
plugins: [
//注入全局变量的插件,通常使用该插件来判别代码运行的环境变量
new webpack.DefinePlugin({
'process.env': evnConfig
}),
//webpack 4之前的版本是通过webpack.optimize.CommonsChunkPlugin来压缩js,
//webpack 4版本之后被移除了,使用config.optimization.splitChunks来代替
//用来缩小(压缩优化)js文件
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: true,
parallel: true
}),
// // 将css提取到自己的文件中
new ExtractTextPlugin({
filename: 'static/css/[name].[contenthash].css',
// Setting the following option to `false` will not extract CSS from codesplit chunks.
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
allChunks: false,
}),
// 压缩提取的CSS。我们使用这个插件是为了来自不同组件的重复CSS可以被删除。
new OptimizeCSSPlugin({
//开发环境
// cssProcessorOptions:{
// safe: true, map: { inline: false }
// },
//打包生产
cssProcessorOptions: { safe: true }
}),
// keep module.id stable when vender modules does not change
new webpack.HashedModuleIdsPlugin(),
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
// 分别提取公共库
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks(module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
// 提取引用最小3次的公共包
// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
// split echarts into its own file
new webpack.optimize.CommonsChunkPlugin({
async: 'echarts',
minChunks(module) {
var context = module.context;
return context && (context.indexOf('echarts') >= 0 || context.indexOf('zrender') >= 0);
}
}),
// split xlsx into its own file
new webpack.optimize.CommonsChunkPlugin({
async: 'xlsx',
minChunks(module) {
var context = module.context;
return context && (context.indexOf('xlsx') >= 0);
}
}),
// split codemirror into its own file
new webpack.optimize.CommonsChunkPlugin({
async: 'codemirror',
minChunks(module) {
var context = module.context;
return context && (context.indexOf('codemirror') >= 0);
}
}),
// copy custom static assets
// new CopyWebpackPlugin([
// {
// from: resolve('static'),
// to: 'static',
// ignore: ['.*']
// }
// ]),
// 打包后,对包进行大小分析
// new BundleAnalyzerPlugin({
// //"bundle-report": "webpack-bundle-analyzer --port 8123 dist/stats.json"
// analyzerMode: 'disabled',//运行特定命令才打开
// generateStatsFile: true,
// statsOptions: { source: false }
// })
],
});