Some checks failed
Deploy to GitHub Pages / Deploy to GitHub Pages (push) Has been cancelled
287 lines
8.0 KiB
Vue
287 lines
8.0 KiB
Vue
const path = require('path')
|
||
const { Configuration, DefinePlugin, BannerPlugin } = require('@rspack/core')
|
||
const HtmlRspackPlugin = require('html-rspack-plugin')
|
||
const { VueLoaderPlugin } = require('vue-loader')
|
||
const { publicPath, assetsDir, outputDir, title, devPort } = require('./src/config')
|
||
const dayjs = require('dayjs')
|
||
const time = dayjs().format('YYYY-M-D HH:mm:ss')
|
||
const fs = require('fs-extra')
|
||
const { webpackBanner } = require('./layouts')
|
||
|
||
// 设置环境变量
|
||
process.env.VUE_APP_TITLE = title || 'Wagoo'
|
||
process.env.VUE_APP_UPDATE_TIME = time
|
||
process.env.BASE_URL = publicPath
|
||
// 删除这一行,避免覆盖rspack.js中设置的值
|
||
// process.env.NODE_ENV = process.env.NODE_ENV || 'development'
|
||
process.env.VUE_APP_MOCK_ENABLE = 'false' // 启用mock
|
||
process.env.VUE_APP_AUTHOR = 'Wagoo' // 设置作者
|
||
|
||
const resolve = (dir) => path.join(__dirname, dir)
|
||
// 定义一个模式变量,避免冲突
|
||
const mode = process.env.NODE_ENV || 'development'
|
||
|
||
/**
|
||
* @type {Configuration}
|
||
*/
|
||
module.exports = {
|
||
mode: mode,
|
||
context: __dirname,
|
||
entry: {
|
||
app: './src/main.js',
|
||
},
|
||
output: {
|
||
path: resolve(outputDir),
|
||
publicPath: publicPath,
|
||
filename: 'js/[name].[contenthash:8].js',
|
||
chunkFilename: 'js/[name].[contenthash:8].js',
|
||
assetModuleFilename: `${assetsDir}/[name].[hash][ext][query]`,
|
||
},
|
||
// 增加性能提示配置
|
||
performance: {
|
||
// 提高阈值以减少警告
|
||
maxEntrypointSize: 3000000, // 3MB
|
||
maxAssetSize: 1000000, // 1MB
|
||
// 只在生产环境显示性能警告
|
||
hints: mode === 'production' ? 'warning' : false,
|
||
},
|
||
module: {
|
||
rules: [
|
||
{
|
||
test: /\.vue$/,
|
||
use: [
|
||
{
|
||
loader: 'vue-loader',
|
||
options: {
|
||
compilerOptions: {
|
||
preserveWhitespace: false,
|
||
},
|
||
},
|
||
},
|
||
],
|
||
},
|
||
{
|
||
test: /\.js$/,
|
||
exclude: /node_modules/,
|
||
use: {
|
||
loader: 'babel-loader',
|
||
options: {
|
||
presets: ['@vue/cli-plugin-babel/preset'],
|
||
},
|
||
},
|
||
},
|
||
{
|
||
test: /\.css$/,
|
||
use: ['style-loader', 'css-loader'],
|
||
},
|
||
{
|
||
test: /\.scss$/,
|
||
use: [
|
||
'style-loader',
|
||
{
|
||
loader: 'css-loader',
|
||
options: {
|
||
modules: {
|
||
auto: true,
|
||
localIdentName: '[path][name]__[local]--[hash:base64:5]',
|
||
},
|
||
},
|
||
},
|
||
{
|
||
loader: 'sass-loader',
|
||
options: {
|
||
additionalData: (content, loaderContext) => {
|
||
const { resourcePath, rootContext } = loaderContext
|
||
const relativePath = path.relative(rootContext, resourcePath)
|
||
if (relativePath.replace(/\\/g, '/') !== 'src/styles/variables.scss') {
|
||
return `@import "~@/styles/variables.scss";${content}`
|
||
}
|
||
return content
|
||
},
|
||
},
|
||
},
|
||
],
|
||
},
|
||
{
|
||
test: /\.(png|jpe?g|gif|svg)$/,
|
||
type: 'asset',
|
||
parser: {
|
||
dataUrlCondition: {
|
||
maxSize: 10 * 1024, // 10KB
|
||
},
|
||
},
|
||
},
|
||
{
|
||
test: /\.(woff2?|eot|ttf|otf)$/,
|
||
type: 'asset',
|
||
parser: {
|
||
dataUrlCondition: {
|
||
maxSize: 30 * 1024, // 增加到30KB
|
||
},
|
||
},
|
||
},
|
||
{
|
||
resourceQuery: /raw/,
|
||
type: 'asset/source',
|
||
},
|
||
],
|
||
},
|
||
resolve: {
|
||
extensions: ['.js', '.vue', '.json'],
|
||
alias: {
|
||
'@': resolve('src'),
|
||
vue$: 'vue/dist/vue.esm.js',
|
||
path: 'path-browserify',
|
||
fs: false,
|
||
},
|
||
fallback: {
|
||
path: require.resolve('path-browserify'),
|
||
},
|
||
},
|
||
plugins: [
|
||
new VueLoaderPlugin(),
|
||
new DefinePlugin({
|
||
// 完全移除可能引起冲突的NODE_ENV定义,让rspack.js来处理
|
||
'process.env.BASE_URL': JSON.stringify(process.env.BASE_URL),
|
||
'process.env.VUE_APP_TITLE': JSON.stringify(process.env.VUE_APP_TITLE),
|
||
'process.env.VUE_APP_MOCK_ENABLE': JSON.stringify(process.env.VUE_APP_MOCK_ENABLE),
|
||
'process.env.VUE_APP_AUTHOR': JSON.stringify(process.env.VUE_APP_AUTHOR),
|
||
'process.env.VUE_APP_UPDATE_TIME': JSON.stringify(process.env.VUE_APP_UPDATE_TIME),
|
||
}),
|
||
new HtmlRspackPlugin({
|
||
template: './public/index.html',
|
||
filename: 'index.html',
|
||
title: title || 'vue-admin-better',
|
||
inject: 'body',
|
||
templateParameters: {
|
||
BASE_URL: publicPath,
|
||
VUE_APP_TITLE: process.env.VUE_APP_TITLE,
|
||
VUE_APP_AUTHOR: process.env.VUE_APP_AUTHOR,
|
||
},
|
||
minify:
|
||
mode === 'production'
|
||
? {
|
||
removeComments: true,
|
||
collapseWhitespace: true,
|
||
removeAttributeQuotes: true,
|
||
collapseBooleanAttributes: true,
|
||
removeScriptTypeAttributes: true,
|
||
}
|
||
: false,
|
||
}),
|
||
// 添加版权信息到打包文件头部
|
||
new BannerPlugin({
|
||
banner: webpackBanner(time),
|
||
entryOnly: false,
|
||
include: /\.(js|css)$/,
|
||
}),
|
||
// 添加CopyPlugin功能,将public目录下除index.html外的文件复制到dist目录
|
||
{
|
||
apply(compiler) {
|
||
compiler.hooks.afterEmit.tap('CopyPublicFolderPlugin', (compilation) => {
|
||
// 确保目标目录存在
|
||
const targetPath = path.resolve(__dirname, 'dist');
|
||
fs.ensureDirSync(targetPath);
|
||
|
||
// 复制public目录下的所有文件(除了index.html)
|
||
fs.copySync(
|
||
path.resolve(__dirname, 'public'),
|
||
targetPath,
|
||
{
|
||
filter: (src) => {
|
||
// 不复制index.html文件,因为HtmlRspackPlugin会处理它
|
||
return !src.endsWith('index.html');
|
||
}
|
||
}
|
||
);
|
||
});
|
||
}
|
||
}
|
||
],
|
||
optimization: {
|
||
splitChunks: {
|
||
automaticNameDelimiter: '-',
|
||
chunks: 'all',
|
||
// 增加maxInitialRequests以允许更多的初始化块
|
||
maxInitialRequests: 6,
|
||
// 减小最小块大小,允许更细粒度的分割
|
||
minSize: 20000,
|
||
cacheGroups: {
|
||
chunk: {
|
||
name: 'vab-chunk',
|
||
test: /[\\/]node_modules[\\/]/,
|
||
minSize: 131072,
|
||
maxSize: 524288,
|
||
chunks: 'async',
|
||
minChunks: 2,
|
||
priority: 10,
|
||
},
|
||
vue: {
|
||
name: 'vue',
|
||
test: /[\\/]node_modules[\\/](vue(.*)|core-js)[\\/]/,
|
||
chunks: 'initial',
|
||
priority: 20,
|
||
},
|
||
elementUI: {
|
||
name: 'element-ui',
|
||
test: /[\\/]node_modules[\\/]element-ui(.*)[\\/]/,
|
||
priority: 30,
|
||
},
|
||
// 单独拆分常用工具库
|
||
vendors: {
|
||
name: 'vendors',
|
||
test: /[\\/]node_modules[\\/](lodash|axios|qs|dayjs)[\\/]/,
|
||
chunks: 'all',
|
||
priority: 35,
|
||
},
|
||
// 拆分样式资源
|
||
styles: {
|
||
name: 'styles',
|
||
test: /\.(css|scss)$/,
|
||
chunks: 'all',
|
||
enforce: true,
|
||
priority: 40,
|
||
},
|
||
extra: {
|
||
name: 'vab-layouts',
|
||
test: resolve('src/layouts'),
|
||
priority: 40,
|
||
},
|
||
},
|
||
},
|
||
// 添加压缩配置
|
||
minimize: mode === 'production',
|
||
// 如果是生产环境,增加tree shaking
|
||
usedExports: mode === 'production',
|
||
},
|
||
devServer: {
|
||
hot: true,
|
||
// 修改端口,避免冲突
|
||
port: 8090,
|
||
historyApiFallback: true,
|
||
static: {
|
||
directory: path.join(__dirname, 'public'),
|
||
},
|
||
client: {
|
||
overlay: {
|
||
errors: true,
|
||
warnings: false,
|
||
},
|
||
},
|
||
open: {
|
||
target: ['http://localhost:8090'],
|
||
},
|
||
setupMiddlewares: (middlewares, devServer) => {
|
||
if (!devServer) {
|
||
throw new Error('dev-server is not defined')
|
||
}
|
||
|
||
if (process.env.VUE_APP_MOCK_ENABLE === 'true') {
|
||
const mockServer = require('./mock/index')
|
||
mockServer(devServer.app)
|
||
}
|
||
|
||
return middlewares
|
||
},
|
||
},
|
||
} |