chore: add image optimization script and README
This commit is contained in:
@@ -1,3 +1,36 @@
|
||||
# personal_site
|
||||
|
||||
This repository is a React-based personal website for Gregory Campbell.
|
||||
|
||||
Quick commands
|
||||
|
||||
```bash
|
||||
# install deps (use legacy peer deps if you hit TypeScript/react-scripts conflicts)
|
||||
npm install --legacy-peer-deps
|
||||
|
||||
# run dev server
|
||||
npm start
|
||||
|
||||
# build production
|
||||
npm run build
|
||||
|
||||
# optimize images (requires sharp)
|
||||
# install sharp (one-time):
|
||||
npm run optimize-images:install
|
||||
# then run optimization:
|
||||
npm run optimize-images
|
||||
```
|
||||
|
||||
Image optimization
|
||||
|
||||
This repo includes `scripts/optimize-images.js`, a small Node script that uses `sharp` to generate WebP resized variants for images found in `src/assets`. The script writes outputs to `public/images` by default.
|
||||
|
||||
If you prefer a different pipeline, consider using `imagemin` or a CI-integrated image optimization step.
|
||||
|
||||
Deployment / Amplify notes
|
||||
|
||||
- The project uses `package-lock.json` (npm) — ensure CI is configured to use `npm install` and not `yarn`.
|
||||
- If deploying via AWS Amplify and it errors with multiple lockfiles, ensure only one lockfile (package-lock.json) is present.
|
||||
[](https://app.netlify.com/projects/gregoryjcampbell/deploys)
|
||||
|
||||
This is the source code for my [Personal Website](https://gregoryjcampbell.netlify.app/).
|
||||
|
||||
+3
-1
@@ -29,7 +29,9 @@
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
"eject": "react-scripts eject",
|
||||
"optimize-images": "node scripts/optimize-images.js",
|
||||
"optimize-images:install": "npm install --save-dev sharp --legacy-peer-deps"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "react-app"
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env node
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
async function main() {
|
||||
let sharp;
|
||||
try {
|
||||
sharp = require('sharp');
|
||||
} catch (e) {
|
||||
console.error('\nError: the package "sharp" is not installed.');
|
||||
console.error('Install it with: npm install --save-dev sharp');
|
||||
console.error('Or run: npm run optimize-images:install to install prerequisites.\n');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const assetsDir = path.join(__dirname, '..', 'src', 'assets');
|
||||
const outDir = path.join(__dirname, '..', 'public', 'images');
|
||||
if (!fs.existsSync(assetsDir)) {
|
||||
console.error('No assets directory found at', assetsDir);
|
||||
process.exit(1);
|
||||
}
|
||||
if (!fs.existsSync(outDir)) fs.mkdirSync(outDir, { recursive: true });
|
||||
|
||||
const files = fs.readdirSync(assetsDir).filter((f) => /\.(jpe?g|png)$/i.test(f));
|
||||
if (!files.length) {
|
||||
console.log('No PNG/JPG assets found to optimize.');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Optimizing ${files.length} images to ${outDir} ...`);
|
||||
const sizes = [320, 640, 1024];
|
||||
|
||||
for (const file of files) {
|
||||
const input = path.join(assetsDir, file);
|
||||
const name = path.parse(file).name;
|
||||
|
||||
for (const w of sizes) {
|
||||
const outPath = path.join(outDir, `${name}-${w}.webp`);
|
||||
try {
|
||||
await sharp(input)
|
||||
.resize({ width: w })
|
||||
.webp({ quality: 80 })
|
||||
.toFile(outPath);
|
||||
console.log('wrote', outPath);
|
||||
} catch (err) {
|
||||
console.error('failed to process', input, err.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log('\nImage optimization complete. Copy generated files into your build or update components to reference them.');
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user