Files
wagoo-admin/rspack.config.js
初心 77a83e363a
Some checks failed
Deploy to GitHub Pages / Deploy to GitHub Pages (push) Has been cancelled
初版提交
2025-09-09 13:35:24 +08:00

287 lines
8.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
},
},
}