@jpapini/webpack-config
Version:
Custom Webpack configuration for bundling projects.
146 lines (130 loc) • 5.14 kB
text/typescript
import { createRequire } from 'node:module';
import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin';
import type { Config as SwcConfig } from '@swc/types';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
import {
ASSET_RULE_TEST,
CSS_RULE_TEST,
HASHED_CSS_FILENAME_PATTERN,
HASHED_JS_FILENAME_PATTERN,
TS_RULE_TEST,
} from '~/constants';
import { ReactAppContext } from '~/contexts';
import type { PresetFunc } from '~/types';
const require = createRequire(import.meta.url);
export const createReactAppPreset: PresetFunc = (context) => {
if (!(context instanceof ReactAppContext)) throw new Error('Invalid context');
return {
presetName: 'react-app',
devtool: context.isProduction ? false : 'eval-source-map',
target: 'web',
node: {
__dirname: true,
__filename: true,
},
resolve: {
extensions: ['.jsx', '.tsx'],
},
externalsPresets: { web: true },
optimization: {
minimize: context.isProduction,
moduleIds: 'deterministic',
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
},
},
entry: [context.entryFile],
output: {
filename: context.isProduction ? HASHED_JS_FILENAME_PATTERN : '[name].js',
publicPath: context.publicUrl.toString(),
},
module: {
rules: [
{
test: TS_RULE_TEST,
use: [
context.useSWC
? {
loader: require.resolve('swc-loader'),
options: {
minify: context.isProduction,
jsc: {
target: 'es5',
parser: {
syntax: 'typescript',
tsx: true,
},
transform: {
react: {
runtime: 'automatic',
refresh: context.isDevServer,
},
},
},
} satisfies SwcConfig,
}
: {
loader: require.resolve('ts-loader'),
options: {},
},
],
},
{
test: CSS_RULE_TEST,
use: [
MiniCssExtractPlugin.loader,
{
loader: require.resolve('css-loader'),
},
{
loader: require.resolve('postcss-loader'),
options: {
implementation: require.resolve('postcss'),
postcssOptions: {
plugins: [require.resolve('@tailwindcss/postcss')],
},
},
},
],
},
{
test: ASSET_RULE_TEST,
use: [
{
loader: require.resolve('url-loader'),
},
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: context.isProduction ? HASHED_CSS_FILENAME_PATTERN : '[name].css',
}),
...(context.htmlTemplateFile
? [new HtmlWebpackPlugin({ template: context.htmlTemplateFile })]
: []),
...(context.isDevServer
? [new ReactRefreshWebpackPlugin({ overlay: { sockIntegration: 'whm' } })]
: []),
],
...(context.isDevServer
? {
devServer: {
historyApiFallback: true,
host: context.publicUrl.hostname || undefined,
port: context.publicUrl.port || undefined,
hot: true,
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',
},
},
}
: {}),
};
};