const path = require('path') const webpack = require('webpack') const { VueLoaderPlugin } = require('vue-loader') const TerserPlugin = require('terser-webpack-plugin') // 判断是否为开发环境 const isDev = process.env.NODE_ENV === 'development' module.exports = { mode: 'production', // 明确指定生产模式 target: 'web', // 明确指定浏览器环境 entry: './src/index.js', devtool: isDev ? 'source-map' : false, // 开发环境生成 sourcemap output: { path: path.resolve(__dirname, 'dist'), filename: 'admin-framework.js', library: { name: 'AdminFramework', // 挂载到 window.AdminFramework type: 'umd', export: 'default' }, globalObject: 'window', // 明确使用 window 对象 umdNamedDefine: true, // 为 UMD 模块添加名称 clean: true // 构建前清理 dist 目录 }, externals: { vue: { commonjs: 'vue', commonjs2: 'vue', amd: 'vue', root: 'Vue' }, 'vue-router': { commonjs: 'vue-router', commonjs2: 'vue-router', amd: 'vue-router', root: 'VueRouter' }, vuex: { commonjs: 'vuex', commonjs2: 'vuex', amd: 'vuex', root: 'Vuex' }, 'view-design': { commonjs: 'view-design', commonjs2: 'view-design', amd: 'view-design', root: 'iview' }, axios: { commonjs: 'axios', commonjs2: 'axios', amd: 'axios', root: 'axios' } }, module: { rules: [ { test: /\.vue$/, loader: 'vue-loader' }, { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/, options: { presets: [ [ '@babel/preset-env', { modules: 'auto', // 修改为 auto,让 webpack 自动处理模块格式 targets: { browsers: ['>1%', 'last 2 versions', 'not ie <= 8'] } } ], [ '@vue/babel-preset-jsx', { injectH: true } ] ] } }, { test: /\.css$/, use: [ 'vue-style-loader', 'css-loader' ] }, { test: /\.less$/, use: [ 'vue-style-loader', 'css-loader', 'less-loader' ] }, { // 图片文件:全部转为 base64 内联到代码中 test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, loader: 'url-loader', options: { limit: 999999999, // 所有图片都转为 base64 内联(设置超大限制) esModule: false } }, { // 字体文件:全部转为 base64 内联到代码中 test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, loader: 'url-loader', options: { limit: 999999999, // 所有字体都转为 base64 内联 esModule: false } }, { // 媒体文件:全部转为 base64 内联到代码中 test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, loader: 'url-loader', options: { limit: 999999999, // 所有媒体文件都转为 base64 内联 esModule: false } }, { // JSON 文件:内联到代码中 test: /\.json$/, type: 'asset/inline' }, { // 其他资源文件:内联到代码中 test: /\.(txt|xml|md)$/, type: 'asset/inline' } ] }, plugins: [ new VueLoaderPlugin(), new webpack.BannerPlugin({ banner: () => { const now = new Date() const updateTime = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}` return [ 'admin-framework v1.0.0', '通用后台管理系统框架 - 包含系统功能、登录、路由管理、布局等', '', '作者: light', '更新时间: ' + updateTime, '', 'Copyright (c) ' + now.getFullYear() ].join('\n') }, entryOnly: true // 只在入口文件顶部添加 }) ], resolve: { extensions: ['.js', '.vue', '.json'], alias: { '@': path.resolve(__dirname, 'src'), '@component': path.resolve(__dirname, 'src/components'), '@utils': path.resolve(__dirname, 'src/utils'), '@api': path.resolve(__dirname, 'src/api'), '@config': path.resolve(__dirname, 'src/config'), '@assets': path.resolve(__dirname, 'src/assets'), 'vue$': 'vue/dist/vue.esm.js' } }, optimization: { minimize: !isDev, // 开发环境不压缩 minimizer: [ new TerserPlugin({ terserOptions: { format: { comments: /^!|@preserve|@license|@cc_on|admin-framework|作者/i // 保留特殊注释 } }, extractComments: false // 不提取注释到单独文件 }) ] } }