From 5735d0f80251745b75a873f9b0e8161f3450a60c Mon Sep 17 00:00:00 2001 From: Ben Grant Date: Fri, 20 May 2022 15:53:27 +1000 Subject: [PATCH 1/6] Create github workflows script --- .github/workflows/main.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..7e6d858 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,29 @@ +name: main + +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 16 + - run: yarn install --immutable + - run: yarn build + name: Build + # TODO: Testing + + publish: + if: github.ref == 'refs/heads/main' + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 16 + - run: echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_AUTH_TOKEN }}" > ~/.npmrc + - name: Publish + run: yarn publish --access public From 204595ce161eb690eae3c5f120f5ddcd27779885 Mon Sep 17 00:00:00 2001 From: Ben Grant Date: Fri, 20 May 2022 16:02:39 +1000 Subject: [PATCH 2/6] Configure build command to build helpers as well --- .github/workflows/main.yml | 2 +- package.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7e6d858..762008d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,7 +11,7 @@ jobs: with: node-version: 16 - run: yarn install --immutable - - run: yarn build + - run: yarn build:ci name: Build # TODO: Testing diff --git a/package.json b/package.json index 1cec169..c07d562 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,8 @@ "./helpers": "./helpers/dist/index.js" }, "scripts": { - "build": "parcel build" + "build": "parcel build", + "build:ci": "yarn build && yarn --cwd helpers build" }, "devDependencies": { "@types/express": "^4.17.13", From ab47b9933dfa307a05ed5104bc307d556fde5654 Mon Sep 17 00:00:00 2001 From: Ben Grant Date: Fri, 20 May 2022 16:06:20 +1000 Subject: [PATCH 3/6] Yarn install in helpers --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 762008d..27f0fbf 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,7 +10,7 @@ jobs: - uses: actions/setup-node@v3 with: node-version: 16 - - run: yarn install --immutable + - run: yarn install --immutable && yarn --cwd helpers install --immutable - run: yarn build:ci name: Build # TODO: Testing From 284fe241bc100098609439960357d271b932ea42 Mon Sep 17 00:00:00 2001 From: Ben Grant Date: Fri, 20 May 2022 16:53:06 +1000 Subject: [PATCH 4/6] Add build command that builds epoxy routes separately, and a flag --- index.ts | 87 +++++++++++++++++++++++++++++++++++------------ package.json | 2 +- src/loadRoutes.ts | 11 ++++-- 3 files changed, 76 insertions(+), 24 deletions(-) diff --git a/index.ts b/index.ts index e69df2d..c233136 100644 --- a/index.ts +++ b/index.ts @@ -1,16 +1,17 @@ #!/usr/bin/env node import yargs from 'yargs' import path from 'path' +import { Parcel } from '@parcel/core' import loadRoutes from './src/loadRoutes' import startServer, { Routes } from './src/server' -const serve = async ({ target, routeFile, host, port, index }) => { +const serve = async ({ target, routeFile, host, port, index, build }) => { // Load routes let routes: Routes = {} if (routeFile) { const resolvedRoutes = path.resolve(routeFile) - routes = await loadRoutes(resolvedRoutes).catch(e => { + routes = await loadRoutes(resolvedRoutes, build).catch(e => { throw new Error(`Failed to load routes file "${resolvedRoutes}": ${e}`) }) } @@ -32,6 +33,31 @@ const serve = async ({ target, routeFile, host, port, index }) => { }) } +const build = async ({ routeFile, outputDir }) => { + // Setup bundler + const bundler = new Parcel({ + entries: routeFile, + defaultConfig: '@parcel/config-default', + mode: 'production', + shouldDisableCache: true, + targets: { + 'main': { + context: 'node', + distDir: outputDir, + engines: { + node: ">=10" + }, + scopeHoist: false, + optimize: false, + } + } + }) + + // Build routes configuration + const { buildTime } = await bundler.run() + console.log(`✨ Built routes file in ${buildTime}ms`) +} + // Use yargs to parse command line options yargs .scriptName("epoxy") @@ -41,25 +67,44 @@ yargs 'Serve the provided static folder', yargs => yargs .positional('target', { describe: 'Path to static directory', require: true }) - .positional('routeFile', { describe: 'Path to router script' }), + .positional('routeFile', { describe: 'Path to cjs router script (can use ES6 with --build option)' }) + .option('port', { + alias: 'p', + type: 'string', + description: 'port to use for http server', + default: 8080, + }) + .option('host', { + alias: 'h', + type: 'string', + description: 'host to use for http server', + default: '0.0.0.0', + }) + .option('index', { + alias: 'i', + type: 'string', + description: 'path to index html inside of target', + default: 'index.html', + }) + .option('build', { + alias: 'b', + type: 'boolean', + description: 'build routes file in memory', + default: false, + }), serve ) - .option('port', { - alias: 'p', - type: 'string', - description: 'port to use for http server', - default: 8080, - }) - .option('host', { - alias: 'h', - type: 'string', - description: 'host to use for http server', - default: '0.0.0.0', - }) - .option('index', { - alias: 'i', - type: 'string', - description: 'path to index html inside of target', - default: 'index.html', - }) + .command( + 'build ', + 'Build a routes file', + yargs => yargs + .positional('routeFile', { describe: 'Path to ES6 router script', require: true }) + .option('outputDir', { + alias: 'o', + type: 'string', + description: 'folder to output built routes file', + default: 'dist', + }), + build + ) .argv diff --git a/package.json b/package.json index c07d562..79bf787 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@stevent-team/epoxy", - "version": "1.1.3", + "version": "2.0.0", "description": "Lightweight server-side per-route html injection", "keywords": [ "epoxy", diff --git a/src/loadRoutes.ts b/src/loadRoutes.ts index f41d883..9384345 100644 --- a/src/loadRoutes.ts +++ b/src/loadRoutes.ts @@ -3,7 +3,14 @@ import { MemoryFS } from '@parcel/fs' import requireFromString from 'require-from-string' // Compile the routes file, then import it -const loadRoutes = async (routeFile: string) => { +const loadRoutes = async (routeFile: string, build: boolean) => { + // Just import a cjs file + if (!build) { + console.log(`🎁 Using route file "${routeFile}"`) + const module = await import(routeFile) + return module.default?.default ?? module.default + } + // Setup bundler using memory file system const workerFarm = createWorkerFarm() const outputFS = new MemoryFS(workerFarm) @@ -29,7 +36,7 @@ const loadRoutes = async (routeFile: string) => { // Build routes configuration const { bundleGraph, buildTime } = await bundler.run() - console.log(`✨ Built routes file in ${buildTime}ms`) + console.log(`✨ Built routes file to memory in ${buildTime}ms`) const [bundle] = bundleGraph.getBundles() From b3f0909bdeb50bcf1a0cf2307ab48883ad481b6b Mon Sep 17 00:00:00 2001 From: Ben Grant Date: Fri, 20 May 2022 16:59:52 +1000 Subject: [PATCH 5/6] Update readme with build command info --- README.md | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4b91434..4103d13 100644 --- a/README.md +++ b/README.md @@ -19,11 +19,13 @@ yarn add @stevent-team/epoxy You can also run `npx epoxy --help` to see this information. +#### `epoxy serve` or `epoxy` + ``` epoxy [routeFile] [options] target Path to static directory -routeFile Path to router script +routeFile Path to cjs router script (can use ES6 with --build option) Options: --help Show help [boolean] @@ -31,6 +33,20 @@ Options: -p, --port port to use for http server [string] [default: 8080] -h, --host host to use for http server [string] [default: "0.0.0.0"] -i, --index path to index html inside of target [string] [default: "index.html"] + -b, --build build routes file in memory [boolean] [default: false] +``` + +#### `epoxy build` + +``` +epoxy build + +routeFile Path to ES6 router script + +Options: + --help Show help [boolean] + --version Show version number [boolean] + -o, --outputDir folder to output built routes file [string] [default: "dist"] ``` ## Example @@ -84,20 +100,34 @@ export default { Then serve your static directory and dynamic routes! ```bash -epoxy ./dist ./routes.js +epoxy ./dist ./routes.js --build ``` or setup an npm script -```js +```json // package.json { "scripts": { - "serve": "epoxy ./dist ./routes.js" + "serve": "epoxy ./dist ./routes.js --build" } } ``` +If you have a deployment that will need to start and stop your Epoxy server often, such as an automatically scaled deployment like Google App Engine, then you can prebuild the routes file so it doesn't have to build before every start: + +```json +// package.json +{ + "scripts": { + "build": "epoxy ./routes.js", + "serve": "epoxy ./dist ./dist/routes.js" + } +} +``` + +Alternatively, you could also write your routes file in CommonJS so it doesn't require building. + ## API Your route handler will be built by Epoxy using Parcel when Epoxy is started. It also has to export a default object with the structure: From 1d7bdaa1a7fb2020def82a4d627fe4169aa00d8f Mon Sep 17 00:00:00 2001 From: Ben Grant Date: Sun, 22 May 2022 13:09:47 +1000 Subject: [PATCH 6/6] Fix command in docs --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4103d13..0d6655f 100644 --- a/README.md +++ b/README.md @@ -120,13 +120,13 @@ If you have a deployment that will need to start and stop your Epoxy server ofte // package.json { "scripts": { - "build": "epoxy ./routes.js", + "build": "epoxy build ./routes.js", "serve": "epoxy ./dist ./dist/routes.js" } } ``` -Alternatively, you could also write your routes file in CommonJS so it doesn't require building. +Alternatively, you could also write your routes file in CommonJS so it doesn't require building; the `epoxy serve` command only build if the flag `--build` is specified. ## API