UNPKG

@jpapini/webpack-config

Version:
146 lines (130 loc) 5.14 kB
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', }, }, } : {}), }; };