Skip to content

The variables in .env files should not be auto-parsed into non-string types #17915

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
yusufkandemir opened this issue Mar 19, 2025 · 0 comments

Comments

@yusufkandemir
Copy link
Member

yusufkandemir commented Mar 19, 2025

As of app-vite v2 / app-webpack v4, Quasar CLI automatically parses environment variables into bool(for true and false) instead of keeping them as strings. This behavior is different from tools like dotenv, which always treat environment variables as string. Standard Node.js behavior also gets all env variables as strings and auto-converts the newly assigned values to strings. It was meant to be a convenience feature, but it can lead to confusion and unexpected behavior in applications, especially when using TypeScript. This is also a hidden breaking change in app-vite v2 / app-webpack v4, considering it encourages developers to drop manual dotenv usage in favor of Quasar's built-in env variable handling.

app-vite v1 and app-webpack v3 had the same problematic behavior, but only for the built-in env variables, e.g. process.env.DEV. The new behavior extends this to all environment variables, including user-defined ones. This can be seen as a unified approach, but due to the differences in how dotenv and Node.js handle environment variables, it is problematic.

Node.js behavior:

// FOO=true node test.js
console.log(process.env.FOO); // 'true' (string)

process.env.BAR = true; // Assigning a boolean
console.log(process.env.BAR); // 'true' (string)

Example of Quasar behavior, given a .env file with:

FOO=true

Quasar converts it to:

console.log(process.env.FOO); // true (boolean)

Instead of the expected:

console.log(process.env.FOO); // 'true' (string)

This can lead to inconsistencies and unexpected behavior in applications, as TypeScript and Node.js both expect process.env values to always be string | undefined.

declare namespace NodeJS {
  interface ProcessEnv {
    FOO: boolean; // will fail
    BAR: string; // will pass
  }
}

Problems Caused

  1. TypeScript Issues:
  • TypeScript type augmentations can only enforce string | undefined, making it impossible to strongly type env variables with bool types.
  • The TS type of process.env.FOO will be seen as string | undefined, but it will be a boolean at runtime. This can lead to type errors, confusion, runtime errors, or even nasty hidden bugs.
  1. Inconsistency with Node.js & dotenv:

    • dotenv and standard Node.js behavior always return env variables as strings.
    • If a developer expects a string but receives a boolean, it may lead to unexpected bugs.
  2. Unexpected Behavior When Comparing Values:

    • Example:
      if (process.env.DEBUG === "true") {
        console.log("Debug mode enabled");
      }
      • In Quasar, if DEBUG=true, the condition fails (true !== 'true').
      • This differs from standard dotenv behavior, which always keeps the value as a string.

Proposed Solutions

For Now (Non-Breaking Change)

  1. Introduce a Configuration Option:

    • Add an option like disableEnvParsing: true in quasar.config file to disable automatic parsing. It can be put under something like future to group and clarify its purpose.
    • Default to false to avoid breaking existing apps.
    • This would allow developers to opt out of the automatic parsing behavior, adjusting their code accordingly if needed.
    • The config option can be made as more generic to extend to the built-in env variables as well. However, it may break existing App Extensions (AEs) that rely on the current behavior.
  2. Improve Documentation:

    • Clearly document the current behavior and its differences from dotenv and Node.js.
    • Provide a guide for developers who want to enforce string-based env variables.
  3. Add support for import.meta.env:

    • import.meta.env allows non-string types. So, using it won't have the confusion or type issues that process.env has.
    • This would allow developers to use both systems without confusion.
    • This may be problematic for app-webpack as it's not standard in Webpack. But, since it's used through the define plugin, it can still work.

For the Future (Breaking Change)

  • Stop Parsing Env Variables Automatically:
    • Follow dotenv and Node.js conventions by keeping all env variables as strings.
    • If developers need specific types, they can manually parse them:
      const DEBUG = process.env.DEBUG === "true"; // Explicit conversion
    • This would be a breaking change but aligns with ecosystem best practices.
  • Support for import.meta.env:
    • This is a more modern approach that aligns with ES modules, Vite, etc.
    • It doesn't have any behavior or type issues like process.env.
  • Deprecate/remove process.env in favor of import.meta.env, for the usual static replacement:
    • process.env can still be used for Node-based code such as SSR, Electron main process, etc.
    • This will also clarify the difference between static replacement and dynamically accessible env variables.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant