@digicms/cms
Version:
An open source headless CMS solution to create and manage your own API. It provides a powerful dashboard and features to make your life easier. Databases supported: MySQL, MariaDB, PostgreSQL, SQLite
200 lines (176 loc) • 5.07 kB
JavaScript
'use strict';
const path = require('path');
const cluster = require('cluster');
const fs = require('fs-extra');
const chokidar = require('chokidar');
const execa = require('execa');
const { getOr } = require('lodash/fp');
const { joinBy } = require('@strapi/utils');
const tsUtils = require('@strapi/typescript-utils');
const loadConfiguration = require('../core/app-configuration');
const strapi = require('../index');
const { buildTypeScript, buildAdmin } = require('./builders');
/**
* `$ strapi develop`
*
*/
module.exports = async ({ build, watchAdmin, polling, browser }) => {
const appDir = process.cwd();
const isTSProject = await tsUtils.isUsingTypeScript(appDir);
const outDir = await tsUtils.resolveOutDir(appDir);
const distDir = isTSProject ? outDir : appDir;
try {
if (cluster.isMaster || cluster.isPrimary) {
return primaryProcess({
distDir,
appDir,
build,
browser,
isTSProject,
watchAdmin,
});
}
if (cluster.isWorker) {
return workerProcess({ appDir, distDir, watchAdmin, polling, isTSProject });
}
} catch (e) {
console.error(e);
process.exit(1);
}
};
const primaryProcess = async ({ distDir, appDir, build, isTSProject, watchAdmin, browser }) => {
if (isTSProject) {
await buildTypeScript({ srcDir: appDir, distDir, watch: false });
}
const config = loadConfiguration({ appDir, distDir });
const serveAdminPanel = getOr(true, 'admin.serveAdminPanel')(config);
const buildExists = fs.existsSync(path.join(distDir, 'build'));
// Don't run the build process if the admin is in watch mode
if (build && !watchAdmin && serveAdminPanel && !buildExists) {
try {
await buildAdmin({
buildDestDir: distDir,
forceBuild: false,
optimization: false,
srcDir: appDir,
});
} catch (err) {
process.exit(1);
}
}
if (watchAdmin) {
try {
execa('npm', ['run', '-s', 'strapi', 'watch-admin', '--', '--browser', browser], {
stdio: 'inherit',
});
} catch (err) {
process.exit(1);
}
}
cluster.on('message', async (worker, message) => {
switch (message) {
case 'reload':
if (isTSProject) {
await buildTypeScript({ srcDir: appDir, distDir, watch: false });
}
console.info('The server is restarting\n');
worker.send('kill');
break;
case 'killed':
cluster.fork();
break;
case 'stop':
process.exit(1);
break;
default: {
break;
}
}
});
cluster.fork();
};
const workerProcess = ({ appDir, distDir, watchAdmin, polling, isTSProject }) => {
const strapiInstance = strapi({
distDir,
autoReload: true,
serveAdminPanel: !watchAdmin,
});
const adminWatchIgnoreFiles = strapiInstance.config.get('admin.watchIgnoreFiles', []);
watchFileChanges({
appDir,
strapiInstance,
watchIgnoreFiles: adminWatchIgnoreFiles,
polling,
isTSProject,
});
process.on('message', async (message) => {
switch (message) {
case 'kill': {
await strapiInstance.destroy();
process.send('killed');
process.exit();
break;
}
default: {
break;
}
// Do nothing.
}
});
return strapiInstance.start();
};
/**
* Init file watching to auto restart strapi app
* @param {Object} options - Options object
* @param {string} options.appDir - This is the path where the app is located, the watcher will watch the files under this folder
* @param {Strapi} options.strapi - Strapi instance
* @param {array} options.watchIgnoreFiles - Array of custom file paths that should not be watched
*/
function watchFileChanges({ appDir, strapiInstance, watchIgnoreFiles, polling }) {
const restart = async () => {
if (strapiInstance.reload.isWatching && !strapiInstance.reload.isReloading) {
strapiInstance.reload.isReloading = true;
strapiInstance.reload();
}
};
const watcher = chokidar.watch(appDir, {
ignoreInitial: true,
usePolling: polling,
ignored: [
/(^|[/\\])\../, // dot files
/tmp/,
'**/src/admin/**',
'**/src/plugins/**/admin/**',
'**/dist/src/plugins/test/admin/**',
'**/documentation',
'**/documentation/**',
'**/node_modules',
'**/node_modules/**',
'**/plugins.json',
'**/build',
'**/build/**',
'**/index.html',
'**/public',
'**/public/**',
strapiInstance.dirs.static.public,
joinBy('/', strapiInstance.dirs.static.public, '**'),
'**/*.db*',
'**/exports/**',
'**/dist/**',
...watchIgnoreFiles,
],
});
watcher
.on('add', (path) => {
strapiInstance.log.info(`File created: ${path}`);
restart();
})
.on('change', (path) => {
strapiInstance.log.info(`File changed: ${path}`);
restart();
})
.on('unlink', (path) => {
strapiInstance.log.info(`File deleted: ${path}`);
restart();
});
}