Skip to content

Commit 6790b1f

Browse files
committed
further improvements
1 parent fca63fe commit 6790b1f

File tree

11 files changed

+1425
-34
lines changed

11 files changed

+1425
-34
lines changed

.busybox

Lines changed: 1199 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
name: Build and Release
2+
3+
on:
4+
push:
5+
branches: main
6+
tags:
7+
- "v*.*"
8+
9+
jobs:
10+
buildAndRelease:
11+
runs-on: ubuntu-latest
12+
13+
permissions:
14+
# needed for creating a release
15+
contents: write
16+
# needed for pushing docker image
17+
attestations: write
18+
id-token: write
19+
packages: write
20+
21+
steps:
22+
- name: Checkout repository
23+
uses: actions/checkout@v4
24+
25+
- name: Set up Node.js
26+
uses: actions/setup-node@v4
27+
with:
28+
node-version: latest
29+
30+
- name: Install Npm dependencies
31+
run: npm install
32+
33+
- name: Run build script
34+
run: node build.mjs
35+
36+
- name: Zip the out directory
37+
if: startsWith(github.ref, 'refs/tags/v')
38+
run: |
39+
zip -r ${{ github.ref_name }}.zip out
40+
41+
- name: Create GitHub Release
42+
uses: softprops/action-gh-release@v2
43+
if: startsWith(github.ref, 'refs/tags/v')
44+
with:
45+
name: Release ${{ github.ref_name }}
46+
draft: false
47+
prerelease: false
48+
#body_path: CHANGELOG.md
49+
files: |
50+
${{ github.ref_name }}.zip
51+
52+
- name: Set up Docker Buildx
53+
uses: docker/setup-buildx-action@v2
54+
55+
- name: Build Docker image
56+
run: |
57+
docker build -t ghcr.io/${{ github.repository }}:${{ github.ref_name }} .
58+
59+
- name: Log in to GitHub Container Registry
60+
uses: docker/login-action@v3
61+
if: startsWith(github.ref, 'refs/tags/v')
62+
with:
63+
registry: ghcr.io
64+
username: ${{ github.actor }}
65+
password: ${{ secrets.GITHUB_TOKEN }}
66+
67+
- name: Push Docker image
68+
if: startsWith(github.ref, 'refs/tags/v')
69+
run: |
70+
docker push ghcr.io/${{ github.repository }}:${{ github.ref_name }}

