Skip to content

Commit 20726ae

Browse files
obiotclaude
andcommitted
Bump to 18.3.0: Node 24, dependency updates, code-split examples
- Minimum Node.js version is now 24.0.0 - CI: upgrade to pnpm/action-setup v5 and node 24 - Update vitest, turbo, eslint-plugin-jsdoc, typescript-eslint, typedoc, type-fest, vite to latest minor versions - Examples: lazy-load all example components for code splitting (main bundle 1286 KB → 427 KB) - Examples: fix ace editor loading order and initial content display - Fix missing README on the npm release Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent a9147da commit 20726ae

11 files changed

Lines changed: 345 additions & 246 deletions

File tree

.github/workflows/docs.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ jobs:
2020
- name: Setup node
2121
uses: actions/setup-node@v6
2222
with:
23-
node-version: 22
24-
- uses: pnpm/action-setup@v4
23+
node-version: 24
24+
- uses: pnpm/action-setup@v5
2525
- name: Get pnpm store directory
2626
run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
2727
- uses: actions/cache@v5

.github/workflows/main.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ jobs:
2828
- name: Setup node
2929
uses: actions/setup-node@v6
3030
with:
31-
node-version: 22
32-
- uses: pnpm/action-setup@v4
31+
node-version: 24
32+
- uses: pnpm/action-setup@v5
3333
- name: Get pnpm store directory
3434
run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
3535
- uses: actions/cache@v5
@@ -52,8 +52,8 @@ jobs:
5252
- name: Setup node
5353
uses: actions/setup-node@v6
5454
with:
55-
node-version: 22
56-
- uses: pnpm/action-setup@v4
55+
node-version: 24
56+
- uses: pnpm/action-setup@v5
5757
- name: Get pnpm store directory
5858
run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
5959
- uses: actions/cache@v5
@@ -73,8 +73,8 @@ jobs:
7373
- name: Setup node
7474
uses: actions/setup-node@v6
7575
with:
76-
node-version: 22
77-
- uses: pnpm/action-setup@v4
76+
node-version: 24
77+
- uses: pnpm/action-setup@v5
7878
- name: Get pnpm store directory
7979
shell: bash
8080
run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV

.github/workflows/publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ jobs:
3737
node-version: 24
3838
registry-url: "https://registry.npmjs.org"
3939

40-
- uses: pnpm/action-setup@v4
40+
- uses: pnpm/action-setup@v5
4141

4242
- name: Install dependencies
4343
run: pnpm install

