diff --git a/docs/blog/pattern-to-reconsider/index.md b/docs/blog/pattern-to-reconsider/index.md index 66c65a0d..629a5b67 100644 --- a/docs/blog/pattern-to-reconsider/index.md +++ b/docs/blog/pattern-to-reconsider/index.md @@ -70,10 +70,12 @@ await axios.put(`${process.env.USER_SERVICE_URL}/api/user/${post.userId}/increme **📊 How popular:** 21,806,137 downloads/week! -**🤔 Why it might be wrong:** Dotenv is so easy and intuitive to start with, so one might easily overlook fundamental features: For example, it's hard to infer the configuration schema and realize the meaning of each key and its typing. Consequently, there is no built-in way to fail fast when a mandatory key is missing - a flow might fail after starting and presenting some side effects (e.g., DB records were already mutated before the failure). In the example above, the blog post will be saved to DB, and only then will the code realize that a mandatory key is missing - This leaves the app hanging in an invalid state. On top of this, in the presence of many keys, it's impossible to organize them hierarchically. If not enough, it encourages developers to commit this .env file which might contain production values - this happens because there is no clear way to define development defaults. Teams usually work around this by committing .env.example file and then asking whoever pulls code to rename this file manually. If they remember to of course +**🤔 Why it might be wrong:** Dotenv is so easy and intuitive to start with, so one might easily overlook fundamental features: For example, it's hard to infer the configuration schema and realize the meaning of each key and its typing. Consequently, there is no built-in way to fail fast when a mandatory key is missing - a flow might fail after starting and presenting some side effects (e.g., DB records were already mutated before the failure). In the example above, the blog post will be saved to DB, and only then will the code realize that a mandatory key is missing - This leaves the app hanging in an invalid state. On top of this, in the presence of many keys, it's impossible to organize them hierarchically. If not enough, it encourages developers to commit this .env file which might contain production values - this happens because there is no clear way to define development defaults. .env is meant to define development and development only. We expressely [recommend against committing your .env file to code](https://github.com/motdotla/dotenv#should-i-commit-my-env-file). Teams usually work around this by committing .env.example file and then asking whoever pulls code to rename this file manually. Recently, the same people that pioneered dotenv are [extending it with syncing features](https://github.com/dotenv-org/dotenv-vault) to avoid this work around. **☀️ Better alternative:** Some configuration libraries provide out of the box solution to all of these needs. They encourage a clear schema and the possibility to validate early and fail if needed. See [comparison of options here](https://practica.dev/decisions/configuration-library). One of the better alternatives is ['convict'](https://github.com/mozilla/node-convict), down below is the same example, this time with Convict, hopefully it's better now: +Doesn't sharing a `config.js` file that should NOT be committed to code have the same risk as committing a .env file? + ```javascript // config.js export default {