Skip to content

Commit

Permalink
Merge pull request #11 from icefoganalytics/issue-6/add-minimal-front…
Browse files Browse the repository at this point in the history
…-end-dockerize-setup

Add Minimal Front-End Dockerize Setup
  • Loading branch information
klondikemarlen authored Jan 15, 2024
2 parents fdb255e + c2ca2bb commit 01d0770
Show file tree
Hide file tree
Showing 37 changed files with 6,168 additions and 38 deletions.
20 changes: 9 additions & 11 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,18 @@ COPY api ./
RUN npm run build

# Stage 2 - web build - requires development environment to install vue-cli-service
# FROM base-node as web-build-stage
FROM base-node as web-build-stage

# ENV NODE_ENV=development
ENV NODE_ENV=development

# WORKDIR /usr/src/web
WORKDIR /usr/src/web

# COPY web/package*.json ./
# COPY web/tsconfig*.json ./
# COPY web/babel.config.js ./
# RUN npm install
COPY web/package*.json ./
COPY web/tsconfig*.json ./
COPY web/vite.config.js ./
RUN npm install

# COPY web ./
COPY web ./

# Switching to production mode for build environment.
ENV NODE_ENV=production
Expand All @@ -55,9 +55,7 @@ COPY --from=api-build-stage --chown=node:node /usr/src/api/package*.json ./
RUN npm install && npm cache clean --force --loglevel=error

COPY --from=api-build-stage --chown=node:node /usr/src/api/dist/src ./dist
# Replace with web build once it's ready
COPY --from=api-build-stage --chown=node:node /usr/src/api/src/web ./dist/web
# COPY --from=web-build-stage --chown=node:node /usr/src/web/dist ./dist/web
COPY --from=web-build-stage --chown=node:node /usr/src/web/dist ./dist/web

RUN echo "RELEASE_TAG=${RELEASE_TAG}" >> VERSION
RUN echo "GIT_COMMIT_HASH=${GIT_COMMIT_HASH}" >> VERSION
Expand Down
1 change: 1 addition & 0 deletions api/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"name": "internal-data-portal",
"private": true,
"version": "0.1.0",
"description": "DataPortal is envisioned as a comprehensive data management system, designed to facilitate easy access, manipulation, and visualization of datasets.",
"main": "src/server.js",
Expand Down
6 changes: 3 additions & 3 deletions api/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import cors from "cors"
import path from "path"
import helmet from "helmet"

import { VUE_APP_FRONTEND_URL } from "@/config"
import { FRONTEND_URL } from "@/config"
import router from "@/router"

