frosty 0.0.149 → 0.0.151
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -117,6 +117,16 @@ module.exports = {
|
|
|
117
117
|
basepath: '/', // (Optional) URL base path for this entry
|
|
118
118
|
}
|
|
119
119
|
},
|
|
120
|
+
workers: { // (Optional) Worker entry points
|
|
121
|
+
myClientWorker: {
|
|
122
|
+
entry: 'src/workers/myClientWorker.js', // Path to worker entry file
|
|
123
|
+
client: true, // true = browser worker (bundled into public/workers/)
|
|
124
|
+
},
|
|
125
|
+
myServerWorker: {
|
|
126
|
+
entry: 'src/workers/myServerWorker.js', // Path to worker entry file
|
|
127
|
+
client: false, // false = server worker (bundled into workers/)
|
|
128
|
+
}
|
|
129
|
+
},
|
|
120
130
|
moduleSuffixes: { // (Optional) Custom module resolution suffixes
|
|
121
131
|
client: ['.browser', '.web', ''],
|
|
122
132
|
server: ['.node', '.server', '.web', '']
|
package/package.json
CHANGED
|
@@ -44,6 +44,7 @@ print_usage() {
|
|
|
44
44
|
echo " -B, --no-build Skip build step"
|
|
45
45
|
echo " -p, --port <port> Specify port for the server (default: 8080)"
|
|
46
46
|
echo " -n, --num-workers <count> Specify number of worker processes"
|
|
47
|
+
echo " -i, --instance-var <name> Specify the env variable name for worker instance index (default: NODE_APP_INSTANCE)"
|
|
47
48
|
echo " -c, --configuration <file> Specify configuration file to use (default: server.config.js)"
|
|
48
49
|
echo " -s, --src <dir> Specify source root directory"
|
|
49
50
|
echo " -o, --output <dir> Specify output directory for build artifacts"
|
|
@@ -66,6 +67,7 @@ while [ $# -gt 0 ]; do
|
|
|
66
67
|
-B|--no-build) NO_BUILD=true; shift ;;
|
|
67
68
|
-p|--port) PORT="$2"; shift 2 ;;
|
|
68
69
|
-n|--num-workers) NUM_WORKERS="$2"; shift 2 ;;
|
|
70
|
+
-i|--instance-var) INSTANCE_VAR="$2"; shift 2 ;;
|
|
69
71
|
-c|--configuration) CONFIG_FILE="$2"; shift 2 ;;
|
|
70
72
|
-s|--src) SRCROOT="$2"; shift 2 ;;
|
|
71
73
|
-o|--output) OUTPUT_DIR="$2"; shift 2 ;;
|
|
@@ -114,6 +116,7 @@ if [ "$NO_BUILD" != "true" ]; then
|
|
|
114
116
|
[ -n "$INPUT_FILE" ] && BUILD_OPTS="$BUILD_OPTS --env INPUT_FILE="$INPUT_FILE""
|
|
115
117
|
[ -n "$SRCROOT" ] && BUILD_OPTS="$BUILD_OPTS --env SRCROOT="$SRCROOT""
|
|
116
118
|
[ -n "$NUM_WORKERS" ] && BUILD_OPTS="$BUILD_OPTS --env NUM_WORKERS="$NUM_WORKERS""
|
|
119
|
+
[ -n "$INSTANCE_VAR" ] && BUILD_OPTS="$BUILD_OPTS --env INSTANCE_VAR="$INSTANCE_VAR""
|
|
117
120
|
[ -n "$PORT" ] && BUILD_OPTS="$BUILD_OPTS --env PORT="$PORT""
|
|
118
121
|
if [ "$WATCH_MODE" = "true" ]; then
|
|
119
122
|
node "$FROSTY_CLI_ROOT/node_modules/webpack-cli/bin/cli.js" $BUILD_OPTS --watch &
|
|
@@ -28,3 +28,4 @@ import { availableParallelism } from 'os';
|
|
|
28
28
|
|
|
29
29
|
export const PORT = process.env.PORT ? parseInt(process.env.PORT) : 8080;
|
|
30
30
|
export const NUM_WORKERS = process.env.NUM_WORKERS ? parseInt(process.env.NUM_WORKERS) : availableParallelism();
|
|
31
|
+
export const INSTANCE_VAR = process.env.INSTANCE_VAR || 'NODE_APP_INSTANCE';
|
|
@@ -31,18 +31,44 @@ import { Server } from '@o2ter/server-js';
|
|
|
31
31
|
import { FrostyRoute } from './route';
|
|
32
32
|
import * as __SERVER__ from '__SERVER__';
|
|
33
33
|
import * as __APPLICATIONS__ from '__APPLICATIONS__';
|
|
34
|
-
import { PORT, NUM_WORKERS } from './env';
|
|
34
|
+
import { PORT, NUM_WORKERS, INSTANCE_VAR } from './env';
|
|
35
35
|
|
|
36
36
|
if (cluster.isPrimary && NUM_WORKERS > 1) {
|
|
37
|
-
console.
|
|
37
|
+
console.info(`Primary ${process.pid} is running`);
|
|
38
38
|
|
|
39
|
-
// Fork workers.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
// Fork workers one by one, waiting for each to come online before starting the next.
|
|
40
|
+
let forked = 0;
|
|
41
|
+
const workerInstances = new Map(); // worker.id -> instance index
|
|
42
|
+
const startedWorkers = new Set(); // worker IDs that have successfully started
|
|
43
|
+
|
|
44
|
+
const spawnWorker = (instance) => {
|
|
45
|
+
const worker = cluster.fork({ [INSTANCE_VAR]: instance });
|
|
46
|
+
workerInstances.set(worker.id, instance);
|
|
47
|
+
return worker;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const forkNext = () => {
|
|
51
|
+
if (forked >= NUM_WORKERS) return;
|
|
52
|
+
const instance = forked++;
|
|
53
|
+
const worker = spawnWorker(instance);
|
|
54
|
+
worker.once('listening', () => {
|
|
55
|
+
startedWorkers.add(worker.id);
|
|
56
|
+
forkNext();
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
forkNext();
|
|
43
60
|
|
|
44
61
|
cluster.on('exit', (worker, code, signal) => {
|
|
45
|
-
console.
|
|
62
|
+
console.info(`Process ${worker.process.pid} exited with code ${code} (${signal})`);
|
|
63
|
+
const instance = workerInstances.get(worker.id);
|
|
64
|
+
workerInstances.delete(worker.id);
|
|
65
|
+
if (startedWorkers.delete(worker.id)) {
|
|
66
|
+
// Worker had started successfully; restart it
|
|
67
|
+
const newWorker = spawnWorker(instance);
|
|
68
|
+
newWorker.once('listening', () => {
|
|
69
|
+
startedWorkers.add(newWorker.id);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
46
72
|
});
|
|
47
73
|
|
|
48
74
|
} else {
|
|
@@ -43,6 +43,7 @@ export default async (env, argv) => {
|
|
|
43
43
|
INPUT_FILE,
|
|
44
44
|
PORT = 8080,
|
|
45
45
|
NUM_WORKERS,
|
|
46
|
+
INSTANCE_VAR,
|
|
46
47
|
} = env;
|
|
47
48
|
|
|
48
49
|
const serverConfig = await (async () => {
|
|
@@ -213,6 +214,16 @@ export default async (env, argv) => {
|
|
|
213
214
|
server: config.moduleSuffixes?.server ?? ['.node', '.server', '.web', ''],
|
|
214
215
|
};
|
|
215
216
|
|
|
217
|
+
const clientWorkers = [];
|
|
218
|
+
const serverWorkers = [];
|
|
219
|
+
for (const [name, { entry, client }] of _.entries(config.workers || {})) {
|
|
220
|
+
if (client) {
|
|
221
|
+
clientWorkers.push({ name, entry });
|
|
222
|
+
} else {
|
|
223
|
+
serverWorkers.push({ name, entry });
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
216
227
|
return [
|
|
217
228
|
..._.map(inputs, ({ entry }, name) => ({
|
|
218
229
|
...webpackConfiguration,
|
|
@@ -249,12 +260,40 @@ export default async (env, argv) => {
|
|
|
249
260
|
]
|
|
250
261
|
}
|
|
251
262
|
})),
|
|
263
|
+
{
|
|
264
|
+
...webpackConfiguration,
|
|
265
|
+
optimization: webpackOptimization({ server: false }),
|
|
266
|
+
plugins: webpackPlugins,
|
|
267
|
+
entry: {
|
|
268
|
+
..._.fromPairs(clientWorkers.map(({ name, entry }) => ([`workers/${name}`, [
|
|
269
|
+
path.resolve(__dirname, 'node_modules/core-js/stable'),
|
|
270
|
+
path.resolve(process.cwd(), entry),
|
|
271
|
+
]]))),
|
|
272
|
+
},
|
|
273
|
+
output: {
|
|
274
|
+
path: path.join(OUTPUT_DIR, 'public'),
|
|
275
|
+
},
|
|
276
|
+
resolve: {
|
|
277
|
+
...webpackConfiguration.resolve,
|
|
278
|
+
extensions: [
|
|
279
|
+
...moduleSuffixes.client.flatMap(x => [`${x}.tsx`, `${x}.jsx`]),
|
|
280
|
+
...moduleSuffixes.client.flatMap(x => [`${x}.ts`, `${x}.mjs`, `${x}.js`]),
|
|
281
|
+
'...'
|
|
282
|
+
],
|
|
283
|
+
},
|
|
284
|
+
module: {
|
|
285
|
+
rules: [
|
|
286
|
+
babelLoaderConfiguration({ server: false }),
|
|
287
|
+
...config.options?.module?.rules ?? [],
|
|
288
|
+
]
|
|
289
|
+
}
|
|
290
|
+
},
|
|
252
291
|
{
|
|
253
292
|
...webpackConfiguration,
|
|
254
293
|
optimization: webpackOptimization({ server: true }),
|
|
255
294
|
plugins: _.compact([
|
|
256
295
|
...webpackPlugins,
|
|
257
|
-
new webpack.EnvironmentPlugin({ PORT, NUM_WORKERS }),
|
|
296
|
+
new webpack.EnvironmentPlugin({ PORT, NUM_WORKERS, INSTANCE_VAR }),
|
|
258
297
|
new webpack.DefinePlugin({
|
|
259
298
|
__applications__: JSON.stringify(_.mapValues(inputs, x => ({
|
|
260
299
|
path: x.basepath,
|
|
@@ -268,6 +307,10 @@ export default async (env, argv) => {
|
|
|
268
307
|
path.resolve(__dirname, 'node_modules/core-js/stable'),
|
|
269
308
|
path.resolve(__dirname, 'src/server/index.js'),
|
|
270
309
|
],
|
|
310
|
+
..._.fromPairs(serverWorkers.map(({ name, entry }) => ([`workers/${name}`, [
|
|
311
|
+
path.resolve(__dirname, 'node_modules/core-js/stable'),
|
|
312
|
+
path.resolve(process.cwd(), entry),
|
|
313
|
+
]]))),
|
|
271
314
|
},
|
|
272
315
|
output: {
|
|
273
316
|
path: OUTPUT_DIR,
|