Invisible 'server' panel doesn't play well with the HMR feature
I've added another panel aside the main one, called 'server' which intended to expose my main panel to outside apps. My folder structure is as follows:
├── js
...
│ ├── lib
...
│ ├── main
...
│ ├── server
│ │ ├── index.html
│ │ └── index.ts
...
src/serve/index.ts code:
import { http } from "../lib/cep/node";
const port = 8088;
const server = http.createServer((req, res) => {
console.log(req);
if (req.url === '/ping') {
res.setHeader('Content-Type', 'text/plain');
res.end('pong');
} else {
res.setHeader('Content-Type', 'text/plain');
res.statusCode = 400;
res.end('METHOD_NOT_ALLOWED');
}
});
server.listen(port, () => {
console.log(`Server is running at http://localhost:${port}`);
console.log(server.listening);
});
The problem:
Each time I save any file HMR is triggered for all the files under src(and I do get that it's expected behavior) causing the listen function to re-run and raise the EADDRINUSE error.
My workaround:
Adding the following line to the triggerHMR function that's inside vite.es.config.ts:
if (panel.name === "server") return;
triggerHMR looks like that right now:
const triggerHMR = () => {
// No built-in way to trigger Vite's HMR reload from outside the root folder
// Workaround will read and save index.html file for each panel to triggger reload
console.log("ExtendScript Change");
cepConfig.panels.map((panel) => {
if (panel.name === "server") return; // this is my addition
const tmpPath = path.join(process.cwd(), "src", "js", panel.mainPath);
if (fs.existsSync(tmpPath)) {
const txt = fs.readFileSync(tmpPath, { encoding: "utf-8" });
fs.writeFileSync(tmpPath, txt, { encoding: "utf-8" });
}
});
};
So ultimately I'm losing the HMR feature for that panel, and each time I want it's code changes to take place I have to rebuild and restart After Effects.. Any ideas how to properly overcome that?
Just found a better solution:
- Canceling the changes to the
triggerHMRfunction that I've mentioned above. - Updated code for the
src/js/server/index.tsfile:
import { http } from "../lib/cep/node";
import { child_process } from "../lib/cep/node";
const port = 8088;
child_process.exec(`lsof -i :${port} | grep LISTEN | awk '{print $2}' | xargs kill`, (error, stdout, stderr) => {
if (error) {
console.error('Error occurred while killing the process:', error);
} else if (stderr) {
console.error('Error occurred while killing the process:', stderr);
} else {
const server = http.createServer((req, res) => {
if (req.url === '/ping') {
res.setHeader('Content-Type', 'text/plain');
res.end('pong');
} else {
res.setHeader('Content-Type', 'text/plain');
res.statusCode = 400;
res.end('METHOD_NOT_ALLOWED');
}
});
server.listen(port, () => {
console.log(`Server is running at http://localhost:${port}`);
});
}
});
Please let me know what you think
I've just used Vite's vite:beforeUpdate to close the server:
server = startServer();
if (import.meta.hot) {
import.meta.hot.on('vite:beforeUpdate', () => {
server.close();
})
}
Seems to work reliably!
I've just used Vite's vite:beforeUpdate to close the server:
server = startServer(); if (import.meta.hot) { import.meta.hot.on('vite:beforeUpdate', () => { server.close(); }) }Seems to work reliably!
Just tried that, cannot get it to work.. do you use native node js http module as I do? and in addition - where do you place that if statement?