From 47c6509bea3a36470b589d388b07167e5b7508fc Mon Sep 17 00:00:00 2001 From: Rishabh Date: Thu, 10 Jun 2021 15:05:08 +0530 Subject: [PATCH] Added experimental start mode script for local development no refs Adds a new `yarn start:dev` command to start portal in development mode that allows development script to be used directly on Ghost site without needing a build for each change. Allows faster development on Portal locally. --- ghost/portal/package.json | 1 + ghost/portal/scripts/load-portal.js | 11 +++ ghost/portal/scripts/start-mode.js | 148 ++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+) create mode 100644 ghost/portal/scripts/load-portal.js create mode 100644 ghost/portal/scripts/start-mode.js diff --git a/ghost/portal/package.json b/ghost/portal/package.json index 7668c3c03a..c638eed270 100644 --- a/ghost/portal/package.json +++ b/ghost/portal/package.json @@ -28,6 +28,7 @@ }, "scripts": { "start": "react-scripts start", + "start:dev": "node ./scripts/start-mode.js", "build": "npm run build:combined && npm run build:bundle", "build:combined": "node ./scripts/build-combined.js", "build:bundle": "webpack --config webpack.config.js", diff --git a/ghost/portal/scripts/load-portal.js b/ghost/portal/scripts/load-portal.js new file mode 100644 index 0000000000..1bc5f30553 --- /dev/null +++ b/ghost/portal/scripts/load-portal.js @@ -0,0 +1,11 @@ +/** Script to load live Portal script chunks for local development */ +function loadScript(src) { + var script = document.createElement('script'); + script.src = src; + document.head.appendChild(script); +} + +loadScript('http://localhost:3000/static/js/bundle.js'); +loadScript('http://localhost:3000/static/js/1.chunk.js'); +loadScript('http://localhost:3000/static/js/0.chunk.js'); +loadScript('http://localhost:3000/static/js/main.chunk.js'); diff --git a/ghost/portal/scripts/start-mode.js b/ghost/portal/scripts/start-mode.js new file mode 100644 index 0000000000..d5962c1ada --- /dev/null +++ b/ghost/portal/scripts/start-mode.js @@ -0,0 +1,148 @@ +const handler = require('serve-handler'); +const http = require('http'); +const chalk = require('chalk'); +const {spawn} = require('child_process'); +const minimist = require('minimist'); + +/* eslint-disable no-console */ +const log = console.log; +/* eslint-enable no-console */ + +let yarnStartProcess; +let stdOutChunks = []; +let stdErrChunks = []; +let startYarnOutput = false; + +const {v, verbose, port = 5000} = minimist(process.argv.slice(2)); +const showVerbose = !!(v || verbose); + +function clearConsole({withHistory = true} = {}) { + if (!withHistory) { + process.stdout.write('\x1Bc'); + return; + } + process.stdout.write( + process.platform === 'win32' ? '\x1B[2J\x1B[0f' : '\x1B[2J\x1B[3J\x1B[H' + ); +} + +function printConfigInstruction() { + const data = { + portal: { + url: `http://localhost:${port}/portal` + } + }; + const stringifedData = JSON.stringify(data, null, 2); + const splitData = stringifedData.split('\n'); + log(); + splitData.forEach((data, idx, arr) => { + if (idx === 0 || idx === arr.length - 1) { + log(chalk.grey(data)); + } else { + log(chalk.bold.whiteBright(data)); + } + }); + log(); +} + +function printInstructions() { + log(); + log(chalk.yellowBright.underline(`Add portal to your local Ghost config`)); + printConfigInstruction(); + log(chalk.cyanBright('='.repeat(50))); + log(); +} + +function onProcessClose(code) { + yarnStartProcess = null; + stdErrChunks = []; + stdOutChunks = []; + log(chalk.redBright.bold.underline(`Please restart the script...\n`)); +} + +function getBuildOptions() { + process.env.FORCE_COLOR = 'true'; + const options = { + shell: true, + env: process.env + }; + if (showVerbose) { + options.stdio = 'inherit'; + } + return options; +} + +function doYarnStart() { + if (yarnStartProcess) { + return; + } + const options = getBuildOptions(); + yarnStartProcess = spawn('BROWSER=none yarn start', options); + + ['SIGINT', 'SIGTERM'].forEach(function (sig) { + yarnStartProcess.on(sig, function () { + yarnStartProcess && yarnStartProcess.exit(); + }); + }); + + yarnStartProcess.on('close', onProcessClose); + + if (!showVerbose) { + yarnStartProcess.stdout.on('data', (data) => { + stdOutChunks.push(data); + printYarnProcessOutput(data); + }); + yarnStartProcess.stderr.on('data', (data) => { + log(Buffer.from(data).toString()); + stdErrChunks.push(data); + }); + } +} + +function printYarnProcessOutput(data) { + const dataStr = Buffer.from(data).toString(); + const dataArr = dataStr.split('\n').filter((d) => { + return /\S/.test(d.trim()); + }); + if (dataArr.find(d => d.includes('Starting the development'))) { + startYarnOutput = true; + log(chalk.yellowBright('Starting the development server...\n')); + return; + } + dataArr.forEach((dataOut) => { + if (startYarnOutput) { + log(dataOut); + } + }); + if (startYarnOutput) { + log(); + } +} + +function startDevServer() { + const server = http.createServer((request, response) => { + return handler(request, response, { + rewrites: [ + {source: '/portal', destination: 'scripts/load-portal.js'} + ], + headers: [ + { + source: '**', + headers: [{ + key: 'Cache-Control', + value: 'no-cache' + }] + } + ] + }); + }); + + server.listen(port, () => { + log(chalk.whiteBright(`Portal dev server is running on http://localhost:${port}`)); + printInstructions(); + doYarnStart(); + }); +} + +clearConsole({withHistory: false}); +startDevServer();