initial commit
This commit is contained in:
418
fluxer_app/rspack.config.mjs
Normal file
418
fluxer_app/rspack.config.mjs
Normal file
@@ -0,0 +1,418 @@
|
||||
/*
|
||||
* Copyright (C) 2026 Fluxer Contributors
|
||||
*
|
||||
* This file is part of Fluxer.
|
||||
*
|
||||
* Fluxer is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Fluxer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import path, {dirname} from 'node:path';
|
||||
import {fileURLToPath} from 'node:url';
|
||||
import {CopyRspackPlugin, DefinePlugin, HtmlRspackPlugin, SwcJsMinimizerRspackPlugin} from '@rspack/core';
|
||||
import ReactRefreshPlugin from '@rspack/plugin-react-refresh';
|
||||
import {createPoFileRule, getLinguiSwcPluginConfig} from './scripts/build/rspack/lingui.mjs';
|
||||
import {staticFilesPlugin} from './scripts/build/rspack/static-files.mjs';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
const ROOT_DIR = path.resolve(__dirname, '.');
|
||||
const SRC_DIR = path.join(ROOT_DIR, 'src');
|
||||
const DIST_DIR = path.join(ROOT_DIR, 'dist');
|
||||
const PKGS_DIR = path.join(ROOT_DIR, 'pkgs');
|
||||
const PUBLIC_DIR = path.join(ROOT_DIR, 'assets');
|
||||
|
||||
const CDN_ENDPOINT = 'https://fluxerstatic.com';
|
||||
|
||||
const isProduction = process.env.NODE_ENV === 'production';
|
||||
const isDevelopment = !isProduction;
|
||||
|
||||
const mode = isProduction ? 'production' : 'development';
|
||||
const devJsName = 'assets/[name].js';
|
||||
const devCssName = 'assets/[name].css';
|
||||
|
||||
function getPublicEnvVar(name) {
|
||||
const value = process.env[name];
|
||||
return JSON.stringify(value) ?? 'undefined';
|
||||
}
|
||||
|
||||
export default () => {
|
||||
const linguiSwcPlugin = getLinguiSwcPluginConfig();
|
||||
|
||||
return {
|
||||
mode,
|
||||
|
||||
entry: {
|
||||
main: path.join(SRC_DIR, 'index.tsx'),
|
||||
},
|
||||
|
||||
output: {
|
||||
path: DIST_DIR,
|
||||
publicPath: isProduction ? `${CDN_ENDPOINT}/` : '/',
|
||||
workerPublicPath: '/',
|
||||
filename: isProduction ? 'assets/[contenthash:16].js' : devJsName,
|
||||
chunkFilename: isProduction ? 'assets/[contenthash:16].js' : devJsName,
|
||||
cssFilename: isProduction ? 'assets/[contenthash:16].css' : devCssName,
|
||||
cssChunkFilename: isProduction ? 'assets/[contenthash:16].css' : devCssName,
|
||||
assetModuleFilename: isProduction ? 'assets/[contenthash:16][ext]' : 'assets/[name].[hash][ext]',
|
||||
webAssemblyModuleFilename: isProduction ? 'assets/[contenthash:16].wasm' : 'assets/[name].[hash].wasm',
|
||||
clean: true,
|
||||
},
|
||||
|
||||
devtool: 'source-map',
|
||||
|
||||
target: ['web', 'browserslist'],
|
||||
|
||||
resolve: {
|
||||
alias: {
|
||||
'~': SRC_DIR,
|
||||
'@pkgs': PKGS_DIR,
|
||||
},
|
||||
extensions: [
|
||||
'.web.tsx',
|
||||
'.web.ts',
|
||||
'.web.jsx',
|
||||
'.web.js',
|
||||
'.tsx',
|
||||
'.ts',
|
||||
'.jsx',
|
||||
'.js',
|
||||
'.json',
|
||||
'.mjs',
|
||||
'.cjs',
|
||||
'.po',
|
||||
],
|
||||
},
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(tsx|ts|jsx|js)$/,
|
||||
exclude: /node_modules/,
|
||||
type: 'javascript/auto',
|
||||
parser: {
|
||||
dynamicImport: false,
|
||||
},
|
||||
use: {
|
||||
loader: 'builtin:swc-loader',
|
||||
options: {
|
||||
jsc: {
|
||||
parser: {
|
||||
syntax: 'typescript',
|
||||
tsx: true,
|
||||
decorators: true,
|
||||
},
|
||||
transform: {
|
||||
legacyDecorator: true,
|
||||
decoratorMetadata: true,
|
||||
react: {
|
||||
runtime: 'automatic',
|
||||
development: isDevelopment,
|
||||
refresh: isDevelopment,
|
||||
},
|
||||
},
|
||||
experimental: {
|
||||
plugins: [linguiSwcPlugin],
|
||||
},
|
||||
target: 'es2015',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
createPoFileRule(),
|
||||
|
||||
{
|
||||
test: /\.module\.css$/,
|
||||
use: [{loader: 'postcss-loader'}],
|
||||
type: 'css/module',
|
||||
parser: {namedExports: false},
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
exclude: /\.module\.css$/,
|
||||
use: [{loader: 'postcss-loader'}],
|
||||
type: 'css',
|
||||
},
|
||||
|
||||
{
|
||||
test: /\.svg$/,
|
||||
issuer: /\.[jt]sx?$/,
|
||||
resourceQuery: /react/,
|
||||
type: 'javascript/auto',
|
||||
use: [
|
||||
{
|
||||
loader: 'builtin:swc-loader',
|
||||
options: {
|
||||
jsc: {
|
||||
parser: {syntax: 'typescript', tsx: true},
|
||||
transform: {react: {runtime: 'automatic', development: isDevelopment}},
|
||||
target: 'es2015',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: '@svgr/webpack',
|
||||
options: {
|
||||
babel: false,
|
||||
typescript: true,
|
||||
jsxRuntime: 'automatic',
|
||||
svgoConfig: {
|
||||
plugins: [
|
||||
{
|
||||
name: 'preset-default',
|
||||
params: {overrides: {removeViewBox: false}},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.svg$/,
|
||||
resourceQuery: {not: [/react/]},
|
||||
type: 'asset/resource',
|
||||
},
|
||||
|
||||
{
|
||||
test: /\.wasm$/,
|
||||
type: 'asset/resource',
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpg|jpeg|gif|webp|ico|woff|woff2|ttf|eot|mp3|wav|ogg|mp4|webm)$/,
|
||||
type: 'asset/resource',
|
||||
generator: {
|
||||
filename: isProduction ? 'assets/[contenthash:16][ext]' : 'assets/[name].[hash][ext]',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
generator: {
|
||||
'css/module': {
|
||||
exportsConvention: 'as-is',
|
||||
},
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new HtmlRspackPlugin({
|
||||
template: path.join(ROOT_DIR, 'index.html'),
|
||||
filename: 'index.html',
|
||||
inject: 'body',
|
||||
scriptLoading: 'module',
|
||||
}),
|
||||
|
||||
new CopyRspackPlugin({
|
||||
patterns: [
|
||||
{
|
||||
from: PUBLIC_DIR,
|
||||
to: DIST_DIR,
|
||||
noErrorOnMissing: true,
|
||||
},
|
||||
],
|
||||
}),
|
||||
|
||||
staticFilesPlugin({cdnEndpoint: CDN_ENDPOINT}),
|
||||
|
||||
new DefinePlugin({
|
||||
'process.env.NODE_ENV': JSON.stringify(mode),
|
||||
'import.meta.env.DEV': JSON.stringify(isDevelopment),
|
||||
'import.meta.env.PROD': JSON.stringify(isProduction),
|
||||
'import.meta.env.MODE': JSON.stringify(mode),
|
||||
'import.meta.env.PUBLIC_BUILD_SHA': getPublicEnvVar('PUBLIC_BUILD_SHA'),
|
||||
'import.meta.env.PUBLIC_BUILD_NUMBER': getPublicEnvVar('PUBLIC_BUILD_NUMBER'),
|
||||
'import.meta.env.PUBLIC_BUILD_TIMESTAMP': getPublicEnvVar('PUBLIC_BUILD_TIMESTAMP'),
|
||||
'import.meta.env.PUBLIC_PROJECT_ENV': getPublicEnvVar('PUBLIC_PROJECT_ENV'),
|
||||
'import.meta.env.PUBLIC_SENTRY_DSN': getPublicEnvVar('PUBLIC_SENTRY_DSN'),
|
||||
'import.meta.env.PUBLIC_SENTRY_PROJECT_ID': getPublicEnvVar('PUBLIC_SENTRY_PROJECT_ID'),
|
||||
'import.meta.env.PUBLIC_SENTRY_PUBLIC_KEY': getPublicEnvVar('PUBLIC_SENTRY_PUBLIC_KEY'),
|
||||
'import.meta.env.PUBLIC_SENTRY_PROXY_PATH': getPublicEnvVar('PUBLIC_SENTRY_PROXY_PATH'),
|
||||
'import.meta.env.PUBLIC_API_VERSION': getPublicEnvVar('PUBLIC_API_VERSION'),
|
||||
'import.meta.env.PUBLIC_BOOTSTRAP_API_ENDPOINT': getPublicEnvVar('PUBLIC_BOOTSTRAP_API_ENDPOINT'),
|
||||
'import.meta.env.PUBLIC_BOOTSTRAP_API_PUBLIC_ENDPOINT': getPublicEnvVar('PUBLIC_BOOTSTRAP_API_PUBLIC_ENDPOINT'),
|
||||
}),
|
||||
|
||||
isDevelopment && new ReactRefreshPlugin(),
|
||||
].filter(Boolean),
|
||||
|
||||
optimization: {
|
||||
splitChunks: isProduction
|
||||
? {
|
||||
chunks: 'all',
|
||||
maxInitialRequests: 50,
|
||||
cacheGroups: {
|
||||
icons: {
|
||||
test: /[\\/]node_modules[\\/]@phosphor-icons[\\/]/,
|
||||
name: 'icons',
|
||||
priority: 60,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
highlight: {
|
||||
test: /[\\/]node_modules[\\/]highlight\.js[\\/]/,
|
||||
name: 'highlight',
|
||||
priority: 55,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
livekit: {
|
||||
test: /[\\/]node_modules[\\/](livekit-client|@livekit)[\\/]/,
|
||||
name: 'livekit',
|
||||
priority: 50,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
katex: {
|
||||
test: /[\\/]node_modules[\\/]katex[\\/]/,
|
||||
name: 'katex',
|
||||
priority: 48,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
animation: {
|
||||
test: /[\\/]node_modules[\\/](framer-motion|motion)[\\/]/,
|
||||
name: 'animation',
|
||||
priority: 45,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
mobx: {
|
||||
test: /[\\/]node_modules[\\/](mobx|mobx-react-lite|mobx-persist-store)[\\/]/,
|
||||
name: 'mobx',
|
||||
priority: 43,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
sentry: {
|
||||
test: /[\\/]node_modules[\\/]@sentry[\\/]/,
|
||||
name: 'sentry',
|
||||
priority: 41,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
reactAria: {
|
||||
test: /[\\/]node_modules[\\/]react-aria-components[\\/]/,
|
||||
name: 'react-aria',
|
||||
priority: 40,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
validation: {
|
||||
test: /[\\/]node_modules[\\/](valibot)[\\/]/,
|
||||
name: 'validation',
|
||||
priority: 38,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
datetime: {
|
||||
test: /[\\/]node_modules[\\/]luxon[\\/]/,
|
||||
name: 'datetime',
|
||||
priority: 37,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
observable: {
|
||||
test: /[\\/]node_modules[\\/]rxjs[\\/]/,
|
||||
name: 'observable',
|
||||
priority: 36,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
unicode: {
|
||||
test: /[\\/]node_modules[\\/](idna-uts46-hx|emoji-regex)[\\/]/,
|
||||
name: 'unicode',
|
||||
priority: 35,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
dnd: {
|
||||
test: /[\\/]node_modules[\\/](@dnd-kit|react-dnd)[\\/]/,
|
||||
name: 'dnd',
|
||||
priority: 33,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
radix: {
|
||||
test: /[\\/]node_modules[\\/]@radix-ui[\\/]/,
|
||||
name: 'radix',
|
||||
priority: 31,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
ui: {
|
||||
test: /[\\/]node_modules[\\/](react-select|react-hook-form|react-modal-sheet|react-zoom-pan-pinch|@floating-ui)[\\/]/,
|
||||
name: 'ui',
|
||||
priority: 30,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
utils: {
|
||||
test: /[\\/]node_modules[\\/](lodash|clsx|qrcode|thumbhash|ua-parser-js|match-sorter)[\\/]/,
|
||||
name: 'utils',
|
||||
priority: 28,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
networking: {
|
||||
test: /[\\/]node_modules[\\/](ws|undici)[\\/]/,
|
||||
name: 'networking',
|
||||
priority: 26,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
react: {
|
||||
test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
|
||||
name: 'react',
|
||||
priority: 25,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
vendor: {
|
||||
test: /[\\/]node_modules[\\/]/,
|
||||
name: 'vendor',
|
||||
priority: 10,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
: false,
|
||||
runtimeChunk: false,
|
||||
chunkSplit: false,
|
||||
moduleIds: 'named',
|
||||
chunkIds: 'named',
|
||||
minimize: isProduction,
|
||||
minimizer: [
|
||||
new SwcJsMinimizerRspackPlugin({
|
||||
compress: true,
|
||||
mangle: true,
|
||||
format: {comments: false},
|
||||
}),
|
||||
],
|
||||
},
|
||||
|
||||
devServer: isDevelopment
|
||||
? {
|
||||
port: 3000,
|
||||
hot: true,
|
||||
liveReload: false,
|
||||
historyApiFallback: true,
|
||||
allowedHosts: 'all',
|
||||
client: {
|
||||
webSocketURL: 'auto://0.0.0.0:0/ws',
|
||||
},
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
|
||||
'Access-Control-Allow-Headers': 'X-Requested-With, content-type, Authorization',
|
||||
},
|
||||
static: {
|
||||
directory: DIST_DIR,
|
||||
watch: false,
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
|
||||
experiments: {css: true},
|
||||
|
||||
css: {
|
||||
modules: {
|
||||
localIdentName: '[name]__[local]___[hash:base64:16]',
|
||||
localsConvention: 'camelCaseOnly',
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user