export const app = express()
Expand Down Expand Up @@ -31,7 +31,7 @@ app.use(
// very basic CORS setup
app.use(
cors({
origin: VUE_APP_FRONTEND_URL,
origin: FRONTEND_URL,
optionsSuccessStatus: 200,
credentials: true,
})
Expand All @@ -44,7 +44,7 @@ app.use(express.static(path.join(__dirname, "web")))

// if no other routes match, just send the front-end
app.use((req: Request, res: Response) => {
res.sendFile(path.join(__dirname, "web/index.html"))
res.status(404).sendFile(path.join(__dirname, "web/index.html"))
})

export default app
12 changes: 7 additions & 5 deletions api/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import path from "path"
import * as dotenv from "dotenv"

import { stripTrailingSlash } from "@/utils/strip-trailing-slash"

export const NODE_ENV = process.env.NODE_ENV || "development"

let dotEnvPath
Expand All @@ -23,12 +25,12 @@ if (process.env.NODE_ENV !== "test") {

export const API_PORT = process.env.API_PORT || "3000"

export const VUE_APP_FRONTEND_URL = process.env.VUE_APP_FRONTEND_URL || ""
export const AUTH0_DOMAIN = (process.env.AUTH0_DOMAIN || "").replace(/\/$/, "")
export const AUTH0_AUDIENCE = process.env.VUE_APP_AUTH_AUDIENCE
export const AUTH_REDIRECT = process.env.AUTH_REDIRECT || process.env.FRONTEND_URL || ""
export const FRONTEND_URL = process.env.FRONTEND_URL || ""
export const AUTH0_DOMAIN = stripTrailingSlash(process.env.VITE_AUTH0_DOMAIN || "")
export const AUTH0_AUDIENCE = process.env.VITE_AUTH0_AUDIENCE
export const AUTH0_REDIRECT = process.env.VITE_AUTH0_REDIRECT || process.env.FRONTEND_URL || ""

export const APPLICATION_NAME = process.env.APPLICATION_NAME || ""
export const APPLICATION_NAME = process.env.VITE_APPLICATION_NAME || ""

export const DB_HOST = process.env.DB_HOST || ""
export const DB_USER = process.env.DB_USER || ""
Expand Down
26 changes: 24 additions & 2 deletions api/src/router.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,37 @@
import path from "path"
import fs from "fs"

import { Router, type Request, type Response } from "express"
import { template } from "lodash"

import { GIT_COMMIT_HASH, RELEASE_TAG } from "@/config"
import { APPLICATION_NAME, GIT_COMMIT_HASH, RELEASE_TAG } from "@/config"

export const router = Router()

// some routes
router.route("/_status").get((req: Request, res: Response) => {
res.json({
return res.json({
RELEASE_TAG,
GIT_COMMIT_HASH,
})
})

// if no other api routes match, send the 404 page
router.use("/api", (req: Request, res: Response) => {
const templatePath = path.resolve(__dirname, "web/404.html")
try {
const templateString = fs.readFileSync(templatePath, "utf8")
const compiledTemplate = template(templateString)
const result = compiledTemplate({
applicationName: APPLICATION_NAME,
releaseTag: RELEASE_TAG,
gitCommitHash: GIT_COMMIT_HASH,
})
return res.status(404).send(result)
} catch (error) {
console.error(error)
return res.status(500).send(`Error building 404 page: ${error}`)
}
})

export default router
3 changes: 3 additions & 0 deletions api/src/utils/strip-trailing-slash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function stripTrailingSlash(url: string) {
return url.endsWith("/") ? url.slice(0, -1) : url
}
29 changes: 29 additions & 0 deletions api/src/web/404.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<title>404 Not Found</title>
<style>
body {
text-align: center;
padding-top: 100px;
}
hr {
margin-top: 30px;
margin-bottom: 30px;
}
</style>
</head>
<body>
<h1>Error 404</h1>
<p>Oops! The page you're looking doesn't exist.</p>
<hr />
<p>Site: ${applicationName}</p>
<p>Version: ${releaseTag}</p>
<p>Commit Hash: ${gitCommitHash}</p>
</body>
</html>
2 changes: 1 addition & 1 deletion api/src/web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
</head>
<body>
<h1>Error 404</h1>
<p>Oops! The page you're looking doesn't exist.</p>
<p>This is a stub is meant to be replaced by the compiled front-end in production</p>
<hr />
<p>Site: Internal Data Portal</p>
<p>Version: 0.1.0</p>
Expand Down
35 changes: 20 additions & 15 deletions docker-compose.development.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ x-default-environment: &default-environment
DB_NAME: idp_development
DB_PASS: &default-db-password DevPwd99!
DB_PORT: &default-db-port 1433
FRONTEND_URL: "http://localhost:8080"
VITE_APPLICATION_NAME: "Internal Data Portal"
VITE_API_BASE_URL: "http://localhost:3000"
VITE_AUTH0_CLIENT_ID": "mS8zklFSgatWX3v1OCQgVpEq5MixCm4k"
VITE_AUTH0_AUDIENCE": "testing"
VITE_AUTH0_DOMAIN": "https://dev-0tc6bn14.eu.auth0.com"
RELEASE_TAG: "${RELEASE_TAG:-development}"
GIT_COMMIT_HASH: "${GIT_COMMIT_HASH:-not-set}"

services:
api:
Expand All @@ -17,8 +25,6 @@ services:
- ./api/.env.development
environment:
<<: *default-environment
RELEASE_TAG: development
GIT_COMMIT_HASH: not-set
tty: true # allows attaching debugger, equivalent of docker exec -t
# stdin_open: true # equivalent of docker exec -i
ports:
Expand All @@ -29,19 +35,18 @@ services:
db:
condition: service_healthy

# web:
# build:
# context: ./web
# dockerfile: development.Dockerfile
# environment:
# <<: *default-environment
# VITE_API_BASE_URL: "http://localhost:3000"
# ports:
# - "8080:8080"
# volumes:
# - ./web:/usr/src/web
# depends_on:
# - api
web:
build:
context: ./web
dockerfile: development.Dockerfile
environment:
<<: *default-environment
ports:
- "8080:8080"
volumes:
- ./web:/usr/src/web
depends_on:
- api

# test_api:
# build:
Expand Down
4 changes: 4 additions & 0 deletions web/.browserslistrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
> 1%
last 2 versions
not dead
not ie 11
27 changes: 27 additions & 0 deletions web/.eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// https://github.com/typescript-eslint/typescript-eslint/issues/251
export default {
root: true,
env: {
browser: true,
es2021: true,
node: true,
},
extends: [
"eslint:recommended",
"plugin:vue/vue3-recommended",
"plugin:@typescript-eslint/recommended",
"prettier",
],
overrides: [],
parser: "vue-eslint-parser",
parserOptions: {
ecmaVersion: "latest",
extraFileExtensions: [".vue"],
parser: "@typescript-eslint/parser",
tsconfigRootDir: __dirname,
project: ["./tsconfig.node.json", "./tsconfig.json"],
sourceType: "module",
},
plugins: ["vue", "@typescript-eslint"],
rules: {},
}
30 changes: 30 additions & 0 deletions web/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
.DS_Store
dist
dist-ssr
coverage
*.local

/cypress/videos/
/cypress/screenshots/

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

*.tsbuildinfo
7 changes: 6 additions & 1 deletion web/.vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
{
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
"recommendations": [
"Vue.volar",
"Vue.vscode-typescript-vue-plugin",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}
18 changes: 18 additions & 0 deletions web/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Vue 3 + TypeScript + Vite

This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.

## Recommended IDE Setup

- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).

## Type Support For `.vue` Imports in TS

TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types.

If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:

1. Disable the built-in TypeScript Extension
1. Run `Extensions: Show Built-in Extensions` from VSCode's command palette
2. Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
11 changes: 11 additions & 0 deletions web/development.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM node:20.10.0-alpine3.19

WORKDIR /usr/src/web

COPY package*.json ./

RUN npm install

COPY . .

CMD ["npm", "run", "start", "--", "--host", "0.0.0.0"]
36 changes: 36 additions & 0 deletions web/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<!doctype html>
<html lang="en">
<head>
<link
rel="preconnect"
href="https://fonts.googleapis.com"
/>
<link
rel="preconnect"
href="https://fonts.gstatic.com"
crossorigin
/>
<link
href="https://fonts.googleapis.com/css2?family=Courier+Prime:wght@400;700&display=swap"
rel="stylesheet"
/>
<meta charset="UTF-8" />
<link
rel="icon"
type="image/ico"
href="/favicon.ico"
/>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<title>Internal Data Portal</title>
</head>
<body>
<div id="app"></div>
<script
type="module"
src="/src/main.ts"
></script>
</body>
</html>
Loading

0 comments on commit 01d0770

Please sign in to comment.