So, I moved my website Code.Build to Vercel from Cloud Run after writing all these Angular Universal articles.
Cloud Run VS AWS Lambdas
My cold start time was cut in a quarter of the time. My build time went from 15min to 3min. Granted, I didn't add any horse power to my Google Cloud Run, and I spend a total of $7 a month on hosting. I went with the default options, which Vercel uses more power. I admit my website is probably not too popular either since all my articles are cross posted here. ☹️
After reading many articles, AWS Lambdas are just faster than Docker and Cloud Run. This was extremely important to me. Google needs to spend more money developing on its Cloud Functions in order to compete. However, it is worth noting that Cloud Run does support things like Web Sockets for streaming data, while AWS Lambdas do no such thing. This is important if you're hosting a database or middleware.
So, last thing I needed to do was configure my ENV variables to work correctly in Vercel.
Firebase
For this example, I am using the Firebase env variables, and storing them in a json file. You can read about that in my Google Cloud Build article.
Basically just put the firebase information in environment.json
and import it into environment.ts
.
On the server, go to your project in Vercel, and add a new variable FIREBASE
with your json keys.
process.env
The developers at Vercel HATE Angular. Angular is not inferior, it is just different. Notice they don't even have a tab for Angular to use ENV variables. They don't support Angular Universal, even though I wrote an aritcle about how to do it. I guess they want a plugin written. You don't need one, but I digress. Perhaps someone could write one. It may be necessary for automating advanced features like lazy loading modules to their own serverless function etc.
So, it is worth noting that process.env
is available on the server, but not on the browser due to reasons listed above.
There is a probably a way to just echo
the env variables to a file like I did in Cloud Build, but I went with the classic script version.
Build File
set-env.js
function setEnv() {
fs = require("fs");
writeFile = fs.writeFile;
// Configure Angular `environment.prod.json` file path
targetPath = "/vercel/path1/src/environments/environment.prod.json";
targetPath2 = "/vercel/path2/src/environments/environment.prod.json";
// `environment.prod.json` file structure
envConfigFile = process.env.FIREBASE;
console.log(
"The file `environment.prod.json` will be written with the following content: \n"
);
writeFile(targetPath, envConfigFile, function (err) {
if (err) {
console.error(err);
throw err;
} else {
console.log(
"Angular environment.prod.json file generated correctly at" +
targetPath +
"\n"
);
}
});
writeFile(targetPath2, envConfigFile, function (err) {
if (err) {
console.error(err);
throw err;
} else {
console.log(
"Angular environment.prod.json file generated correctly at" +
targetPath +
"\n"
);
}
});
}
setEnv();
Create this file in your environments folder. Notice it must build two copies of the json files: one for the server, and one for the browser.
Follow my Vercel Setup instructions, add scripts.config
and update scripts.vercel-build
.
"config": "node src/environments/set-env.js",
"vercel-build": "npm run config && npm run build:ssr"
Done.
Now the script runs when you build to populate the env variables on BOTH server and browser. Remember, if you just want the variables on the server, you can simple check for process.env.FIREBASE
and get it that way. The problem is development environments.
Hope this helps someone,
J
Top comments (1)
I used this script for an Angular app (non-universal) with a few minor changes and it has been working great. The most notable changes I made were:
fileWrite
targetPath = "./src/environments/environment.prod.json";
"build": "npm run config && ng build",
Now, I have another Angular app where the content is mostly static, so I am pre-rendering the application to be able to optimize it for SEO. I am using the same script as for the other app, however, instead of the above change to the build task, I added the following vercel-build task:
npm run config && npm run prerender
, which uses task:"prerender": "ng run <my-app-name>:prerender"
.On local it works fine, if I create my env variables on my local machine, and run the vercel-build task, the sources are generated and the env variable values are injected correctly. However, when pushing to Vercel, it doesn't work. I do see the console log showing the success message indicating that the variables were written to disk.
If I pre-populate the environment.prod.json file with dummy entries, those dummy entries are the ones that show up in the Vercel output contents, which hints at one of the following:
I've tried all kinds of things and nothing seems to work, it's driving me crazy. If you can think of what I might be missing, I would really appreciate any suggestions.
P.S. Both apps are still on Angular 16.