diff --git a/packages/core/cli/src/commands/dev.js b/packages/core/cli/src/commands/dev.js index 5eebb59003..b0eefb9978 100644 --- a/packages/core/cli/src/commands/dev.js +++ b/packages/core/cli/src/commands/dev.js @@ -6,16 +6,21 @@ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. * For more information, please refer to: https://www.nocobase.com/agreement. */ - -const chalk = require('chalk'); +const _ = require('lodash'); const { Command } = require('commander'); -const { generatePlugins, run, postCheck, nodeCheck, promptForTs } = require('../util'); +const { generatePlugins, run, postCheck, nodeCheck, promptForTs, isPortReachable } = require('../util'); const { getPortPromise } = require('portfinder'); const chokidar = require('chokidar'); const { uid } = require('@formily/shared'); const path = require('path'); const fs = require('fs'); +function sleep(ms = 1000) { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); +} + /** * * @param {Command} cli @@ -31,6 +36,24 @@ module.exports = (cli) => { .option('--inspect [port]') .allowUnknownOption() .action(async (opts) => { + let subprocess; + const runDevClient = () => { + console.log('starting client', 1 * clientPort); + subprocess = run('umi', ['dev'], { + env: { + ...process.env, + stdio: 'inherit', + shell: true, + PORT: clientPort, + APP_ROOT: `${APP_PACKAGE_ROOT}/client`, + WEBSOCKET_URL: + process.env.WEBSOCKET_URL || + (serverPort ? `ws://localhost:${serverPort}${process.env.WS_PATH}` : undefined), + PROXY_TARGET_URL: + process.env.PROXY_TARGET_URL || (serverPort ? `http://127.0.0.1:${serverPort}` : undefined), + }, + }); + }; const watcher = chokidar.watch('./storage/plugins/**/*', { cwd: process.cwd(), ignored: /(^|[\/\\])\../, // 忽略隐藏文件 @@ -39,15 +62,45 @@ module.exports = (cli) => { }); await fs.promises.mkdir(path.dirname(process.env.WATCH_FILE), { recursive: true }); + let isReady = false; + + const restartClient = _.debounce(async () => { + if (!isReady) return; + generatePlugins(); + if (subprocess) { + console.log('client restarting...'); + subprocess.cancel(); + let i = 0; + while (true) { + ++i; + const result = await isPortReachable(clientPort); + if (!result) { + break; + } + await sleep(500); + if (i > 10) { + break; + } + } + runDevClient(); + await fs.promises.writeFile(process.env.WATCH_FILE, `export const watchId = '${uid()}';`, 'utf-8'); + } + }, 500); watcher + .on('ready', () => { + console.log('Initial scan complete.'); + isReady = true; + }) .on('addDir', async (pathname) => { - generatePlugins(); - await fs.promises.writeFile(process.env.WATCH_FILE, `export const watchId = '${uid()}';`, 'utf-8'); + console.log('addDir....', isReady); + if (!isReady) return; + restartClient(); }) .on('unlinkDir', async (pathname) => { - generatePlugins(); - await fs.promises.writeFile(process.env.WATCH_FILE, `export const watchId = '${uid()}';`, 'utf-8'); + console.log('unlinkDir....', isReady); + if (!isReady) return; + restartClient(); }); promptForTs(); @@ -133,18 +186,7 @@ module.exports = (cli) => { } if (client || !server) { - console.log('starting client', 1 * clientPort); - run('umi', ['dev'], { - env: { - PORT: clientPort, - APP_ROOT: `${APP_PACKAGE_ROOT}/client`, - WEBSOCKET_URL: - process.env.WEBSOCKET_URL || - (serverPort ? `ws://localhost:${serverPort}${process.env.WS_PATH}` : undefined), - PROXY_TARGET_URL: - process.env.PROXY_TARGET_URL || (serverPort ? `http://127.0.0.1:${serverPort}` : undefined), - }, - }); + runDevClient(); } }); }; diff --git a/packages/core/cli/src/commands/start.js b/packages/core/cli/src/commands/start.js index 193336cd63..112c5419b4 100644 --- a/packages/core/cli/src/commands/start.js +++ b/packages/core/cli/src/commands/start.js @@ -6,7 +6,7 @@ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. * For more information, please refer to: https://www.nocobase.com/agreement. */ - +const _ = require('lodash'); const { Command } = require('commander'); const { isDev, run, postCheck, downloadPro, promptForTs } = require('../util'); const { existsSync, rmSync } = require('fs'); @@ -51,10 +51,26 @@ module.exports = (cli) => { depth: 1, // 只监听第一层目录 }); - watcher.on('addDir', async (pathname) => { - console.log('pathname', pathname); + const restart = _.debounce(async () => { + console.log('restarting...'); await run('yarn', ['nocobase', 'pm2-restart']); - }); + }, 500); + + watcher + .on('ready', () => { + console.log('Initial scan complete.'); + isReady = true; + }) + .on('addDir', async (pathname) => { + console.log('addDir....', isReady); + if (!isReady) return; + restart(); + }) + .on('unlinkDir', async (pathname) => { + console.log('unlinkDir....', isReady); + if (!isReady) return; + restart(); + }); if (opts.port) { process.env.APP_PORT = opts.port; diff --git a/packages/core/cli/src/util.js b/packages/core/cli/src/util.js index bbf2f73d56..84bc15e6eb 100644 --- a/packages/core/cli/src/util.js +++ b/packages/core/cli/src/util.js @@ -346,6 +346,7 @@ exports.initEnv = function initEnv() { PLAYWRIGHT_AUTH_FILE: resolve(process.cwd(), 'storage/playwright/.auth/admin.json'), CACHE_DEFAULT_STORE: 'memory', CACHE_MEMORY_MAX: 2000, + BROWSERSLIST_IGNORE_OLD_DATA: true, PLUGIN_STATICS_PATH: '/static/plugins/', LOGGER_BASE_PATH: 'storage/logs', APP_SERVER_BASE_URL: '', diff --git a/packages/core/create-nocobase-app/templates/app/package.json.tpl b/packages/core/create-nocobase-app/templates/app/package.json.tpl index c1beaf112d..8d01ee973b 100644 --- a/packages/core/create-nocobase-app/templates/app/package.json.tpl +++ b/packages/core/create-nocobase-app/templates/app/package.json.tpl @@ -11,6 +11,7 @@ "scripts": { "nocobase": "nocobase", "pm": "nocobase pm", + "pm2": "nocobase pm2", "dev": "nocobase dev", "start": "nocobase start", "clean": "nocobase clean",