Skip to content
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

feat: add JS config handling to webpack and jest configs #515

Closed

Conversation

jsnwesson
Copy link

@jsnwesson jsnwesson commented Feb 14, 2024

This PR includes the following changes:

  • JS-based configuration is made available to Webpack Prod by passing in an environment variable
  • Webpack Dev config can now use the PORT assigned in env.config.js. Otherwise checks process.env.PORT or falls back to 8080.
  • Jest config now searches for either env.config.js or env.config.jsx for environment variables.
  • updated README to provide steps for using JS config in production and testing.

Resolves issues #513 and #514

* Jest config can now handle both JS and JSX env.configs
* Webpack dev config will be able to assign devserver port based on the PORT in env.config.js
* Require env.config object after copying it into MFE
@jsnwesson jsnwesson force-pushed the jwesson/add-js-config-handling-to-webpack-jest branch from 5cab127 to d664423 Compare March 1, 2024 21:00
@jsnwesson jsnwesson marked this pull request as ready for review March 1, 2024 22:35
Comment on lines +8 to +9
const appEnvConfigPathJs = path.resolve(process.cwd(), './env.config.js');
const appEnvConfigPathJsx = path.resolve(process.cwd(), './env.config.jsx');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[curious] Is there a chance someone may want to use .ts or .tsx with the env.config file?

Copy link
Contributor

@bradenmacdonald bradenmacdonald Mar 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would! ;)
Or at the least, let me put // @ts-check at the top of env.config.jsx to turn on VS Code's TypeScript checking, and let me write the configuration with auto-completion and type checking in the IDE.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use https://www.npmjs.com/package/glob to find the file with regex instead? It is easier to improve in the future.

Comment on lines 24 to 31
const envConfigPathJs = path.resolve(process.cwd(), './env.config.js');
const envConfigPathJsx = path.resolve(process.cwd(), './env.config.jsx');