package.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"version": "0.0.0",
44
"type": "module",
55
"engines": {
6-
"node": "^20.19.0 || >=22.12.0"
6+
"node": ">=24.0.0"
77
},
88
"scripts": {
99
"build": "turbo build",
@@ -25,18 +25,18 @@
2525
"@biomejs/biome": "2.3.14",
2626
"@eslint/js": "^9.39.4",
2727
"@types/node": "^25.5.0",
28-
"@vitest/browser": "^4.0.18",
29-
"@vitest/browser-playwright": "^4.0.18",
28+
"@vitest/browser": "^4.1.2",
29+
"@vitest/browser-playwright": "^4.1.2",
3030
"eslint": "^9.39.4",
31-
"eslint-plugin-jsdoc": "^62.8.0",
31+
"eslint-plugin-jsdoc": "^62.8.1",
3232
"globals": "^17.4.0",
3333
"lefthook": "^2.1.4",
3434
"tsconfig": "workspace:^",
3535
"tsx": "^4.21.0",
36-
"turbo": "^2.8.20",
36+
"turbo": "^2.8.21",
3737
"typescript": "^5.9.3",
38-
"typescript-eslint": "^8.57.1",
39-
"vitest": "^4.0.18"
38+
"typescript-eslint": "^8.57.2",
39+
"vitest": "^4.1.2"
4040
},
4141
"devDependencies": {
4242
"eslint-plugin-react-refresh": "^0.5.2",

packages/debug-plugin/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"author": "Olivier Biot (AltByte Pte Ltd)",
3131
"funding": "https://github.com/sponsors/melonjs",
3232
"engines": {
33-
"node": "^20.19.0 || >=22.12.0"
33+
"node": ">=24.0.0"
3434
},
3535
"types": "./build/index.d.ts",
3636
"exports": {

packages/examples/src/main.tsx

Lines changed: 130 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, {
2-
type ReactElement,
2+
lazy,
3+
Suspense,
34
useEffect,
45
useMemo,
56
useRef,
@@ -16,36 +17,127 @@ const sourceFiles = import.meta.glob("./examples/**/*.{ts,tsx,js}", {
1617
eager: true,
1718
}) as Record<string, string>;
1819

19-
import { ExampleAseprite } from "./examples/aseprite/ExampleAseprite";
20-
import { ExampleBenchmark } from "./examples/benchmark/ExampleBenchmark";
21-
import { ExampleBlendModes } from "./examples/blendModes/ExampleBlendModes";
22-
import { ExampleCompressedTextures } from "./examples/compressedTextures/ExampleCompressedTextures";
23-
import { ExampleDeviceTest } from "./examples/deviceTest/ExampleDeviceTest";
24-
import { ExampleDragAndDrop } from "./examples/dragAndDrop/ExampleDragAndDrop";
25-
import { ExampleGraphics } from "./examples/graphics/ExampleGraphics";
26-
import { ExampleHelloWorld } from "./examples/helloWorld/ExampleHelloWorld";
27-
import { ExampleIsometricRPG } from "./examples/isometricRpg/ExampleIsometricRPG";
28-
import { ExampleLights } from "./examples/lights/ExampleLights";
29-
import { ExampleLineOfSight } from "./examples/lineOfSight/ExampleLineOfSight";
30-
import { ExampleMasking } from "./examples/masking/ExampleMasking";
31-
import { ExamplePlatformer } from "./examples/platformer/ExamplePlatformer";
32-
import { ExampleSpaceInvaders } from "./examples/spaceInvaders/ExampleSpaceInvaders";
33-
import { ExampleSpine } from "./examples/spine/ExampleSpine";
34-
import { ExampleSprite } from "./examples/sprite/ExampleSprite";
35-
import { ExampleSVGShapes } from "./examples/svgShapes/ExampleSVGShapes";
36-
import { ExampleText } from "./examples/text/ExampleText";
37-
import { ExampleTexturePacker } from "./examples/texturePacker/ExampleTexturePacker";
38-
import { ExampleTiledMapLoader } from "./examples/tiledMapLoader/ExampleTiledMapLoader";
39-
import { ExampleUI } from "./examples/ui/ExampleUI";
40-
import { ExampleVideo } from "./examples/video/ExampleVideo";
41-
import { ExampleWhacAMole } from "./examples/whac-a-mole/ExampleWhacAMole";
20+
// lazy-load each example so they are code-split into separate chunks
21+
const ExampleAseprite = lazy(() =>
22+
import("./examples/aseprite/ExampleAseprite").then((m) => ({
23+
default: m.ExampleAseprite,
24+
})),
25+
);
26+
const ExampleBenchmark = lazy(() =>
27+
import("./examples/benchmark/ExampleBenchmark").then((m) => ({
28+
default: m.ExampleBenchmark,
29+
})),
30+
);
31+
const ExampleBlendModes = lazy(() =>
32+
import("./examples/blendModes/ExampleBlendModes").then((m) => ({
33+
default: m.ExampleBlendModes,
34+
})),
35+
);
36+
const ExampleCompressedTextures = lazy(() =>
37+
import("./examples/compressedTextures/ExampleCompressedTextures").then(
38+
(m) => ({ default: m.ExampleCompressedTextures }),
39+
),
40+
);
41+
const ExampleDeviceTest = lazy(() =>
42+
import("./examples/deviceTest/ExampleDeviceTest").then((m) => ({
43+
default: m.ExampleDeviceTest,
44+
})),
45+
);
46+
const ExampleDragAndDrop = lazy(() =>
47+
import("./examples/dragAndDrop/ExampleDragAndDrop").then((m) => ({
48+
default: m.ExampleDragAndDrop,
49+
})),
50+
);
51+
const ExampleGraphics = lazy(() =>
52+
import("./examples/graphics/ExampleGraphics").then((m) => ({
53+
default: m.ExampleGraphics,
54+
})),
55+
);
56+
const ExampleHelloWorld = lazy(() =>
57+
import("./examples/helloWorld/ExampleHelloWorld").then((m) => ({
58+
default: m.ExampleHelloWorld,
59+
})),
60+
);
61+
const ExampleIsometricRPG = lazy(() =>
62+
import("./examples/isometricRpg/ExampleIsometricRPG").then((m) => ({
63+
default: m.ExampleIsometricRPG,
64+
})),
65+
);
66+
const ExampleLights = lazy(() =>
67+
import("./examples/lights/ExampleLights").then((m) => ({
68+
default: m.ExampleLights,
69+
})),
70+
);
71+
const ExampleLineOfSight = lazy(() =>
72+
import("./examples/lineOfSight/ExampleLineOfSight").then((m) => ({
73+
default: m.ExampleLineOfSight,
74+
})),
75+
);
76+
const ExampleMasking = lazy(() =>
77+
import("./examples/masking/ExampleMasking").then((m) => ({
78+
default: m.ExampleMasking,
79+
})),
80+
);
81+
const ExamplePlatformer = lazy(() =>
82+
import("./examples/platformer/ExamplePlatformer").then((m) => ({
83+
default: m.ExamplePlatformer,
84+
})),
85+
);
86+
const ExampleSpaceInvaders = lazy(() =>
87+
import("./examples/spaceInvaders/ExampleSpaceInvaders").then((m) => ({
88+
default: m.ExampleSpaceInvaders,
89+
})),
90+
);
91+
const ExampleSpine = lazy(() =>
92+
import("./examples/spine/ExampleSpine").then((m) => ({
93+
default: m.ExampleSpine,
94+
})),
95+
);
96+
const ExampleSprite = lazy(() =>
97+
import("./examples/sprite/ExampleSprite").then((m) => ({
98+
default: m.ExampleSprite,
99+
})),
100+
);
101+
const ExampleSVGShapes = lazy(() =>
102+
import("./examples/svgShapes/ExampleSVGShapes").then((m) => ({
103+
default: m.ExampleSVGShapes,
104+
})),
105+
);
106+
const ExampleText = lazy(() =>
107+
import("./examples/text/ExampleText").then((m) => ({
108+
default: m.ExampleText,
109+
})),
110+
);
111+
const ExampleTexturePacker = lazy(() =>
112+
import("./examples/texturePacker/ExampleTexturePacker").then((m) => ({
113+
default: m.ExampleTexturePacker,
114+
})),
115+
);
116+
const ExampleTiledMapLoader = lazy(() =>
117+
import("./examples/tiledMapLoader/ExampleTiledMapLoader").then((m) => ({
118+
default: m.ExampleTiledMapLoader,
119+
})),
120+
);
121+
const ExampleUI = lazy(() =>
122+
import("./examples/ui/ExampleUI").then((m) => ({ default: m.ExampleUI })),
123+
);
124+
const ExampleVideo = lazy(() =>
125+
import("./examples/video/ExampleVideo").then((m) => ({
126+
default: m.ExampleVideo,
127+
})),
128+
);
129+
const ExampleWhacAMole = lazy(() =>
130+
import("./examples/whac-a-mole/ExampleWhacAMole").then((m) => ({
131+
default: m.ExampleWhacAMole,
132+
})),
133+
);
42134

43135
const examples: {
44136
label: string;
45137
path: string;
46138
sourceDir: string;
47139
description: string;
48-
component: ReactElement;
140+
component: React.ReactElement;
49141
}[] = [
50142
{
51143
component: <ExampleAseprite />,
@@ -237,15 +329,17 @@ const AceEditorPane = ({ value, mode }: { value: string; mode: string }) => {
237329
const editorRef = useRef<HTMLDivElement>(null);
238330
const editorInstance = useRef<import("ace-builds").Ace.Editor | null>(null);
239331

332+
// biome-ignore lint/correctness/useExhaustiveDependencies: intentionally run once on mount; value/mode are read for initial content only
240333
useEffect(() => {
241334
if (!editorRef.current || editorInstance.current) return;
242-
Promise.all([
243-
import("ace-builds/src-noconflict/ace"),
244-
import("ace-builds/src-noconflict/mode-javascript"),
245-
import("ace-builds/src-noconflict/mode-typescript"),
246-
import("ace-builds/src-noconflict/theme-one_dark"),
247-
])
248-
.then(([aceModule]) => {
335+
// ace must load first — modes and themes depend on the global `ace` variable
336+
import("ace-builds/src-noconflict/ace")
337+
.then(async (aceModule) => {
338+
await Promise.all([
339+
import("ace-builds/src-noconflict/mode-javascript"),
340+
import("ace-builds/src-noconflict/mode-typescript"),
341+
import("ace-builds/src-noconflict/theme-one_dark"),
342+
]);
249343
const aceLib = aceModule.default || aceModule;
250344
if (!editorRef.current) return;
251345
const editor = aceLib.edit(editorRef.current);
@@ -259,6 +353,9 @@ const AceEditorPane = ({ value, mode }: { value: string; mode: string }) => {
259353
tabSize: 2,
260354
useWorker: false,
261355
});
356+
// set the initial content
357+
editor.setValue(value, -1);
358+
editor.session.setMode(`ace/mode/${mode}`);
262359
editorInstance.current = editor;
263360
})
264361
.catch((err) => {
@@ -410,7 +507,7 @@ const router = createHashRouter([
410507
path: `/${example.path}`,
411508
element: (
412509
<ExampleLayout label={example.label} sourceDir={example.sourceDir}>
413-
{example.component}
510+
<Suspense>{example.component}</Suspense>
414511
</ExampleLayout>
415512
),
416513
};

packages/melonjs/CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# Changelog
22

3-
## [18.2.2] (melonJS 2)
3+
## [18.3.0] (melonJS 2)
4+
5+
### Chore
6+
- Minimum Node.js version is now 24.0.0 (Node 18/20 EOL, Node 22 in maintenance)
7+
- CI: upgrade to pnpm/action-setup v5 (Node.js 24 runtime)
48

59
### Fixed
610
- Chore: fix missing README on the npm release

packages/melonjs/package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "melonjs",
3-
"version": "18.2.2",
3+
"version": "18.3.0",
44
"description": "melonJS Game Engine",
55
"homepage": "http://www.melonjs.org/",
66
"type": "module",
@@ -38,7 +38,7 @@
3838
"author": "Olivier Biot (AltByte Pte Ltd)",
3939
"funding": "https://github.com/sponsors/melonjs",
4040
"engines": {
41-
"node": "^20.19.0 || >=22.12.0"
41+
"node": ">=24.0.0"
4242
},
4343
"types": "./build/index.d.ts",
4444
"module": "./build/index.js",
@@ -67,10 +67,10 @@
6767
"serve": "^14.2.6",
6868
"tsconfig": "workspace:^",
6969
"tsx": "^4.21.0",
70-
"type-fest": "^5.4.3",
71-
"typedoc": "^0.28.16",
70+
"type-fest": "^5.5.0",
71+
"typedoc": "^0.28.18",
7272
"typescript": "^5.9.3",
73-
"vite": "^8.0.0",
73+
"vite": "8.0.0",
7474
"vite-plugin-glsl": "^1.5.6"
7575
},
7676
"scripts": {

packages/spine-plugin/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
"author": "AltByte Pte Ltd",
3333
"funding": "https://github.com/sponsors/melonjs",
3434
"engines": {
35-
"node": "^20.19.0 || >=22.12.0"
35+
"node": ">=24.0.0"
3636
},
3737
"exports": {
3838
".": "./build/index.js"

packages/tiled-inflate-plugin/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"author": "Olivier Biot (AltByte Pte Ltd)",
2929
"funding": "https://github.com/sponsors/melonjs",
3030
"engines": {
31-
"node": "^20.19.0 || >=22.12.0"
31+
"node": ">=24.0.0"
3232
},
3333
"types": "./build/index.d.ts",
3434
"exports": {

0 commit comments

Comments
 (0)