Paris.js #53
Gérer ses serveurs
de développement et de tests avec PM2
@alexisjanvier
@marmelab
Advanced, production process manager for Node.js
http://pm2.keymetrics.io/
Un projet classique
- une API d'administration (Koa)
- une API public (Koa)
- une interface d'administration (ng-admin)
- une application public (React/Redux)
https://github.com/marmelab/javascript-boilerplate
Développement
- un serveur Node pour les deux API
- un webpack-dev-server pour l'administration
et l'application public
TESTS
- un serveur Node pour les deux API
- un serveur de statics (http-server) pour l'administration
et l'application public
Lancement ""à la mano""
$: ./node_modules/.bin/nodemon --watch api --watch config src/api/index.js
$: ./node_modules/.bin/webpack-dev-server --content-base=build \
--devtool=cheap-module-inline-source-map --hot --inline --quiet --progress
webpack-dev-server
node (nodemon)
bof ...
makefile
webpack.PID:
@./node_modules/.bin/webpack-dev-server \
--content-base=build \
--devtool=cheap-module-inline-source-map \
--hot \
--inline \
--quiet \
--progress \
& echo "$$!" > webpack.PID
stop-frontend-dev: webpack.PID
@kill `cat $<` && rm $<
@echo "Webpack server stopped"
run-api-dev: server.PID
server.PID:
@./node_modules/.bin/nodemon --watch api --watch config api/index.js \
& echo "$$!" > server.PID
stop-api-dev: server.PID
@kill `cat $<` && rm $<
@echo "Node server stopped"
run-dev: run-frontend-dev run-api-dev
stop-dev: stop-frontend-dev stop-api-dev
AVEC PM2
// config/pm2-servers/dev.json
{
"apps" : [{
"name" : "bpm_api-dev",
"script" : "./src/api/index.js",
"watch" : ["./src/api", "./src/isomorphic", "config"],
"instances" : 1,
"autorestart" : true,
"env": {
"NODE_ENV": "development",
}
}, {
"name" : "bpm_frontend-dev",
"script" : "./node_modules/.bin/webpack-dev-server",
"args" : [
"--content-base=build",
"--devtool=cheap-module-inline-source-map",
"--hot",
"--inline",
"--quiet",
"--progress"
],
"instances" : 1,
"autorestart" : true,
"env": {
"NODE_ENV": "development",
}
}]
}
# makefile
run-dev:
@node_modules/.bin/pm2 start ./config/pm2_servers/dev.json
stop-dev:
@node_modules/.bin/pm2 delete ./config/pm2_servers/dev.json
Et beaucoup d'autres features : restart, logs, monitoring, ...
Lancement des tests fonctionnels
// config/pm2-servers/test.json
{
"apps" : [{
"name" : "bpm_api-test",
"script" : "./src/api/index.js",
"exec_mode" : "fork",
"env": {
"NODE_ENV": "test",
"NODE_PORT": 3010
}
},
{
"name" : "bpm_frontend-test",
"script" : "./node_modules/.bin/http-server",
"args" : ["./build", "-p 8081", "--silent"],
"exec_mode" : "fork",
"env": {
"NODE_ENV": "test",
"NODE_PORT": 3020
}
}]
}
# Makefile
test-frontend-functional: reset-test-database
NODE_ENV=test make load-fixtures
@make build-test
@node_modules/.bin/pm2 start ./config/pm2_servers/test.json
@node_modules/.bin/nightwatch --config="./e2e/frontend/nightwatch.json"
@node_modules/.bin/pm2 delete ./config/pm2_servers/test.json
... et une API pour utiliser pm2 directement dans les tests
import pm2 from 'pm2';
pm2.connect((err) => {
if (err) {
console.error(err);
process.exit(2);
}
pm2.start({
script : 'app.js', // Script to be run
exec_mode : 'cluster', // Allow your app to be clustered
instances : 4, // Optional: Scale your app by 4
max_memory_restart : '100M' // Optional: Restart your app if it reaches 100Mo
},(err, apps) => {
pm2.disconnect();
});
});
global Vs project
# ~/.pm2
.
├── conf.js
├── dump.pm2
├── logs
│ ├── bpm-api-dev-error-0.log
│ ├── bpm-api-dev-out-0.log
│ ├── bpm-frontend-dev-error-1.log
│ └── bpm-frontend-dev-out-1.log
├── module_conf.json
├── pids
├── pm2.log
├── pm2.pid
├── pub.sock
├── rpc.sock
└── touch
2 directories, 12 files
$: PM2_HOME='.myProject' ./node_modules/.bin/pm2 start ./config/pm2_servers/test.json