Skip to content

Commit 8d91a77

Browse files
authored
Migrate to rsbuild and swc (#3131)
* Remove react-scripts * Install rspack dependencies * Migrate and simplify index.html * Create rsbuild config * Migrate webpack config * Fix env var loading * Fix import types * Add ESLint plugin in dev mode * Set up test dependencies * Migrate jest config * Use SWV for jest * Fix test configuration * Update snapshot serialization * Fix SVG test issues * Move import resolver to test utils * Fix test environment issues with modern jest * Fix timezone issues * Fix image loading * Update more snapshots * Deduplicate dependencies * Fix jest module resolution * Fix some tests * Fix GitHub callback tests * Update more snapshots * Fix tree node creator tests * Fix `FileExplorerDialog` tests * Fix most tests * Fix repository dialog tests * Fix remaining test cases * Fix test utils * Update scripts * Remove CRACO * Remove old CRACO config * Fix and check tsc * Re-add the ignore warnings for dynamic modules * Address PR comments * Update snapshots
1 parent b9bb1cd commit 8d91a77

File tree

43 files changed

+4191
-8932
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+4191
-8932
lines changed

craco.config.js

Lines changed: 0 additions & 182 deletions
This file was deleted.

jest.config.js

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// @ts-check
2+
3+
const ignoreModulePaths = (...paths) => {
4+
const moduleRoot = replaceSlashes('/node_modules/');
5+
const modulePaths = paths
6+
.map(replaceSlashes)
7+
.map(path => `(${path}[/\\\\.*])`)
8+
.join('|');
9+
return moduleRoot + '(?!' + modulePaths + ').*.(js|jsx|ts|tsx)$';
10+
};
11+
const replaceSlashes = target => {
12+
return target.replaceAll('/', '[/\\\\]');
13+
};
14+
15+
/** @type {import('jest').Config} */
16+
export default {
17+
moduleDirectories: ['<rootDir>', 'node_modules'],
18+
testEnvironment: './jsdom-env.js',
19+
transform: {
20+
'^.+\\.(t|j)sx?$': [
21+
'@swc/jest',
22+
{
23+
sourceMaps: true,
24+
jsc: {
25+
parser: {
26+
syntax: 'typescript',
27+
tsx: true,
28+
decorators: false,
29+
dynamicImport: false
30+
},
31+
baseUrl: '.',
32+
transform: {
33+
react: {
34+
runtime: 'automatic'
35+
}
36+
}
37+
}
38+
}
39+
]
40+
},
41+
transformIgnorePatterns: [
42+
// Will give something like
43+
// '[/\\\\]node_modules[/\\\\]
44+
// (?!
45+
// ( @ion-phaser[/\\\\]react[/\\\\.*] )|
46+
// ( js-slang[/\\\\.*] )|
47+
// ( array-move[/\\\\.*] )|
48+
// ...
49+
// ( comma-separated-tokens[/\\\\.*] )
50+
// ).*.(js|jsx|ts|tsx)$'
51+
ignoreModulePaths(
52+
'@ion-phaser/react',
53+
'js-slang',
54+
'array-move',
55+
'konva',
56+
'react-konva',
57+
'react-debounce-render',
58+
'devlop',
59+
'hastscript',
60+
'hast-to-hyperscript',
61+
'hast-util-.+',
62+
'mdast-util-.+',
63+
'micromark',
64+
'micromark-.+',
65+
'vfile',
66+
'vfile-message',
67+
'unist-util-.+',
68+
'web-namespaces',
69+
'rehype-react',
70+
'unified',
71+
'bail',
72+
'is-plain-obj',
73+
'trough',
74+
'decode-named-character-reference',
75+
'character-entities',
76+
'trim-lines',
77+
'property-information',
78+
'space-separated-tokens',
79+
'comma-separated-tokens',
80+
'query-string',
81+
'decode-uri-component',
82+
'split-on-first',
83+
'filter-obj',
84+
'@sourceacademy/c-slang',
85+
'java-parser',
86+
'conductor'
87+
),
88+
'^.+\\.module\\.(css|sass|scss)$'
89+
],
90+
moduleNameMapper: {
91+
'\\.(jpg|jpeg)$': '<rootDir>/src/fileMock.ts',
92+
'\\.svg$': 'identity-obj-proxy',
93+
'\\.(css|less|sass|scss)$': 'identity-obj-proxy',
94+
'unist-util-visit-parents/do-not-use-color':
95+
'<rootDir>/node_modules/unist-util-visit-parents/lib',
96+
'vfile/do-not-use-conditional-minpath': '<rootDir>/node_modules/vfile/lib',
97+
'vfile/do-not-use-conditional-minproc': '<rootDir>/node_modules/vfile/lib',
98+
'vfile/do-not-use-conditional-minurl': '<rootDir>/node_modules/vfile/lib'
99+
},
100+
setupFilesAfterEnv: [
101+
'./src/setupTests.ts', // Setup file for Jest
102+
'./src/i18n/i18n.ts' // Setup i18next configuration
103+
]
104+
};

jsdom-env.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import JSDOMEnvironment from 'jest-environment-jsdom';
2+
3+
// https://stackoverflow.com/a/78051351
4+
export default class FixJSDOMEnvironment extends JSDOMEnvironment {
5+
constructor(...args) {
6+
super(...args);
7+
this.global.fetch = fetch;
8+
this.global.Request = Request;
9+
this.global.Response = Response;
10+
// And any other missing globals
11+
}
12+
}

package.json

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"private": true,
3+
"type": "module",
34
"name": "frontend",
45
"packageManager": "[email protected]",
56
"version": "1.4.3",
@@ -13,18 +14,19 @@
1314
},
1415
"scripts": {
1516
"analyze": "yarn build --stats; webpack-bundle-analyzer build/bundle-stats.json",
16-
"build": "cross-env DISABLE_ESLINT_PLUGIN=true NODE_OPTIONS=--max_old_space_size=8192 craco build",
17-
"coverage": "./scripts/coverage-fix.sh do && craco test --coverage && ./scripts/coverage-fix.sh undo",
17+
"build": "tsc -b && rsbuild build",
18+
"coverage": "./scripts/coverage-fix.sh do && yarn test --coverage && ./scripts/coverage-fix.sh undo",
1819
"format": "eslint --fix src && prettier --write \"src/**/*.{js,jsx,ts,tsx}\" && prettier --write --parser scss \"src/**/*.scss\"",
1920
"format:tsx": "prettier --list-different \"src/**/*.{js,jsx,ts,tsx}\"",
2021
"format:scss": "prettier --list-different --parser scss \"src/**/*.scss\"",
2122
"format:ci": "yarn run format:tsx && yarn run format:scss",
22-
"start": "cross-env DISABLE_ESLINT_PLUGIN=true BROWSER=none PORT=8000 craco start",
23-
"test": "cross-env TZ=UTF-8 craco test",
23+
"start": "rsbuild dev",
24+
"test": "cross-env TZ=Asia/Singapore jest",
2425
"test-coveralls": "./scripts/test-coveralls.sh",
2526
"update-ui-snapshots": "jest --updateSnapshot",
2627
"eslint": "eslint src",
27-
"prepare": "husky"
28+
"prepare": "husky",
29+
"preview": "rsbuild preview"
2830
},
2931
"dependencies": {
3032
"@blueprintjs/core": "^5.10.1",
@@ -98,6 +100,9 @@
98100
"sourceror": "^0.8.5",
99101
"unified": "^11.0.0",
100102
"uuid": "^11.0.2",
103+
"workbox-core": "^7.3.0",
104+
"workbox-precaching": "^7.3.0",
105+
"workbox-routing": "^7.3.0",
101106
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz",
102107
"xml2js": "^0.6.0",
103108
"yareco": "^0.1.5"
@@ -108,8 +113,15 @@
108113
"@babel/preset-typescript": "^7.24.1",
109114
"@babel/runtime": "^7.24.5",
110115
"@convergencelabs/ace-collab-ext": "^0.6.0",
111-
"@craco/craco": "^7.1.0",
116+
"@rsbuild/core": "^1.3.12",
117+
"@rsbuild/plugin-eslint": "^1.1.1",
118+
"@rsbuild/plugin-node-polyfill": "^1.3.0",
119+
"@rsbuild/plugin-react": "^1.3.0",
120+
"@rsbuild/plugin-sass": "^1.3.1",
121+
"@rsbuild/plugin-svgr": "^1.2.0",
112122
"@svgr/webpack": "^8.0.0",
123+
"@swc/core": "^1.11.22",
124+
"@swc/jest": "^0.2.38",
113125
"@testing-library/jest-dom": "^6.0.0",
114126
"@testing-library/react": "^15.0.6",
115127
"@testing-library/user-event": "^14.4.3",
@@ -120,6 +132,7 @@
120132
"@types/gapi.client": "^1.0.5",
121133
"@types/gapi.client.drive-v3": "^0.0.5",
122134
"@types/google.picker": "^0.0.39",
135+
"@types/identity-obj-proxy": "^3",
123136
"@types/jest": "^29.0.0",
124137
"@types/js-cookie": "^3.0.6",
125138
"@types/js-yaml": "^4.0.5",
@@ -146,6 +159,9 @@
146159
"eslint-plugin-simple-import-sort": "^12.1.1",
147160
"https-browserify": "^1.0.0",
148161
"husky": "^9.0.0",
162+
"identity-obj-proxy": "^3.0.0",
163+
"jest": "^29.7.0",
164+
"jest-environment-jsdom": "^29.7.0",
149165
"npm-run-all2": "^7.0.0",
150166
"os-browserify": "^0.3.0",
151167
"path": "^0.12.7",
@@ -154,7 +170,6 @@
154170
"prettier": "^3.3.3",
155171
"process": "^0.11.10",
156172
"react-error-overlay": "^6.0.11",
157-
"react-scripts": "^5.0.1",
158173
"react-test-renderer": "^18.2.0",
159174
"redux-saga-test-plan": "^4.0.6",
160175
"resize-observer-polyfill": "^1.5.1",

0 commit comments

Comments
 (0)