NPM Module
Whistle can be integrated into your project as an NPM module. It's strongly recommended that you run Whistle in a separate child process to avoid interfering with the main process and to facilitate management.
Install dependencies
npm i --save whistle pfork
Standalone Service Mode
- Create the Whistle startup script (
/lib/whistle.js
):jsconst startWhistle = require('whistle'); module.exports = (options, callback) => { startWhistle({ port: options.port }, () => callback()); };
For startup parameters such as disabling plugins, customizing plugin directories, and modifying storage directories, refer to: https://github.com/avwo/whistle/blob/master/index.d.ts
- Start the Whistle process code:js
const { fork } = require('pfork'); const path = require('path'); const script = path.join(__dirname, './whistle.js'); const options = { script, port: 8080, }; const forkWhistle = (retry) => { fork(options, (err, result, child) => { if (err) { // Initialization error, exit the service directly if (!retry) { throw err; } // Retry error, delay 100 milliseconds before retrying return setTimeout(forkWhistle, 100); } // Child process automatically retry after exit child.once('close', () => forkWhistle(true)); }); }; forkWhistle();
Starting Whistle this way is the same as starting Whistle independently or as a Whistle client from the command line.
Internal Service Mode (Recommended)
- Create the Whistle startup script (
/lib/whistle.js
):jsconst startWhistle = require('whistle'); const http = require('http'); let curPort = 30013; const getPort = (callback) => { const server = http.createServer(); server.on('error', () => { if (++curPort % 5 === 0) { ++curPort; } getPort(callback); }); server.listen(curPort, '127.0.0.1', () => { server.removeAllListeners(); server.close(() => callback(curPort)); }); }; module.exports = (options, callback) => { // Get a random port getPort((port) => { // Start at a random port Whistle, after successful startup, passes startup parameters to the parent process. const options = { port, host: '127.0.0.1', }; startWhistle(options, () => callback(options)); }); };
Reference: https://github.com/Tencent/nohost/blob/master/lib/whistle.js
Whistle will
- Start the Whistle process method (
/lib/fork.js
):jsconst { fork } = require('pfork'); const path = require('path'); const script = path.join(__dirname, './whistle.js'); const options = { script, }; module.exports = () => { return new Promise((resolve, reject) => { fork(options, (err, result) => { if (err) { return reject(err); } resolve(result); }); }); };
Reference: https://github.com/Tencent/nohost/blob/master/lib/main/whistleMgr.js
- Forward the specified request in the project to Whistle:js
const { createServer } = require('http'); const forkWhistle = require('./fork'); const server = createServer(async (req, res) => { try { const { host, port } = await forkWhistle(); // Forward the request to host, port } catch (e) { // handle errors } }); server.listen(8010);
Reference: https://github.com/Tencent/nohost/blob/master/lib/index.js#L160
Started in this way Whistle uses a random port and is started on demand. External requests do not access Whistle directly but are forwarded through the project's services. This provides more flexibility and is the recommended method for project integration.
Related Documentation
- For all Whistle startup parameters, see the source code type definitions: https://github.com/avwo/whistle/blob/master/index.d.ts
- pfork: https://github.com/avwo/pfork
- Complete example: https://github.com/Tencent/nohost