Skip to content

Commit c68ebba

Browse files
authored
Merge pull request #51 from ogarich89/feature/rspack
Migrate webpack to rspack
2 parents 762107d + 63136c8 commit c68ebba

File tree

9 files changed

+1294
-529
lines changed

9 files changed

+1294
-529
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ ISO uses a number of open source projects to work properly:
1717
* [Fastify](https://www.fastify.io/) - Fast and low overhead web framework, for Node.js
1818
* [React](https://reactjs.org/) - JavaScript library for building user interfaces
1919
* [Redux](https://redux.js.org/) - A Predictable State Container for JS Apps
20-
* [Webpack](https://webpack.js.org/) - Module bundler
21-
* [HMR](https://webpack.js.org/concepts/hot-module-replacement/) - Hot Module Replacement
20+
* [Rspack](https://rspack.dev/) - Module bundler
21+
* [HMR](https://rspack.dev/api/runtime-api/hmr) - Hot Module Replacement
2222
* [Browsersync](https://browsersync.io/) - Time-saving synchronised browser testing
2323
* [SWC](https://swc.rs/) - Rust-based platform for the Web
2424
* [ESLint](https://eslint.org/) - Statically analyzes your code to quickly find problems.
@@ -69,7 +69,7 @@ $ touch config/environment/development.json
6969
`withRedis` - Session with Redis store \
7070
`inspect` - Debugging Node.js with Chrome DevTools \
7171
`logger` - Fastify logger \
72-
`analyze` - Webpack Bundle Analyzer \
72+
`analyze` - Rsdoctor \
7373
`sentryDSN` - Error monitoring with [Sentry](https://sentry.io) \
7474
`certificate` - Optional object for run https server `{ "key": "/path/to/key.pem", "cert": "/path/to/cert.pem" }`
7575

@@ -118,7 +118,7 @@ For production release:
118118
```sh
119119
$ yarn production
120120
```
121-
[Build mode](https://webpack.js.org/configuration/mode/) (development | production) depending on `NODE_ENV` \
121+
[Build mode](https://rspack.dev/config/mode) (development | production) depending on `NODE_ENV` \
122122
Reading file `config/environment/(staging | production).json` depending on `ENVIRONMENT`
123123
```sh
124124
$ yarn build
Lines changed: 25 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import LoadablePlugin from '@loadable/webpack-plugin';
2-
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
3-
import TerserPlugin from 'terser-webpack-plugin';
4-
import webpack from 'webpack';
5-
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
2+
import { RsdoctorRspackPlugin } from '@rsdoctor/rspack-plugin';
3+
import rspack from '@rspack/core';
64
import { merge } from 'webpack-merge';
75

86
import { dirname, resolve } from 'path';
@@ -16,12 +14,16 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
1614

1715
const { analyze, withStatic } = config;
1816
const isDevelopment = process.env.NODE_ENV !== 'production';
19-
const { default: ReactRefreshWebpackPlugin } = isDevelopment
20-
? await import('@pmmmwh/react-refresh-webpack-plugin')
17+
const { default: ReactRefreshPlugin } = isDevelopment
18+
? await import('@rspack/plugin-react-refresh')
2119
: { default: null };
2220

2321
export default merge(common(), {
2422
context: resolve(__dirname, '../../src/root'),
23+
performance: {
24+
maxEntrypointSize: 500000,
25+
maxAssetSize: 500000,
26+
},
2527
entry: {
2628
bundle: [
2729
'./client.tsx',
@@ -44,9 +46,8 @@ export default merge(common(), {
4446
...(isDevelopment ? { runtimeChunk: 'single' } : {}),
4547
minimize: !isDevelopment,
4648
minimizer: [
47-
new TerserPlugin({
48-
minify: TerserPlugin.swcMinify,
49-
terserOptions: {
49+
new rspack.SwcJsMinimizerRspackPlugin({
50+
minimizerOptions: {
5051
compress: true,
5152
format: {
5253
comments: false,
@@ -55,50 +56,32 @@ export default merge(common(), {
5556
extractComments: false,
5657
}),
5758
],
58-
splitChunks: !isDevelopment
59-
? {
60-
cacheGroups: {
61-
vendors: {
62-
test: /[\\/]node_modules[\\/]/,
63-
priority: -10,
64-
reuseExistingChunk: true,
65-
},
66-
common: {
67-
minChunks: 2,
68-
priority: -20,
69-
reuseExistingChunk: true,
70-
},
71-
},
72-
chunks: 'all',
73-
maxInitialRequests: 30,
74-
maxAsyncRequests: 30,
75-
maxSize: 250000,
76-
}
77-
: false,
7859
},
7960
plugins: [
80-
...(analyze
81-
? [
82-
new BundleAnalyzerPlugin({
83-
openAnalyzer: false,
84-
analyzerMode: 'static',
85-
}),
86-
]
87-
: []),
88-
new MiniCssExtractPlugin({
61+
new LoadablePlugin({ writeToDisk: true }),
62+
new rspack.CssExtractRspackPlugin({
8963
filename: isDevelopment
9064
? 'css/[name].css'
9165
: 'css/[name].[contenthash].css',
9266
chunkFilename: isDevelopment
9367
? 'css/[name].css'
9468
: 'css/[name].[contenthash].css',
9569
}),
96-
new LoadablePlugin({ writeToDisk: true }),
97-
...(isDevelopment
70+
...(analyze
9871
? [
99-
new ReactRefreshWebpackPlugin(),
100-
new webpack.HotModuleReplacementPlugin(),
72+
new RsdoctorRspackPlugin({
73+
disableClientServer: !isDevelopment,
74+
mode: isDevelopment ? 'normal' : 'brief',
75+
linter: {
76+
rules: {
77+
'ecma-version-check': 'off',
78+
},
79+
},
80+
}),
10181
]
10282
: []),
83+
...(isDevelopment
84+
? [new ReactRefreshPlugin(), new rspack.HotModuleReplacementPlugin()]
85+
: []),
10386
],
10487
});

config/webpack/common.config.mjs renamed to config/rspack/common.config.mjs

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
2-
import webpack from 'webpack';
1+
import rspack from '@rspack/core';
32

43
import { dirname, resolve } from 'path';
54
import { fileURLToPath } from 'url';
@@ -32,12 +31,23 @@ const common = ({ isServer } = {}) => ({
3231
{
3332
test: /\.(ts|tsx|js|jsx)$/,
3433
exclude: /node_modules/,
35-
loader: 'swc-loader',
34+
loader: 'builtin:swc-loader',
3635
options: {
3736
sourceMap: isDevelopment,
37+
env: {
38+
targets: {
39+
chrome: '94',
40+
safari: '15',
41+
},
42+
mode: 'usage',
43+
coreJs: '3.36',
44+
},
3845
jsc: {
3946
experimental: {
40-
plugins: [['@swc/plugin-loadable-components', {}]],
47+
plugins: [
48+
['@swc/plugin-loadable-components', {}],
49+
...(isDevelopment ? [['swc-plugin-add-display-name', {}]] : []),
50+
],
4151
},
4252
parser: {
4353
syntax: 'typescript',
@@ -58,7 +68,16 @@ const common = ({ isServer } = {}) => ({
5868
{
5969
test: /\.(scss|sass|css)$/,
6070
use: [
61-
...(!isServer ? [MiniCssExtractPlugin.loader] : []),
71+
...(!isServer
72+
? [
73+
{
74+
loader: rspack.CssExtractRspackPlugin.loader,
75+
options: {
76+
hmr: isDevelopment,
77+
},
78+
},
79+
]
80+
: []),
6281
{
6382
loader: 'css-loader',
6483
options: {
@@ -92,6 +111,7 @@ const common = ({ isServer } = {}) => ({
92111
},
93112
},
94113
],
114+
type: 'javascript/auto',
95115
},
96116
{
97117
test: /\.svg$/,
@@ -102,30 +122,27 @@ const common = ({ isServer } = {}) => ({
102122
{
103123
test: /\.(png|jpe?g|gif)$/i,
104124
issuer: /\.(ts|tsx|js|jsx)$/,
105-
use: [
106-
{
107-
loader: 'url-loader',
108-
options: {
109-
fallback: 'file-loader',
110-
limit: 8192,
111-
emitFile: !isServer,
112-
name: isDevelopment ? '[name].[ext]' : '[name].[hash:8].[ext]',
113-
outputPath: 'assets',
114-
},
125+
type: 'asset',
126+
generator: {
127+
emit: !isServer,
128+
},
129+
parser: {
130+
dataUrlCondition: {
131+
maxSize: 8 * 1024,
115132
},
116-
],
133+
},
117134
},
118135
],
119136
},
120137
plugins: [
121-
new webpack.DefinePlugin({
138+
new rspack.DefinePlugin({
122139
'process.env.NODE_ENV': JSON.stringify(
123140
process.env.NODE_ENV || 'development',
124141
),
125142
isDevelopment,
126143
timestamp: JSON.stringify(+new Date()),
127144
}),
128-
new webpack.LoaderOptionsPlugin({
145+
new rspack.LoaderOptionsPlugin({
129146
options: { failOnError: !isDevelopment },
130147
}),
131148
],

config/webpack/server.config.mjs renamed to config/rspack/server.config.mjs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import webpack from 'webpack';
1+
import rspack from '@rspack/core';
22
import { merge } from 'webpack-merge';
33
import nodeExternals from 'webpack-node-externals';
44

@@ -21,11 +21,13 @@ export default merge(common({ isServer: true }), {
2121
splitChunks: false,
2222
},
2323
output: {
24+
library: {
25+
type: 'commonjs-module',
26+
},
2427
path: resolve(__dirname, '../../dist'),
2528
filename: 'request-handler.cjs',
26-
libraryTarget: 'commonjs-static',
2729
publicPath: '/',
2830
},
2931
externals: ['@loadable/component', nodeExternals()],
30-
plugins: [new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 })],
32+
plugins: [new rspack.optimize.LimitChunkCountPlugin({ maxChunks: 1 })],
3133
});

gulpfile.mjs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1+
import { rspack } from '@rspack/core';
12
import browserSync from 'browser-sync';
23
import gulpNodemon from 'gulp-nodemon';
3-
import webpack from 'webpack';
44
import webpackDevMiddleware from 'webpack-dev-middleware';
55
import webpackHotMiddleware from 'webpack-hot-middleware';
66

77
import { config } from './config/config.cjs';
8-
import webpackClientConfig from './config/webpack/client.config.mjs';
9-
import webpackServerConfig from './config/webpack/server.config.mjs';
8+
import rspackClientConfig from './config/rspack/client.config.mjs';
9+
import rspackServerConfig from './config/rspack/server.config.mjs';
1010

11-
const clientCompiler = webpack(webpackClientConfig);
12-
const serverCompiler = webpack(webpackServerConfig);
11+
const clientCompiler = rspack(rspackClientConfig);
12+
const serverCompiler = rspack(rspackServerConfig);
1313

1414
const { inspect, port, browserSyncPort } = config;
1515

@@ -40,7 +40,7 @@ export const server = () => {
4040

4141
export const client = () => {
4242
const devMiddleware = webpackDevMiddleware(clientCompiler, {
43-
publicPath: webpackClientConfig.output.publicPath,
43+
publicPath: rspackClientConfig.output.publicPath,
4444
});
4545
browserSync.init(null, {
4646
host: 'localhost',

package.json

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
"repository": "[email protected]:ogarich89/iso.git",
77
"type": "module",
88
"config": {
9-
"server": "--config config/webpack/server.config.mjs",
10-
"client": "--config config/webpack/client.config.mjs"
9+
"server": "--config config/rspack/server.config.mjs",
10+
"client": "--config config/rspack/client.config.mjs"
1111
},
1212
"engines": {
1313
"node": "^20.*"
@@ -17,8 +17,8 @@
1717
"server": "gulp server",
1818
"nodemon": "gulp nodemon",
1919
"dev": "gulp development",
20-
"build": "webpack $npm_package_config_client && webpack $npm_package_config_server",
21-
"production": "NODE_ENV=production webpack $npm_package_config_client && NODE_ENV=production webpack $npm_package_config_server",
20+
"build": "rspack $npm_package_config_client && rspack $npm_package_config_server",
21+
"production": "NODE_ENV=production rspack $npm_package_config_client && NODE_ENV=production rspack $npm_package_config_server",
2222
"start": "yarn build && node $npm_package_main",
2323
"test": "jest --coverage",
2424
"typecheck": "tsc --noEmit",
@@ -73,8 +73,11 @@
7373
"devDependencies": {
7474
"@eslint/js": "^9.9.0",
7575
"@loadable/webpack-plugin": "^5.2.2",
76-
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.15",
7776
"@prisma/client": "^5.18.0",
77+
"@rsdoctor/rspack-plugin": "^0.4.7",
78+
"@rspack/cli": "^1.0.14",
79+
"@rspack/core": "^1.0.14",
80+
"@rspack/plugin-react-refresh": "^1.0.0",
7881
"@svgr/webpack": "^8.1.0",
7982
"@swc/core": "^1.7.11",
8083
"@swc/jest": "^0.2.36",
@@ -102,15 +105,13 @@
102105
"eslint-plugin-import": "^2.31.0",
103106
"eslint-plugin-prettier": "^5.2.1",
104107
"eslint-plugin-react": "^7.35.0",
105-
"file-loader": "^6.2.0",
106108
"globals": "^15.9.0",
107109
"gulp": "^5.0.0",
108110
"gulp-nodemon": "^2.4.1",
109111
"identity-obj-proxy": "^3.0.0",
110112
"jest": "^29.3.1",
111113
"jest-environment-jsdom": "^29.3.1",
112114
"jest-transform-stub": "^2.0.0",
113-
"mini-css-extract-plugin": "^2.9.0",
114115
"nodemon": "^3.1.4",
115116
"postcss": "^8.4.41",
116117
"postcss-combine-media-query": "^1.0.1",
@@ -124,14 +125,9 @@
124125
"sass-embedded": "^1.77.8",
125126
"sass-loader": "^16.0.0",
126127
"stylelint": "^16.8.2",
127-
"swc-loader": "^0.2.6",
128-
"terser-webpack-plugin": "^5.3.6",
128+
"swc-plugin-add-display-name": "^0.5.0",
129129
"typescript": "^5.5.4",
130130
"typescript-eslint": "^8.1.0",
131-
"url-loader": "^4.1.1",
132-
"webpack": "^5.93.0",
133-
"webpack-bundle-analyzer": "^4.10.2",
134-
"webpack-cli": "^5.0.0",
135131
"webpack-dev-middleware": "^7.3.0",
136132
"webpack-hot-middleware": "^2.26.1",
137133
"webpack-merge": "^6.0.1",

server/index.mjs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ import { dirname, resolve } from 'path';
77
import { fileURLToPath } from 'url';
88

99
import { config } from '../config/config.cjs';
10-
import { requestHandler } from '../dist/request-handler.cjs';
10+
import pkg from '../dist/request-handler.cjs';
1111

1212
import { register } from './register.mjs';
1313
import { routes } from './routes.mjs';
1414

15+
const { requestHandler } = pkg;
16+
1517
const __dirname = dirname(fileURLToPath(import.meta.url));
1618

1719
const statsFile = resolve(__dirname, '../dist/loadable-stats.json');
@@ -55,7 +57,7 @@ app.setErrorHandler(async (error, request, reply) => {
5557
Sentry.captureException(error);
5658
}
5759

58-
reply.status(500).send({ error: 'Something went wrong' });
60+
reply.status(500).send(error);
5961
});
6062

6163
register(app);

src/root/client.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ import type { InitOptions } from 'i18next';
1313

1414
i18next.use(Fetch);
1515
i18next.use(initReactI18next);
16-
i18next.init(options() as InitOptions);
1716

1817
const ExtendedApp = withSSR()(App);
1918
const store = initializeState(window.__initialData__);
2019

21-
loadableReady(() => {
20+
loadableReady(async () => {
21+
await i18next.init(options() as InitOptions);
2222
hydrateRoot(
2323
document.getElementById('root') as HTMLDivElement,
2424
<Provider store={store}>

0 commit comments

Comments
 (0)