**What**
This PR introduces experimental Hot Module Replacement (HMR) for the Medusa backend, enabling developers to see code changes reflected immediately without restarting the server. This significantly improves the development experience by reducing iteration time.
### Key Features
- Hot reload support for:
- API Routes
- Workflows & Steps
- Scheduled Jobs
- Event Subscribers
- Modules
- IPC-based architecture: The dev server runs in a child process, communicating with the parent watcher via IPC. When HMR fails, the child process is killed and restarted, ensuring
clean resource cleanup.
- Recovery mechanism: Automatically recovers from broken module states without manual intervention.
- Graceful fallback: When HMR cannot handle a change (e.g., medusa-config.ts, .env), the server restarts completely.
### Architecture
```mermaid
flowchart TB
subgraph Parent["develop.ts (File Watcher)"]
W[Watch Files]
end
subgraph Child["start.ts (HTTP Server)"]
R[reloadResources]
R --> MR[ModuleReloader]
R --> WR[WorkflowReloader]
R --> RR[RouteReloader]
R --> SR[SubscriberReloader]
R --> JR[JobReloader]
end
W -->|"hmr-reload"| R
R -->|"hmr-result"| W
```
### How to enable it
Backend HMR is behind a feature flag. Enable it by setting:
```ts
// medusa-config.ts
module.exports = defineConfig({
featureFlags: {
backend_hmr: true
}
})
```
or
```bash
export MEDUSA_FF_BACKEND_HMR=true
```
or
```
// .env
MEDUSA_FF_BACKEND_HMR=true
```
Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
Co-authored-by: Carlos R. L. Rodrigues <37986729+carlos-r-l-rodrigues@users.noreply.github.com>
119 lines
3.7 KiB
JSON
119 lines
3.7 KiB
JSON
{
|
|
"name": "@medusajs/framework",
|
|
"version": "2.12.1",
|
|
"description": "Framework",
|
|
"main": "dist/index.js",
|
|
"types": "dist/index.d.ts",
|
|
"files": [
|
|
"dist",
|
|
"!dist/**/__tests__",
|
|
"!dist/**/__mocks__",
|
|
"!dist/**/__fixtures__"
|
|
],
|
|
"bin": {
|
|
"medusa-mikro-orm": "./dist/mikro-orm-cli/bin.js"
|
|
},
|
|
"exports": {
|
|
".": "./dist/index.js",
|
|
"./config": "./dist/config/index.js",
|
|
"./caching": "./dist/caching/index.js",
|
|
"./logger": "./dist/logger/index.js",
|
|
"./database": "./dist/database/index.js",
|
|
"./subscribers": "./dist/subscribers/index.js",
|
|
"./workflows": "./dist/workflows/index.js",
|
|
"./links": "./dist/links/index.js",
|
|
"./jobs": "./dist/jobs/index.js",
|
|
"./http": "./dist/http/index.js",
|
|
"./telemetry": "./dist/telemetry/index.js",
|
|
"./feature-flags": "./dist/feature-flags/index.js",
|
|
"./utils": "./dist/utils/index.js",
|
|
"./types": "./dist/types/index.js",
|
|
"./build-tools": "./dist/build-tools/index.js",
|
|
"./orchestration": "./dist/orchestration/index.js",
|
|
"./workflows-sdk": "./dist/workflows-sdk/index.js",
|
|
"./workflows-sdk/composer": "./dist/workflows-sdk/composer.js",
|
|
"./modules-sdk": "./dist/modules-sdk/index.js",
|
|
"./migrations": "./dist/migrations/index.js",
|
|
"./mikro-orm/cli": "./dist/deps/mikro-orm-cli.js",
|
|
"./mikro-orm/core": "./dist/deps/mikro-orm-core.js",
|
|
"./mikro-orm/knex": "./dist/deps/mikro-orm-knex.js",
|
|
"./mikro-orm/migrations": "./dist/deps/mikro-orm-migrations.js",
|
|
"./mikro-orm/postgresql": "./dist/deps/mikro-orm-postgresql.js",
|
|
"./opentelemetry/instrumentation-pg": "./dist/deps/opentelemetry-instrumentation-pg.js",
|
|
"./opentelemetry/sdk-node": "./dist/deps/opentelemetry-sdk-node.js",
|
|
"./opentelemetry/sdk-trace-node": "./dist/deps/opentelemetry-sdk-trace-node.js",
|
|
"./opentelemetry/resources": "./dist/deps/opentelemetry-resources.js",
|
|
"./opentelemetry/api": "./dist/deps/opentelemetry-api.js",
|
|
"./awilix": "./dist/deps/awilix.js",
|
|
"./pg": "./dist/deps/pg.js"
|
|
},
|
|
"engines": {
|
|
"node": ">=20"
|
|
},
|
|
"repository": {
|
|
"type": "git",
|
|
"url": "https://github.com/medusajs/medusa",
|
|
"directory": "packages/core/framework"
|
|
},
|
|
"publishConfig": {
|
|
"access": "public"
|
|
},
|
|
"author": "Medusa",
|
|
"license": "MIT",
|
|
"scripts": {
|
|
"watch": "yarn run -T tsc --watch ",
|
|
"watch:test": "yarn run -T tsc --watch",
|
|
"build": "yarn run -T rimraf dist && yarn run -T tsc --build",
|
|
"test": "../../../node_modules/.bin/jest --bail --forceExit --testPathPattern=src"
|
|
},
|
|
"devDependencies": {
|
|
"@medusajs/cli": "2.12.1"
|
|
},
|
|
"dependencies": {
|
|
"@jercle/yargonaut": "^1.1.5",
|
|
"@medusajs/deps": "2.12.1",
|
|
"@medusajs/modules-sdk": "2.12.1",
|
|
"@medusajs/orchestration": "2.12.1",
|
|
"@medusajs/telemetry": "2.12.1",
|
|
"@medusajs/types": "2.12.1",
|
|
"@medusajs/utils": "2.12.1",
|
|
"@medusajs/workflows-sdk": "2.12.1",
|
|
"@types/express": "^4.17.21",
|
|
"chokidar": "^3.5.3",
|
|
"compression": "^1.8.1",
|
|
"connect-redis": "5.2.0",
|
|
"cookie-parser": "^1.4.6",
|
|
"cors": "^2.8.5",
|
|
"express": "^4.21.0",
|
|
"express-session": "^1.17.3",
|
|
"glob": "11.1.0",
|
|
"jsonwebtoken": "^9.0.2",
|
|
"lodash.memoize": "^4.1.2",
|
|
"morgan": "^1.9.1",
|
|
"path-to-regexp": "^8.2.0",
|
|
"tsconfig-paths": "^4.2.0",
|
|
"zod": "3.25.76",
|
|
"zod-validation-error": "3.5.1"
|
|
},
|
|
"peerDependencies": {
|
|
"@aws-sdk/client-dynamodb": "^3.218.0",
|
|
"@medusajs/cli": "2.12.1",
|
|
"connect-dynamodb": "^3.0.5",
|
|
"ioredis": "^5.4.1"
|
|
},
|
|
"peerDependenciesMeta": {
|
|
"@aws-sdk/client-dynamodb": {
|
|
"optional": true
|
|
},
|
|
"connect-dynamodb": {
|
|
"optional": true
|
|
},
|
|
"ioredis": {
|
|
"optional": true
|
|
},
|
|
"vite": {
|
|
"optional": true
|
|
}
|
|
}
|
|
}
|