2024-01-11
Last year I wrote a blog about the same top here.
In the previous blog, I need to:
build the app normally;
manually move the built static assets (js/css/images etc.) to a versioned folder;
manually replace the path in index.html
and manifest.json
to add the versioned prefix;
upload everything to S3;
But yesterday I found that create-react-app has a native support for placing assets to a specific folder, and all the links in index.html will also have that prefix automatically. And since I now generate all my favicon with Favicon37, I don't need to care about manifest.json
anymore.
The trick is the PUBLIC_URL
env variable:
const timestamp = new Date()
.toISOString()
.replace(/[^0-9]/g, '')
.slice(0, 14);
PUBLIC_URL
in .env.production
to be the timestamp:const envPath = path.join(__dirname, '..', '.env.production'); // Adjust the path to your .env file
let envContents = fs.readFileSync(envPath, 'utf-8');
let lines = envContents.split('\n');
let found = false;
lines = lines.map(line => {
const [currentKey] = line.split('=');
if (currentKey === key) {
found = true;
return `${key}=${value}`;
}
return line;
});
if (!found) {
lines.push(`${key}=${value}`);
}
// Filter out any empty lines
lines = lines.filter(line => line.trim() !== '');
fs.writeFileSync(envPath, lines.join('\n'));
console.log('Building the app...');
execSync(`npm run build`);
console.log('Build app completed.');
console.log('Uploading assets to S3...');
execSync(
`aws s3 sync build/static ${process.env.S3_URL}/${timestamp}/static --cache-control max-age=31536000,public`
);
console.log('Upload assets to S3 completed.');
console.log('Uploading index.html to S3...');
execSync(
`aws s3 cp build/index.html ${process.env.S3_URL}/index.html --cache-control max-age=0,no-store`
);
console.log('Upload index.html to S3 completed.');
That's it.