More docker updates

Minifying CSS
This commit is contained in:
Jordan Roher 2023-12-18 12:21:08 -08:00
parent 219841a148
commit 8b21ff6e68
11 changed files with 147 additions and 57 deletions

2
.gitignore vendored
View File

@ -3,3 +3,5 @@ node_modules
dist dist
src/*.js src/*.js
src/**/*.js src/**/*.js
public/index.html
public/main.*.css

18
default.conf Normal file
View File

@ -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;
}

View File

@ -1,6 +1,7 @@
# Build site using Node JS # Build site using Node JS
FROM node:21-slim FROM node:21-slim
# Install nginx
RUN apt-get update && apt-get install -y nginx RUN apt-get update && apt-get install -y nginx
ARG BUILD_DATE ARG BUILD_DATE
@ -19,6 +20,9 @@ RUN npm i
COPY . . COPY . .
# Copy the nginx config to the correct folder
COPY default.conf /etc/nginx/conf.d/default.conf
ENV NODE_ENV production ENV NODE_ENV production
ENV TITLE "My Website" ENV TITLE "My Website"
@ -37,4 +41,4 @@ EXPOSE 4173
RUN chmod +x /app/docker-entrypoint.sh RUN chmod +x /app/docker-entrypoint.sh
ENTRYPOINT ["/app/docker-entrypoint.sh"] ENTRYPOINT ["/app/docker-entrypoint.sh"]
CMD ["npm", "run", "start"] CMD ["npm", "run", "build"]

View File

@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
<title>My Website</title> <title>My Website</title>
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" /> <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
<link rel="stylesheet" crossorigin="" href="./main.css" /> <link rel="stylesheet" href="./main.css" crossorigin="" />
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>

33
package-lock.json generated
View File

@ -9,10 +9,14 @@
"version": "1.4.0", "version": "1.4.0",
"dependencies": { "dependencies": {
"@types/node": "^20.10.5", "@types/node": "^20.10.5",
"clean-css": "^5.3.3",
"html-minifier": "^4.0.0", "html-minifier": "^4.0.0",
"prettier": "^3.1.1", "prettier": "^3.1.1",
"tailwindcss": "^3.3.6", "tailwindcss": "^3.3.6",
"typescript": "^5.3.3" "typescript": "^5.3.3"
},
"devDependencies": {
"@types/clean-css": "^4.2.11"
} }
}, },
"node_modules/@alloc/quick-lru": { "node_modules/@alloc/quick-lru": {
@ -106,6 +110,16 @@
"node": ">= 8" "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": { "node_modules/@types/node": {
"version": "20.10.5", "version": "20.10.5",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz",
@ -224,14 +238,14 @@
} }
}, },
"node_modules/clean-css": { "node_modules/clean-css": {
"version": "4.2.1", "version": "5.3.3",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz",
"integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==",
"dependencies": { "dependencies": {
"source-map": "~0.6.0" "source-map": "~0.6.0"
}, },
"engines": { "engines": {
"node": ">= 4.0" "node": ">= 10.0"
} }
}, },
"node_modules/commander": { "node_modules/commander": {
@ -408,6 +422,17 @@
"node": ">=6" "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": { "node_modules/html-minifier/node_modules/commander": {
"version": "2.20.3", "version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",

View File

@ -8,12 +8,14 @@
"version": "1.4.0", "version": "1.4.0",
"type": "commonjs", "type": "commonjs",
"scripts": { "scripts": {
"build": "tsc && node ./dist/static.js && npm run html && npm run tailwind", "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 ./dist --output-dir ./dist --file-ext html", "html": "html-minifier --remove-comments --collapse-whitespace --input-dir ./public --output-dir ./public --file-ext html",
"tailwind": "npx tailwindcss -i ./src/tailwind.css -o ./dist/main.css" "tailwind": "npx tailwindcss -i ./src/tailwind.css -o ./public/main.css",
"css-cache-break": "node ./dist/css-cache-break.js"
}, },
"dependencies": { "dependencies": {
"@types/node": "^20.10.5", "@types/node": "^20.10.5",
"clean-css": "^5.3.3",
"html-minifier": "^4.0.0", "html-minifier": "^4.0.0",
"prettier": "^3.1.1", "prettier": "^3.1.1",
"tailwindcss": "^3.3.6", "tailwindcss": "^3.3.6",
@ -27,5 +29,8 @@
"tabWidth": 4, "tabWidth": 4,
"trailingComma": "es5", "trailingComma": "es5",
"useTabs": true "useTabs": true
},
"devDependencies": {
"@types/clean-css": "^4.2.11"
} }
} }

23
src/css-cache-break.ts Normal file
View File

@ -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<void> {
await sbRename(cssFileInPath, cssFileOutPath);
const css = await sbReadFile(cssFileOutPath);
await sbWriteFile(cssFileOutPath, new CleanCSS().minify(css).styles);
const index = await sbReadFile(indexFileInOutPath);
const cssLink = `<link rel="stylesheet" href="./main.css" crossorigin="">`;
const cssLinkReplacement = `<link rel="stylesheet" href="./${mainCSSFilename}" crossorigin="" />`;
await sbWriteFile(indexFileInOutPath, index.replace(cssLink, cssLinkReplacement));
}
start();

21
src/index.ts Normal file
View File

@ -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<void> {
const index = await sbReadFile(indexFileInPath);
const newText = IndexPage({ icon: PAGEICON, title: PAGETITLE });
const rootDiv = '<div id="root"></div>';
const rootDivReplacement = '<div id="root">$1</div>';
const newIndex = index.replace(rootDiv, rootDivReplacement.replace("$1", newText));
await sbWriteFile(indexFileOutPath, newIndex);
}
start();

38
src/shared/files.ts Normal file
View File

@ -0,0 +1,38 @@
import * as fs from "fs/promises";
export async function sbReadFile(fileName: string): Promise<string> {
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<boolean> {
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<boolean> {
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);
}
});
}

View File

@ -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<string> {
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<boolean> {
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<void> {
const index = await readIndexPage();
const newText = IndexPage({ icon: PAGEICON, title: PAGETITLE });
const rootDiv = '<div id="root"></div>';
const rootDivReplacement = '<div id="root">$1</div>';
const newIndex = index.replace(rootDiv, rootDivReplacement.replace("$1", newText));
await writeIndexPage(newIndex);
}
start();

View File

@ -8,5 +8,5 @@
"resolveJsonModule": true, "resolveJsonModule": true,
"module": "CommonJS" "module": "CommonJS"
}, },
"include": ["src/static.ts"] "include": ["src/index.ts", "src/css-cache-break.ts"]
} }