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)
|
[](https://app.netlify.com/projects/gregoryjcampbell/deploys)
|
||||||
|
|
||||||
This is the source code for my [Personal Website](https://gregoryjcampbell.netlify.app/).
|
This is the source code for my [Personal Website](https://gregoryjcampbell.netlify.app/).
|
||||||
|
|||||||
+3
-1
@@ -29,7 +29,9 @@
|
|||||||
"start": "react-scripts start",
|
"start": "react-scripts start",
|
||||||
"build": "react-scripts build",
|
"build": "react-scripts build",
|
||||||
"test": "react-scripts test",
|
"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": {
|
"eslintConfig": {
|
||||||
"extends": "react-app"
|
"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