Skip to content

Commit ed15eab

Browse files
chore: test rspack
Signed-off-by: SebastianKrupinski <krupinskis05@gmail.com>
1 parent 9aea6ee commit ed15eab

7 files changed

Lines changed: 4232 additions & 3203 deletions

File tree

package-lock.json

Lines changed: 3984 additions & 3020 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@
66
"license": "AGPL-3.0-only",
77
"author": "Christoph Wurst <christoph@winzerhof-wurst.at>",
88
"scripts": {
9-
"build": "NODE_ENV=production webpack --progress --config webpack.prod.js",
10-
"dev": "NODE_ENV=development webpack --config webpack.dev.js",
9+
"build": "rspack build --env production",
10+
"dev": "rspack build --env development",
11+
"watch": "rspack build --env development --watch",
12+
"analyze": "RSDOCTOR=true rspack build --env production",
13+
"stats": "rspack build --env production --json js/stats.json",
1114
"postinstall": "patch-package",
1215
"lint": "eslint --ext .js,.ts,.vue .",
1316
"lint:fix": "eslint --ext .js,.ts,.vue --fix .",
@@ -16,8 +19,7 @@
1619
"test:e2e": "playwright test",
1720
"test:e2e:ui": "playwright test --ui",
1821
"test:unit": "vitest --run",
19-
"test:unit:watch": "vitest --watch",
20-
"watch": "NODE_ENV=development webpack --progress --watch --config webpack.dev.js"
22+
"test:unit:watch": "vitest --watch"
2123
},
2224
"browserslist": [
2325
"extends @nextcloud/browserslist-config"
@@ -84,33 +86,25 @@
8486
"@nextcloud/eslint-config": "^9.0.0-rc.8",
8587
"@nextcloud/stylelint-config": "^3.2.1",
8688
"@playwright/test": "^1.59.1",
89+
"@rsdoctor/rspack-plugin": "^1.5.9",
90+
"@rspack/cli": "^2.0.0",
91+
"@rspack/core": "^2.0.0",
92+
"@rspack/dev-server": "^2.0.1",
93+
"@rspack/plugin-node-polyfill": "^0.5.8",
8794
"@vitejs/plugin-vue2": "^2.3.4",
8895
"@vue/test-utils": "^1.3.6",
89-
"autoprefixer": "^10.5.0",
90-
"babel-loader": "^10.1.1",
91-
"babel-loader-exclude-node-modules-except": "^1.2.4",
9296
"css-loader": "^7.1.4",
9397
"eslint-plugin-import": "^2.32.0",
9498
"eslint-plugin-vitest-globals": "^1.6.1",
95-
"file-loader": "^6.2.0",
9699
"jsdom": "^29.1.1",
97-
"node-polyfill-webpack-plugin": "^3.0.0",
98100
"patch-package": "^8.0.1",
99-
"postcss": "^8.5.13",
100-
"postcss-loader": "^4.3.0",
101101
"sass": "^1.99.0",
102102
"sass-loader": "^16.0.7",
103-
"style-loader": "^4.0.0",
104-
"svg-inline-loader": "^0.8.2",
105-
"ts-loader": "^9.5.7",
106103
"typescript": "^5.9.3",
107-
"url-loader": "^4.1.1",
108104
"vitest": "^3.2.4",
109105
"vue-loader": "^15.11.1",
110-
"vue-template-compiler": "^2.7.16",
111-
"webpack": "^5.106.2",
112-
"webpack-cli": "^6.0.1",
113-
"webpack-merge": "^5.10.0"
106+
"webpack": "^5.102.1",
107+
"vue-template-compiler": "^2.7.16"
114108
},
115109
"engines": {
116110
"node": "^24.0.0",

rspack.config.js

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
const browserslistConfig = require('@nextcloud/browserslist-config')
7+
const { RsdoctorRspackPlugin } = require('@rsdoctor/rspack-plugin')
8+
const { defineConfig } = require('@rspack/cli')
9+
const { CssExtractRspackPlugin, LightningCssMinimizerRspackPlugin, DefinePlugin, ProgressPlugin, SwcJsMinimizerRspackPlugin, IgnorePlugin } = require('@rspack/core')
10+
const NodePolyfillPlugin = require('@rspack/plugin-node-polyfill')
11+
const browserslist = require('browserslist')
12+
const path = require('node:path')
13+
const { VueLoaderPlugin } = require('vue-loader')
14+
15+
// browserslist-rs does not support baseline queries yet
16+
// Manually resolving the browserslist config to the list of browsers with minimal versions
17+
// See: https://github.com/browserslist/browserslist-rs/issues/40
18+
const browsers = browserslist(browserslistConfig)
19+
const minBrowserVersion = browsers
20+
.map((str) => str.split(' '))
21+
.reduce((minVersion, [browser, version]) => {
22+
minVersion[browser] = minVersion[browser] ? Math.min(minVersion[browser], parseFloat(version)) : parseFloat(version)
23+
return minVersion
24+
}, {})
25+
const targets = Object.entries(minBrowserVersion).map(([browser, version]) => `${browser} >=${version}`).join(',')
26+
27+
const transpilePackages = [
28+
'js-base64',
29+
'p-limit',
30+
'p-defer',
31+
'p-queue',
32+
'p-try',
33+
'parseley',
34+
'selderee',
35+
'yocto-queue',
36+
]
37+
38+
const shouldExcludeFromJsTranspile = (resourcePath) => {
39+
if (!resourcePath.includes(`${path.sep}node_modules${path.sep}`)) {
40+
return false
41+
}
42+
43+
return !transpilePackages.some((moduleName) => resourcePath.includes(`${path.sep}node_modules${path.sep}${moduleName}${path.sep}`))
44+
}
45+
46+
module.exports = defineConfig((env) => {
47+
const appName = process.env.npm_package_name
48+
const appVersion = process.env.npm_package_version
49+
50+
const mode = (env.development && 'development') || (env.production && 'production') || process.env.NODE_ENV || 'production'
51+
const isDev = mode === 'development'
52+
process.env.NODE_ENV = mode
53+
54+
console.info('Building', appName, appVersion, '\n')
55+
56+
return {
57+
target: 'web',
58+
mode,
59+
devtool: isDev ? 'cheap-source-map' : 'source-map',
60+
stats: 'normal',
61+
62+
entry: {
63+
mail: path.join(__dirname, 'src', 'main.js'),
64+
oauthpopup: path.join(__dirname, 'src', 'main-oauth-popup.js'),
65+
settings: path.join(__dirname, 'src', 'main-settings.js'),
66+
htmlresponse: path.join(__dirname, 'src', 'html-response.js'),
67+
},
68+
69+
output: {
70+
path: path.resolve('./js'),
71+
filename: '[name].js',
72+
chunkFilename: `${appName}-[name].js?v=[contenthash]`,
73+
publicPath: 'auto',
74+
assetModuleFilename: '[name].[ext]?[contenthash]',
75+
clean: true,
76+
devtoolNamespace: appName,
77+
devtoolModuleFilenameTemplate(info) {
78+
const rootDir = process.cwd()
79+
const rel = path.relative(rootDir, info.absoluteResourcePath)
80+
return `webpack:///${appName}/${rel}`
81+
},
82+
},
83+
84+
optimization: {
85+
chunkIds: 'named',
86+
splitChunks: {
87+
automaticNameDelimiter: '-',
88+
cacheGroups: {
89+
defaultVendors: {
90+
reuseExistingChunk: true,
91+
},
92+
},
93+
},
94+
minimize: !isDev,
95+
minimizer: [
96+
new SwcJsMinimizerRspackPlugin({
97+
minimizerOptions: {
98+
targets,
99+
},
100+
}),
101+
new LightningCssMinimizerRspackPlugin({
102+
minimizerOptions: {
103+
targets,
104+
},
105+
}),
106+
],
107+
},
108+
109+
module: {
110+
rules: [
111+
{
112+
test: /\.vue$/,
113+
loader: 'vue-loader',
114+
options: {
115+
experimentalInlineMatchResource: true,
116+
},
117+
},
118+
{
119+
test: /\.css$/,
120+
use: [
121+
'vue-style-loader',
122+
'css-loader',
123+
],
124+
},
125+
{
126+
test: /\.scss$/,
127+
use: [
128+
'vue-style-loader',
129+
'css-loader',
130+
'sass-loader',
131+
],
132+
},
133+
{
134+
test: /\.[cm]?js$/,
135+
exclude: shouldExcludeFromJsTranspile,
136+
loader: 'builtin:swc-loader',
137+
options: {
138+
jsc: {
139+
parser: {
140+
syntax: 'ecmascript',
141+
},
142+
},
143+
env: {
144+
targets,
145+
},
146+
},
147+
type: 'javascript/auto',
148+
},
149+
{
150+
test: /\.ts$/,
151+
exclude: [/node_modules/],
152+
loader: 'builtin:swc-loader',
153+
options: {
154+
jsc: {
155+
parser: {
156+
syntax: 'typescript',
157+
},
158+
},
159+
env: {
160+
targets,
161+
},
162+
},
163+
type: 'javascript/auto',
164+
},
165+
{
166+
test: /\.(png|jpe?g|gif|svg|webp)$/i,
167+
type: 'asset',
168+
},
169+
{
170+
test: /\.(woff2?|eot|ttf|otf)$/i,
171+
type: 'asset/resource',
172+
},
173+
{
174+
test: /\.wasm$/i,
175+
type: 'asset/resource',
176+
},
177+
{
178+
test: /\.tflite$/i,
179+
type: 'asset/resource',
180+
},
181+
{
182+
resourceQuery: /raw/,
183+
type: 'asset/source',
184+
},
185+
{
186+
resourceQuery: /url$/,
187+
type: 'asset/resource',
188+
},
189+
{
190+
test: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
191+
type: 'asset/source',
192+
},
193+
],
194+
},
195+
196+
plugins: [
197+
new ProgressPlugin(),
198+
new VueLoaderPlugin(),
199+
new NodePolyfillPlugin(),
200+
new DefinePlugin({
201+
appName: JSON.stringify(appName),
202+
appVersion: JSON.stringify(appVersion),
203+
// Vue compile time flags
204+
// See: https://vuejs.org/api/compile-time-flags.html#compile-time-flags
205+
// See: https://github.com/vuejs/core/blob/v3.5.24/packages/vue/README.md#bundler-build-feature-flags
206+
// > The build will work without configuring these flags,
207+
// > however it is strongly recommended to properly configure them in order to get proper tree-shaking in the final bundle
208+
// Unlike Vite plugin, vue-loader does not do this automatically for Webpack
209+
// Although documentation says, it is optional, sometimes it breaks with:
210+
// ReferenceError: __VUE_PROD_DEVTOOLS__ is not defined
211+
__VUE_OPTIONS_API__: true,
212+
__VUE_PROD_DEVTOOLS__: false,
213+
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false,
214+
}),
215+
new IgnorePlugin({
216+
resourceRegExp: /^\.\/locale$/,
217+
contextRegExp: /moment$/,
218+
}),
219+
process.env.RSDOCTOR && new RsdoctorRspackPlugin(),
220+
],
221+
222+
resolve: {
223+
extensions: ['*', '.tsx', '.ts', '.js', '.vue', '.json'],
224+
symlinks: false,
225+
alias: {
226+
'@': path.resolve(__dirname, 'src'),
227+
},
228+
fallback: {
229+
fs: false,
230+
},
231+
},
232+
233+
cache: true,
234+
}
235+
})

0 commit comments

Comments
 (0)