A better build
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,3 +6,4 @@ node_modules
|
||||
pnpm-lock.yaml
|
||||
.eslintcache
|
||||
.stylelintcache
|
||||
dist
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM nginx:alpine
|
||||
|
||||
COPY nginx/conf.d/ /etc/nginx/conf.d/
|
||||
COPY src/ /usr/share/nginx/html/
|
||||
COPY dist/ /usr/share/nginx/html/
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"version": "1.0.0",
|
||||
"packageManager": "pnpm@10.29.3",
|
||||
"scripts": {
|
||||
"build": "node scripts/build.js",
|
||||
"docker:build": "docker build --platform linux/amd64 -t git.mifi.dev/mifi-holdings/landing:latest .",
|
||||
"docker:push": "docker push git.mifi.dev/mifi-holdings/landing:latest",
|
||||
"format": "prettier --write .",
|
||||
@@ -18,11 +19,14 @@
|
||||
"lint:fix:yaml": "yamllint .woodpecker/ci.yml .woodpecker/build.yml .woodpecker/deploy.yml docker-compose.yml --fix"
|
||||
},
|
||||
"devDependencies": {
|
||||
"clean-css": "^5.3.3",
|
||||
"critters": "^0.0.25",
|
||||
"eslint": "^10.0.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"prettier": "^3.4.2",
|
||||
"stylelint": "^17.3.0",
|
||||
"stylelint-config-standard": "^40.0.0",
|
||||
"terser": "^5.46.0",
|
||||
"yaml-lint": "^1.7.0"
|
||||
},
|
||||
"repository": {
|
||||
|
||||
69
scripts/build.js
Normal file
69
scripts/build.js
Normal file
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Build script: copy src → dist, minify JS/CSS, inline critical CSS (Critters).
|
||||
* Run with: pnpm build
|
||||
*/
|
||||
import { rmSync, mkdirSync, readFileSync, writeFileSync, cpSync, readdirSync } from 'fs'
|
||||
import { join, dirname, extname } from 'path'
|
||||
import { fileURLToPath } from 'url'
|
||||
import Critters from 'critters'
|
||||
import { minify as minifyJs } from 'terser'
|
||||
import CleanCSS from 'clean-css'
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||
const root = join(__dirname, '..')
|
||||
const srcDir = join(root, 'src')
|
||||
const distDir = join(root, 'dist')
|
||||
|
||||
function getFiles(dir, files = []) {
|
||||
const entries = readdirSync(dir, { withFileTypes: true })
|
||||
for (const e of entries) {
|
||||
const full = join(dir, e.name)
|
||||
if (e.isDirectory()) getFiles(full, files)
|
||||
else files.push(full)
|
||||
}
|
||||
return files
|
||||
}
|
||||
|
||||
async function main() {
|
||||
// 1. Clean and copy src → dist
|
||||
rmSync(distDir, { recursive: true, force: true })
|
||||
mkdirSync(distDir, { recursive: true })
|
||||
cpSync(srcDir, distDir, { recursive: true })
|
||||
|
||||
const distFiles = getFiles(distDir)
|
||||
|
||||
// 2. Minify JS
|
||||
const jsFiles = distFiles.filter((f) => extname(f) === '.js')
|
||||
for (const f of jsFiles) {
|
||||
const code = readFileSync(f, 'utf8')
|
||||
const result = await minifyJs(code, { format: { comments: false } })
|
||||
if (result.code) writeFileSync(f, result.code)
|
||||
}
|
||||
|
||||
// 3. Minify CSS
|
||||
const cleanCss = new CleanCSS({ level: 2 })
|
||||
const cssFiles = distFiles.filter((f) => extname(f) === '.css')
|
||||
for (const f of cssFiles) {
|
||||
const code = readFileSync(f, 'utf8')
|
||||
const result = cleanCss.minify(code)
|
||||
if (!result.errors.length) writeFileSync(f, result.styles)
|
||||
}
|
||||
|
||||
// 4. Inline critical CSS with Critters (no browser; works in CI)
|
||||
const critters = new Critters({
|
||||
path: distDir,
|
||||
preload: 'default',
|
||||
logLevel: 'warn',
|
||||
})
|
||||
const indexPath = join(distDir, 'index.html')
|
||||
const html = readFileSync(indexPath, 'utf8')
|
||||
const inlined = await critters.process(html)
|
||||
writeFileSync(indexPath, inlined)
|
||||
|
||||
console.log('Build complete: dist/')
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -14,7 +14,7 @@
|
||||
<meta name="robots" content="index, follow" />
|
||||
<meta name="author" content="mifi" />
|
||||
|
||||
<link rel="stylesheet" href="css/styles.css" />
|
||||
<link rel="stylesheet" href="assets/css/style.css" />
|
||||
|
||||
<link rel="icon" type="image/svg+xml" href="/assets/images/favicon.svg" />
|
||||
<link rel="icon" type="image/x-icon" href="/assets/images/favicon.ico" />
|
||||
|
||||
Reference in New Issue
Block a user