Skip to content

Commit

Permalink
Merge pull request #12 from stevent-team/feat/build-separately
Browse files Browse the repository at this point in the history
Separate build command
  • Loading branch information
GRA0007 authored May 22, 2022
2 parents ab47b99 + 1d7bdaa commit e3379e0
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 28 deletions.
38 changes: 34 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,34 @@ yarn add @stevent-team/epoxy

You can also run `npx epoxy --help` to see this information.

#### `epoxy serve` or `epoxy`

```
epoxy <target> [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]
--version Show version number [boolean]
-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>
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
Expand Down Expand Up @@ -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 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; the `epoxy serve` command only build if the flag `--build` is specified.

## 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:
Expand Down
87 changes: 66 additions & 21 deletions index.ts
Original file line number Diff line number Diff line change
@@ -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}`)
})
}
Expand All @@ -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")
Expand All @@ -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 <routeFile>',
'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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
11 changes: 9 additions & 2 deletions src/loadRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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()

Expand Down

0 comments on commit e3379e0

Please sign in to comment.