mirror of
https://github.com/MichMich/MagicMirror.git
synced 2025-12-12 01:42:19 +00:00
## Description
This PR adds a new `server:watch` script that runs MagicMirror² in
server-only mode with automatic restart and browser reload capabilities.
Particularly helpful for:
- **Developers** who need to see changes immediately without manual
restarts.
- **Users setting up their mirror** who make many changes to `config.js`
or `custom.css` and need quick feedback.
### What it does
When you run `npm run server:watch`, the watcher monitors files you
specify in `config.watchTargets`. Whenever a monitored file changes:
1. The server automatically restarts
2. Waits for the port to become available
3. Sends a reload notification to all connected browsers via Socket.io
4. Browsers automatically refresh to show the changes
This creates a seamless development experience where you can edit code,
save, and see the results within seconds.
### Implementation highlights
**Zero dependencies:** Uses only Node.js built-ins (`fs.watch`,
`child_process.spawn`, `net`, `http`) - no nodemon or external watchers
needed.
**Smart file watching:** Monitors parent directories instead of files
directly to handle atomic writes from modern editors (VSCode, etc.) that
create temporary files during save operations.
**Port management:** Waits for the old server instance to fully release
the port before starting a new one, preventing "port already in use"
errors.
### Configuration
Users explicitly define which files to monitor in their `config.js`:
```js
let config = {
watchTargets: [
"config/config.js",
"css/custom.css",
"modules/MMM-MyModule/MMM-MyModule.js",
"modules/MMM-MyModule/node_helper.js"
],
// ... rest of config
};
```
This explicit approach keeps the implementation simple (~260 lines)
while giving users full control over what triggers restarts. If
`watchTargets` is empty or undefined, the watcher starts but monitors
nothing, logging a clear warning message.
---
**Note:** This PR description has been updated to reflect the final
implementation. During the review process, we refined the approach
multiple times based on feedback.
---------
Co-authored-by: Jboucly <contact@jboucly.fr>
Co-authored-by: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com>
129 lines
4.2 KiB
JSON
129 lines
4.2 KiB
JSON
{
|
|
"name": "magicmirror",
|
|
"version": "2.34.0-develop",
|
|
"description": "The open source modular smart mirror platform.",
|
|
"keywords": [
|
|
"magic mirror",
|
|
"magicmirror",
|
|
"smart mirror",
|
|
"mirror UI",
|
|
"modular"
|
|
],
|
|
"homepage": "https://magicmirror.builders",
|
|
"bugs": {
|
|
"url": "https://github.com/MagicMirrorOrg/MagicMirror/issues"
|
|
},
|
|
"repository": {
|
|
"type": "git",
|
|
"url": "https://github.com/MagicMirrorOrg/MagicMirror"
|
|
},
|
|
"license": "MIT",
|
|
"author": "Michael Teeuw",
|
|
"contributors": [
|
|
"https://github.com/MagicMirrorOrg/MagicMirror/graphs/contributors"
|
|
],
|
|
"type": "commonjs",
|
|
"imports": {
|
|
"#module_functions": {
|
|
"default": "./js/module_functions.js"
|
|
},
|
|
"#server_functions": {
|
|
"default": "./js/server_functions.js"
|
|
}
|
|
},
|
|
"main": "js/electron.js",
|
|
"scripts": {
|
|
"config:check": "node js/check_config.js",
|
|
"postinstall": "git clean -df fonts vendor",
|
|
"install-mm": "npm install --no-audit --no-fund --no-update-notifier --only=prod --omit=dev",
|
|
"install-mm:dev": "npm install --no-audit --no-fund --no-update-notifier",
|
|
"lint:css": "stylelint 'css/main.css' 'css/roboto.css' 'css/font-awesome.css' 'modules/default/**/*.css' --fix",
|
|
"lint:js": "eslint --fix",
|
|
"lint:markdown": "markdownlint-cli2 . --fix",
|
|
"lint:prettier": "prettier . --write",
|
|
"prepare": "[ -f node_modules/.bin/husky ] && husky || echo no husky installed.",
|
|
"server": "node ./serveronly",
|
|
"server:watch": "node ./serveronly/watcher.js",
|
|
"start": "node --run start:x11",
|
|
"start:dev": "node --run start:x11 -- dev",
|
|
"start:wayland": "WAYLAND_DISPLAY=\"${WAYLAND_DISPLAY:=wayland-1}\" ./node_modules/.bin/electron js/electron.js --enable-features=UseOzonePlatform --ozone-platform=wayland",
|
|
"start:wayland:dev": "node --run start:wayland -- dev",
|
|
"start:windows": ".\\node_modules\\.bin\\electron js\\electron.js",
|
|
"start:windows:dev": "node --run start:windows -- dev",
|
|
"start:x11": "DISPLAY=\"${DISPLAY:=:0}\" ./node_modules/.bin/electron js/electron.js",
|
|
"start:x11:dev": "node --run start:x11 -- dev",
|
|
"test": "NODE_ENV=test jest -i --forceExit",
|
|
"test:calendar": "node ./modules/default/calendar/debug.js",
|
|
"test:coverage": "NODE_ENV=test jest --coverage -i --verbose false --forceExit",
|
|
"test:css": "stylelint 'css/main.css' 'css/roboto.css' 'css/font-awesome.css' 'modules/default/**/*.css'",
|
|
"test:e2e": "NODE_ENV=test jest --selectProjects e2e -i --forceExit",
|
|
"test:electron": "NODE_ENV=test jest --selectProjects electron -i --forceExit",
|
|
"test:js": "eslint",
|
|
"test:markdown": "markdownlint-cli2 .",
|
|
"test:prettier": "prettier . --check",
|
|
"test:spelling": "cspell . --gitignore",
|
|
"test:unit": "NODE_ENV=test jest --selectProjects unit"
|
|
},
|
|
"lint-staged": {
|
|
"*": "prettier --ignore-unknown --write",
|
|
"*.js": "eslint --fix",
|
|
"*.css": "stylelint --fix"
|
|
},
|
|
"overrides": {
|
|
"parse5": "7.3.0"
|
|
},
|
|
"dependencies": {
|
|
"@fontsource/roboto": "^5.2.8",
|
|
"@fontsource/roboto-condensed": "^5.2.8",
|
|
"@fortawesome/fontawesome-free": "^7.1.0",
|
|
"ajv": "^8.17.1",
|
|
"animate.css": "^4.1.1",
|
|
"console-stamp": "^3.1.2",
|
|
"croner": "^9.1.0",
|
|
"envsub": "^4.1.0",
|
|
"eslint": "^9.38.0",
|
|
"express": "^5.1.0",
|
|
"feedme": "^2.0.2",
|
|
"helmet": "^8.1.0",
|
|
"html-to-text": "^9.0.5",
|
|
"iconv-lite": "^0.7.0",
|
|
"ipaddr.js": "^2.2.0",
|
|
"moment": "^2.30.1",
|
|
"moment-timezone": "^0.6.0",
|
|
"node-ical": "^0.22.0",
|
|
"nunjucks": "^3.2.4",
|
|
"pm2": "^6.0.13",
|
|
"socket.io": "^4.8.1",
|
|
"suncalc": "^1.9.0",
|
|
"systeminformation": "^5.27.11",
|
|
"undici": "^7.16.0",
|
|
"weathericons": "^2.1.0"
|
|
},
|
|
"devDependencies": {
|
|
"@stylistic/eslint-plugin": "^5.5.0",
|
|
"cspell": "^9.2.1",
|
|
"eslint-plugin-import-x": "^4.16.1",
|
|
"eslint-plugin-jest": "^29.0.1",
|
|
"eslint-plugin-jsdoc": "^61.1.5",
|
|
"eslint-plugin-package-json": "^0.57.0",
|
|
"express-basic-auth": "^1.2.1",
|
|
"husky": "^9.1.7",
|
|
"jest": "^30.2.0",
|
|
"jsdom": "27.0.0",
|
|
"lint-staged": "^16.2.4",
|
|
"markdownlint-cli2": "^0.18.1",
|
|
"playwright": "^1.56.1",
|
|
"prettier": "^3.6.2",
|
|
"prettier-plugin-jinja-template": "^2.1.0",
|
|
"stylelint": "^16.25.0",
|
|
"stylelint-config-standard": "^39.0.1",
|
|
"stylelint-prettier": "^5.0.3"
|
|
},
|
|
"optionalDependencies": {
|
|
"electron": "^38.3.0"
|
|
},
|
|
"engines": {
|
|
"node": ">=22.20.0 <23 || >=24"
|
|
}
|
|
}
|