if (fs.existsSync(envConfigPathJs)) {
envConfig = require(envConfigPathJs);
} else if (fs.existsSync(envConfigPathJsx)) {
envConfig = require(envConfigPathJsx);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[suggestion] I wonder if it might make sense to create a helper/utility function (e.g., getEnvConfigPath) that can be used both here and in jest.config.js? E.g.

// jest.config.js
const envConfigPath = getEnvConfigPath();

// returns nothing if `env.config` doesn't exist; otherwise, returns path to appropriate `env.config`.
const envConfigPath = getEnvConfigPath();
if (envConfigPath) {
  envConfig = require(envConfigPath);
}
// webpack.dev.config.js

let envConfig = {};
// returns nothing if `env.config` doesn't exist; otherwise, returns path to appropriate `env.config`.
const envConfigPath = getEnvConfigPath();
if (envConfigPath) {
  envConfig = require(envConfigPath);
}

Related, I might also recommend adding support for envConfig within webpack.dev-stage.config.js file as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What Adam said.

Plus, we need to document somewhere in the README that the .js file takes precedence if both exist.

@@ -45,12 +65,12 @@ if (process.env.ENABLE_NEW_RELIC !== 'false') {
agentID: process.env.NEW_RELIC_AGENT_ID || 'undefined_agent_id',
trustKey: process.env.NEW_RELIC_TRUST_KEY || 'undefined_trust_key',
licenseKey: process.env.NEW_RELIC_LICENSE_KEY || 'undefined_license_key',
applicationID: process.env.NEW_RELIC_APP_ID || 'undefined_application_id',
applicationID: envConfig.NEW_RELIC_APP_ID || process.env.NEW_RELIC_APP_ID || 'undefined_application_id',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[curious] Would we expect the other process.env.NEW_RELIC_* env vars might be usable with envConfig as well (e.g., agentID, trustKey, licenseKey, etc.)?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are y'all looking into pluggifying the NEW_RELIC stuff, yet? It would be great for the project if we didn't have to deal with it so specifically.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually went ahead and removed these changes as this would've meant using a require statement in this config to fetch the environment variables, and that got in the way of using import in the env.config.js file.

This will mean that there's no clear solution yet for if we ever want to replace the process.env.ENV_VARs in this file or webpack.dev.config.js.

@arbrandes arbrandes self-requested a review March 4, 2024 17:17
Copy link
Contributor

@arbrandes arbrandes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wish I had a specific community use-case in mind for JS config beyond the Tubular usage at edx.org, but I can't object in principle: it offers significant additional flexibility, at least in theory. I also take it means it'll make pluggability more practical.

Nevertheless, we need to make sure it's not the primary use case, at least not until Tutor can make use of it.

README.md Outdated
To use a private `env.config.js` file during the production build, the Webpack Production config will look for an env
variable `process.env.JS_CONFIG_FILEPATH`, which should represent a file path to the desired `env.config.js`.

The only requirement is that the filepath end with `env.config.*`, where either `.js` or `.jsx` as the extension
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The only requirement is that the filepath end with `env.config.*`, where either `.js` or `.jsx` as the extension
The only requirement is that the filepath end with `env.config.*`, with either `.js` or `.jsx` as the extension.


JS_CONFIG_FILEPATH="{HOME}/frontends/frontend-app-profile/stage.env.config.jsx"

## Requiring Jest to reference env.config.js
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean that an env.config.js will now be required for tests to run successfully?

Maybe it already is and I just missed it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, env.config.js isn't required to run tests, but if there are any env variables or configuration in the env.config.js file that should be used for tests, this is what will be needed in the setupTest.js file.

README.md Outdated
@@ -218,6 +217,31 @@ locally. To serve a production build locally:
attempt to run the build on the same port specified in the
`env.config.js` file.

## Creating a Production Build with env.config.js (using Tubular)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only place Tubular is mentioned. I feel like we should either remove the reference entirely, or add a section that explains how to use it. I lean towards the former.

Comment on lines 24 to 31
const envConfigPathJs = path.resolve(process.cwd(), './env.config.js');
const envConfigPathJsx = path.resolve(process.cwd(), './env.config.jsx');

if (fs.existsSync(envConfigPathJs)) {
envConfig = require(envConfigPathJs);
} else if (fs.existsSync(envConfigPathJsx)) {
envConfig = require(envConfigPathJsx);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What Adam said.

Plus, we need to document somewhere in the README that the .js file takes precedence if both exist.

config/webpack.dev.config.js Outdated Show resolved Hide resolved
config/webpack.prod.config.js Outdated Show resolved Hide resolved
@@ -45,12 +65,12 @@ if (process.env.ENABLE_NEW_RELIC !== 'false') {
agentID: process.env.NEW_RELIC_AGENT_ID || 'undefined_agent_id',
trustKey: process.env.NEW_RELIC_TRUST_KEY || 'undefined_trust_key',
licenseKey: process.env.NEW_RELIC_LICENSE_KEY || 'undefined_license_key',
applicationID: process.env.NEW_RELIC_APP_ID || 'undefined_application_id',
applicationID: envConfig.NEW_RELIC_APP_ID || process.env.NEW_RELIC_APP_ID || 'undefined_application_id',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are y'all looking into pluggifying the NEW_RELIC stuff, yet? It would be great for the project if we didn't have to deal with it so specifically.

*  this is due to the fact that if any 'import' was desired in env.config it would fail due to the 'require' of env.config
Comment on lines +12 to +15
if (fs.existsSync(appEnvConfigPathJs)) {
envConfigPath = appEnvConfigPathJs;
} else if (fs.existsSync(appEnvConfigPathJsx)) {
envConfigPath = appEnvConfigPathJsx;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a specific reason this logic prioritizes .js over .jsx? I don't have strong feelings either way, but the decision around the prioritization should be documented.

@MaxFrank13
Copy link
Member

Hello all! I have taken over this PR as Jason is out for the next couple weeks. I have read through comments/code and have some questions to help get me up to speed.

  1. .ts(x) support and prioritization

    • The recommendation to use glob seems straightforward but would introduce another dependency for frontend-build — are there any objections to adding this dependency?
    • W.r.t prioritization, I'm having a hard time understanding why there would ever be more than one configuration file. That sounds like an implementation mistake seeing as we don’t have a mechanism for combining multiple config files in the first place. So anyone with two config files has presumably made an error in their setup, no? Regardless, I'll be happy to sort this out... once I'm less confused 😆
  2. Same changes in jest config to go in dev and dev-stage configs

    • Should we add the config changes to the other config files? If my understanding is correct, this would enable us to use the config file path rather than putting env values directly in the MFE’s env.config.{js/jsx/ts/tsx} file
    • From what I gathered in the discussion, this was recommended as well as extracting the functionality into a utility to reduce code duplication. Just making sure I understand the suggestion before doing any work.
  3. Need for specific community use case

    • Is this still true post-adoption of FPF?
    • In other words, is FPF a sufficient primary use case?
  4. Clarification around jest.config and why it’s been modified

    • Allows tests to access env.config values if needed — do we need specific examples of when this would be done?
    • Do we have examples?

cc: @adamstankiewicz @arbrandes @jsnwesson @brian-smith-tcril @leangseu-edx

@arbrandes
Copy link
Contributor

As discussed in the last FWG meeting, I don't see the point of adding an .env variable, here. We already have webpack configuration that pulls in env.config.js* if present. It shouldn't be frontend-build's responsibility to copy that file in.

@MaxFrank13
Copy link
Member

Closed as we aren't going forward with changes to the prod.config and don't see an immediate need for the jest.config changes. It may just need to confusion as we haven't fully migrated to JS configs yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants