From 8b21ff6e686e28d6943e3e11b1794883d4d00857 Mon Sep 17 00:00:00 2001 From: Jordan Roher Date: Mon, 18 Dec 2023 12:21:08 -0800 Subject: [PATCH] More docker updates Minifying CSS --- .gitignore | 4 +++- default.conf | 18 +++++++++++++++++ dockerfile | 6 +++++- index.html | 2 +- package-lock.json | 33 ++++++++++++++++++++++++++---- package.json | 11 +++++++--- src/css-cache-break.ts | 23 +++++++++++++++++++++ src/index.ts | 21 +++++++++++++++++++ src/shared/files.ts | 38 ++++++++++++++++++++++++++++++++++ src/static.ts | 46 ------------------------------------------ tsconfig.json | 2 +- 11 files changed, 147 insertions(+), 57 deletions(-) create mode 100644 default.conf create mode 100644 src/css-cache-break.ts create mode 100644 src/index.ts create mode 100644 src/shared/files.ts delete mode 100644 src/static.ts diff --git a/.gitignore b/.gitignore index 2575ddd..b65edcc 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,6 @@ node_modules .DS_Store dist src/*.js -src/**/*.js \ No newline at end of file +src/**/*.js +public/index.html +public/main.*.css \ No newline at end of file diff --git a/default.conf b/default.conf new file mode 100644 index 0000000..3f65062 --- /dev/null +++ b/default.conf @@ -0,0 +1,18 @@ +server { + listen 4173; + + root /app; + + location /app { + try_files $uri $uri/ =404; + + # Cache settings for static content + expires 7d; # Cache static content for 7 days + add_header Cache-Control "public, max-age=604800, immutable"; + } + + # Additional configurations can be added here if needed + # For example, error handling, logging, etc. + error_page 404 /index.html; + error_page 500 502 503 504 /index.html; +} diff --git a/dockerfile b/dockerfile index e46b829..88d6e52 100644 --- a/dockerfile +++ b/dockerfile @@ -1,6 +1,7 @@ # Build site using Node JS FROM node:21-slim +# Install nginx RUN apt-get update && apt-get install -y nginx ARG BUILD_DATE @@ -19,6 +20,9 @@ RUN npm i COPY . . +# Copy the nginx config to the correct folder +COPY default.conf /etc/nginx/conf.d/default.conf + ENV NODE_ENV production ENV TITLE "My Website" @@ -37,4 +41,4 @@ EXPOSE 4173 RUN chmod +x /app/docker-entrypoint.sh ENTRYPOINT ["/app/docker-entrypoint.sh"] -CMD ["npm", "run", "start"] \ No newline at end of file +CMD ["npm", "run", "build"] \ No newline at end of file diff --git a/index.html b/index.html index 69c016f..9794b27 100644 --- a/index.html +++ b/index.html @@ -5,7 +5,7 @@ My Website - +
diff --git a/package-lock.json b/package-lock.json index c97f95d..c3c06e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,10 +9,14 @@ "version": "1.4.0", "dependencies": { "@types/node": "^20.10.5", + "clean-css": "^5.3.3", "html-minifier": "^4.0.0", "prettier": "^3.1.1", "tailwindcss": "^3.3.6", "typescript": "^5.3.3" + }, + "devDependencies": { + "@types/clean-css": "^4.2.11" } }, "node_modules/@alloc/quick-lru": { @@ -106,6 +110,16 @@ "node": ">= 8" } }, + "node_modules/@types/clean-css": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/@types/clean-css/-/clean-css-4.2.11.tgz", + "integrity": "sha512-Y8n81lQVTAfP2TOdtJJEsCoYl1AnOkqDqMvXb9/7pfgZZ7r8YrEyurrAvAoAjHOGXKRybay+5CsExqIH6liccw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "source-map": "^0.6.0" + } + }, "node_modules/@types/node": { "version": "20.10.5", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz", @@ -224,14 +238,14 @@ } }, "node_modules/clean-css": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", - "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", "dependencies": { "source-map": "~0.6.0" }, "engines": { - "node": ">= 4.0" + "node": ">= 10.0" } }, "node_modules/commander": { @@ -408,6 +422,17 @@ "node": ">=6" } }, + "node_modules/html-minifier/node_modules/clean-css": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz", + "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 4.0" + } + }, "node_modules/html-minifier/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", diff --git a/package.json b/package.json index 8015d79..e72f2c2 100644 --- a/package.json +++ b/package.json @@ -8,12 +8,14 @@ "version": "1.4.0", "type": "commonjs", "scripts": { - "build": "tsc && node ./dist/static.js && npm run html && npm run tailwind", - "html": "html-minifier --remove-comments --collapse-whitespace --input-dir ./dist --output-dir ./dist --file-ext html", - "tailwind": "npx tailwindcss -i ./src/tailwind.css -o ./dist/main.css" + "build": "tsc && node ./dist/index.js && npm run html && npm run tailwind && npm run css-cache-break", + "html": "html-minifier --remove-comments --collapse-whitespace --input-dir ./public --output-dir ./public --file-ext html", + "tailwind": "npx tailwindcss -i ./src/tailwind.css -o ./public/main.css", + "css-cache-break": "node ./dist/css-cache-break.js" }, "dependencies": { "@types/node": "^20.10.5", + "clean-css": "^5.3.3", "html-minifier": "^4.0.0", "prettier": "^3.1.1", "tailwindcss": "^3.3.6", @@ -27,5 +29,8 @@ "tabWidth": 4, "trailingComma": "es5", "useTabs": true + }, + "devDependencies": { + "@types/clean-css": "^4.2.11" } } diff --git a/src/css-cache-break.ts b/src/css-cache-break.ts new file mode 100644 index 0000000..ba16e0d --- /dev/null +++ b/src/css-cache-break.ts @@ -0,0 +1,23 @@ +import CleanCSS from "clean-css"; +import * as path from "path"; +import { sbReadFile, sbRename, sbWriteFile } from "./shared/files"; + +const mainCSSFilename = `main.${new Date().getTime()}.css`; + +const cssFileInPath = path.join(__dirname, "../", "./public", "main.css"); +const cssFileOutPath = path.join(__dirname, "../", "./public", mainCSSFilename); +const indexFileInOutPath = path.join(__dirname, "../", "./public", "index.html"); + +async function start(): Promise { + await sbRename(cssFileInPath, cssFileOutPath); + const css = await sbReadFile(cssFileOutPath); + await sbWriteFile(cssFileOutPath, new CleanCSS().minify(css).styles); + + const index = await sbReadFile(indexFileInOutPath); + const cssLink = ``; + const cssLinkReplacement = ``; + + await sbWriteFile(indexFileInOutPath, index.replace(cssLink, cssLinkReplacement)); +} + +start(); diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..1a7d643 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,21 @@ +import * as path from "path"; +import { IndexPage } from "./pages/index"; +import { sbReadFile, sbWriteFile } from "./shared/files"; +import { PAGEICON, PAGETITLE } from "./variables"; + +const indexFileInPath = path.join(__dirname, "../", "index.html"); +const indexFileOutPath = path.join(__dirname, "../", "./public", "index.html"); + +async function start(): Promise { + const index = await sbReadFile(indexFileInPath); + + const newText = IndexPage({ icon: PAGEICON, title: PAGETITLE }); + const rootDiv = '
'; + const rootDivReplacement = '
$1
'; + + const newIndex = index.replace(rootDiv, rootDivReplacement.replace("$1", newText)); + + await sbWriteFile(indexFileOutPath, newIndex); +} + +start(); diff --git a/src/shared/files.ts b/src/shared/files.ts new file mode 100644 index 0000000..99b868d --- /dev/null +++ b/src/shared/files.ts @@ -0,0 +1,38 @@ +import * as fs from "fs/promises"; + +export async function sbReadFile(fileName: string): Promise { + return new Promise(async (resolve, reject) => { + try { + const index = await fs.readFile(fileName); + + return resolve(index.toString()); + } catch (exception) { + console.error(`Could not read file: ${fileName}`); + reject(exception); + } + }); +} + +export async function sbWriteFile(fileName: string, contents: string): Promise { + return new Promise(async (resolve, reject) => { + try { + await fs.writeFile(fileName, contents); + return resolve(true); + } catch (exception) { + console.error(`Could not write file: ${fileName}`); + reject(exception); + } + }); +} + +export async function sbRename(fileNameOld: string, fileNameNew: string): Promise { + return new Promise(async (resolve, reject) => { + try { + await fs.rename(fileNameOld, fileNameNew); + return resolve(true); + } catch (exception) { + console.error(`Could not rename file: ${fileNameOld} to ${fileNameNew}`); + reject(exception); + } + }); +} diff --git a/src/static.ts b/src/static.ts deleted file mode 100644 index 8b832aa..0000000 --- a/src/static.ts +++ /dev/null @@ -1,46 +0,0 @@ -import * as fs from "fs/promises"; -import * as path from "path"; -import { IndexPage } from "./pages/index"; -import { PAGEICON, PAGETITLE } from "./variables"; - -const indexFileInPath = path.join(__dirname, "../", "index.html"); -const indexFileOutPath = path.join(__dirname, "../", "./dist", "index.html"); - -async function readIndexPage(): Promise { - return new Promise(async (resolve, reject) => { - try { - const index = await fs.readFile(indexFileInPath); - - return resolve(index.toString()); - } catch (exception) { - console.error("Could not read index.html file"); - reject(exception); - } - }); -} - -async function writeIndexPage(contents: string): Promise { - return new Promise(async (resolve, reject) => { - try { - await fs.writeFile(indexFileOutPath, contents); - return resolve(true); - } catch (exception) { - console.error("Could not write index.html file"); - reject(exception); - } - }); -} - -async function start(): Promise { - const index = await readIndexPage(); - - const newText = IndexPage({ icon: PAGEICON, title: PAGETITLE }); - const rootDiv = '
'; - const rootDivReplacement = '
$1
'; - - const newIndex = index.replace(rootDiv, rootDivReplacement.replace("$1", newText)); - - await writeIndexPage(newIndex); -} - -start(); diff --git a/tsconfig.json b/tsconfig.json index c7edd98..24e9c88 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,5 +8,5 @@ "resolveJsonModule": true, "module": "CommonJS" }, - "include": ["src/static.ts"] + "include": ["src/index.ts", "src/css-cache-break.ts"] }