.gitignore

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
11
node_modules
2-
3-
dist/*.js
4-
dist/*.css
2+
out

Dockerfile

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
ARG ALPINE_VERSION=3.20
2+
3+
FROM alpine:${ALPINE_VERSION} AS builder
4+
5+
ARG BUSYBOX_VERSION=1.36.1
6+
7+
# Install all dependencies required for compiling busybox
8+
RUN apk add gcc musl-dev make perl
9+
10+
# Download busybox sources
11+
RUN wget https://busybox.net/downloads/busybox-${BUSYBOX_VERSION}.tar.bz2 \
12+
&& tar xf busybox-${BUSYBOX_VERSION}.tar.bz2 \
13+
&& mv /busybox-${BUSYBOX_VERSION} /busybox
14+
15+
WORKDIR /busybox
16+
17+
# Copy the busybox build config (limited to httpd)
18+
COPY .busybox .config
19+
20+
# Compile
21+
RUN make && ./make_single_applets.sh
22+
23+
# Create a non-root user to own the files and run our server
24+
RUN adduser -D static
25+
26+
# Switch to the scratch image
27+
FROM scratch
28+
29+
# port httpd runs on
30+
EXPOSE 3000
31+
32+
# Copy over the user
33+
COPY --from=builder /etc/passwd /etc/passwd
34+
35+
# Copy the static binary
36+
COPY --from=builder /busybox/busybox_HTTPD /busybox-httpd
37+
38+
# Use our non-root user
39+
USER static
40+
WORKDIR /home/static
41+
42+
# Uploads a blank default httpd.conf
43+
# This is only needed in order to set the `-c` argument in this base file
44+
# and save the developer the need to override the CMD line in case they ever
45+
# want to use a httpd.conf
46+
COPY httpd.conf .
47+
48+
# Copy the static website
49+
# Use the .dockerignore file to control what ends up inside the image!
50+
# NOTE: Commented out since this will also copy the .config file
51+
COPY out .
52+
53+
# Run busybox httpd
54+
CMD ["/busybox-httpd", "-f", "-v", "-p", "3000", "-c", "httpd.conf"]

Makefile

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
PORT?=3000
2+
MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
3+
NAME := $(notdir $(patsubst %/,%,$(dir $(MKFILE_PATH))))
4+
5+
build:
6+
npm install
7+
node build.mjs
8+
docker build -t ${NAME}:latest .
9+
@echo "🛠️ Docker build successful"
10+
11+
serve:
12+
npm install
13+
node build.mjs serve
14+
15+
run: build
16+
@docker run --name ${NAME} -dt --rm --init -p ${PORT}:3000 ${NAME}:latest > /dev/null
17+
@echo "🚀 Serving at http://localhost:${PORT}/"
18+
19+
stop:
20+
@docker container stop ${NAME} > /dev/null
21+
@echo "☠️ Container ${NAME} stopped"

README.md

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,46 @@
11
# spa-simple
22
Simple SPA using [esbuild](https://esbuild.github.io/), [jsx-dom](https://www.npmjs.com/package/jsx-dom) and [tailwindcss](https://www.npmjs.com/package/tailwindcss)
33

4-
## Overview
4+
# Requirements
5+
* [NodeJS](https://nodejs.org/) or similar javascript engine
6+
* [Docker](https://www.docker.com/) or similar container engine
7+
8+
# Development
59
All source-files for the app resides in `src` folder.
6-
Where the `app.jsx` file is your main entry point.
7-
Any custom css goes into the `app.css` file. That's all.
10+
Where the `src/main/app.jsx` file is your main entry point for `esbuild`.
11+
Any custom css goes into the `app.css` file and any static resource (e.g. html, ico, etc.) goes into the `src/resource` folder. That's all! 🙂
812

9-
## Getting Started
10-
After installing the dependencies with
13+
# Build App (for Production)
14+
Just run `make` or following commands
1115
```
1216
npm install
17+
node build.mjs
18+
docker build -t ${NAME}:latest .
1319
```
14-
Build and serve the app with
20+
21+
# Serve App (for Development)
22+
Just run `make serve` or following commands
1523
```
24+
npm install
1625
node build.mjs serve
1726
```
18-
All output-files are inside the `dist` folder, which you can see in the browser by navigating to [http://0.0.0.0:8000/](http://0.0.0.0:8000/).
1927

20-
## Build
21-
Build a minified version for production use with
28+
# Run Docker App
29+
Just run `make run` or following commands
2230
```
23-
node build.mjs
31+
docker run --name ${NAME} -dt --rm --init -p ${PORT}:3000 ${NAME}:latest
32+
```
33+
34+
# Stop Docker App
35+
Just run `make stop` or following commands
36+
```
37+
docker container stop ${NAME}
38+
```
39+
40+
# Github Action
41+
Whenever a commit gets pushed to the `main` branch a workflow gets triggered, which builds the app.
42+
You can create a Github release by tagging a specific commit with `v*.*` and push it to the repository.
43+
```
44+
git tag v1.0
45+
git push origin tag v1.0
2446
```

build.mjs

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,55 @@
1-
import * as esbuild from 'esbuild'
1+
import * as esbuild from 'esbuild';
22
import { tailwindPlugin } from 'esbuild-plugin-tailwindcss';
3+
import * as fs from 'fs';
4+
import * as path from 'path';
35

4-
const serve = process.argv[2] === 'serve'
6+
const appJs = 'app.tsx';
7+
const appDir = 'src/main';
8+
const resDir = 'src/resources';
9+
const outDir = 'out';
10+
const serve = process.argv[2] === 'serve';
511

12+
// esbuild config
613
const conf = {
7-
entryPoints: ['src/app.tsx'],
8-
bundle: true,
9-
minify: !serve,
10-
plugins: [
11-
// https://www.npmjs.com/package/esbuild-plugin-tailwindcss
12-
tailwindPlugin(),
13-
],
14-
outdir: 'dist',
15-
}
14+
entryPoints: [`${appDir}/${appJs}`],
15+
bundle: true,
16+
minify: !serve,
17+
plugins: [tailwindPlugin()],
18+
outdir: outDir,
19+
};
1620

21+
// serves the app (node build.mjs serve)
22+
// or builds it for production (node build.mjs)
1723
if (serve) {
18-
// https://esbuild.github.io/api/#live-reload
19-
const ctx = await esbuild.context(conf)
20-
await ctx.watch()
21-
const { host, port } = await ctx.serve({
22-
servedir: conf.outdir,
23-
})
24-
console.log(`http://${host}:${port}/`)
24+
const ctx = await esbuild.context(conf);
25+
await ctx.watch();
26+
const { host, port } = await ctx.serve({
27+
port: 3000,
28+
servedir: conf.outdir,
29+
});
30+
console.log(`🚀 Serving at http://${host}:${port}/`);
2531
} else {
26-
await esbuild.build(conf)
27-
await esbuild.stop()
28-
}
32+
await esbuild.build(conf);
33+
await esbuild.stop();
34+
}
35+
36+
// copy static resources to output dir
37+
(function copyFiles(sourceDir, targetDir) {
38+
fs.readdir(sourceDir, (err, files) => {
39+
if (err) {
40+
console.error('Error reading resource directory:', err);
41+
return;
42+
}
43+
44+
files.forEach((file) => {
45+
const sourceFile = path.join(sourceDir, file);
46+
const targetFile = path.join(targetDir, file);
47+
48+
fs.copyFile(sourceFile, targetFile, (err) => {
49+
if (err) {
50+
console.error('Error copying resource file:', err);
51+
}
52+
});
53+
});
54+
});
55+
})(resDir, outDir);

httpd.conf

Whitespace-only changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)