-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #431 from openedx/bw/alpha_to_master
Bw/alpha to master
- Loading branch information
Showing
14 changed files
with
3,326 additions
and
4,773 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# Serving production Webpack builds locally with `fedx-scripts` | ||
|
||
## Summary | ||
|
||
The build-and-deploy process for micro-frontends (MFEs) throughout Open edX include running the MFE through a production Webpack build process, relying on configuration specified in a `webpack.prod.config.js` file. The resulting file assets are what ultimately get released to production and served to users. However, it is currently non-obvious how to preview the production file assets generated by `npm run build` locally should the need arise (e.g., to have more confidence in the resulting Webpack output and/or behavior before relying on the build-and-deploy process to release to a staging/production environment). | ||
|
||
## Context | ||
|
||
Most micro-frontends (MFEs) throughout the Open edX platform rely on a `npm run build` script that runs a production Webpack build based on the configuration specified in a `webpack.prod.config.js` file. The `webpack-prod.config.js` may be provided either by consumers in the root of their MFE's repository (i.e., typically using `createConfig` to extend/override parts of the default production Webpack configuration), or simply rely on the default `webpack.prod.config.js` configuration file provided by `@edx/frontend-build`. | ||
|
||
The output from `npm run build` is generated in a Git-ignored `dist` directory, and contains the actual files that should be deployed to production. | ||
|
||
Included in the `dist` directory's files is the MFE's `index.html` file that needs to be served for all routes the user may try loading. By simply loading `index.html` in the browser, it will inevitably run into some issues (e.g., not supporting React routing, etc.). | ||
|
||
To mitigate this, this ADR describes a new mechanism to provide a standard, documented way to serve the generated assets from the production Webpack build when running `npm run build`. | ||
|
||
# Decision | ||
|
||
We will create a new `serve` command for `fedx-scripts` that creates an Express.js server to run the generated `dist` file assets (e.g., `index.html`) on the `PORT` specified in the MFE's `env.config.js` and/or `.env.development|private` file(s) on `localhost`. | ||
|
||
If no `env.config.js` and/or `.env.development|private` file(s) exist and/or no `PORT` setting is specified those files, the `serve` command will fallback to a default port 8080, which is similar to the default ports our typical example MFE applications use. | ||
|
||
# Implementation | ||
|
||
The new `serve` command will live as under a new `scripts` directory under `lib`. | ||
|
||
Once in place, a MFE application may add a `serve` script to its NPM scripts in the `package.json` file: | ||
|
||
```json | ||
{ | ||
"scripts": { | ||
"serve": "fedx-scripts serve" | ||
} | ||
} | ||
``` | ||
|
||
Then, running `npm run serve` in the root of that MFE application will run the new `serve` command in `@edx/frontend-build`, serving the assets in the MFE's `dist` directory on the `PORT` specified in the `env.config.js` file or `.env.development|private` file(s). |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
PORT=3000 | ||
FAVICON_URL=https://edx-cdn.org/v3/default/favicon.ico | ||
TEST_VARIABLE='foo' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
const express = require('express'); | ||
const path = require('path'); | ||
const fs = require('fs'); | ||
const chalk = require('chalk'); | ||
const dotenv = require('dotenv'); | ||
|
||
const resolvePrivateEnvConfig = require('../resolvePrivateEnvConfig'); | ||
|
||
// Add process env vars. Currently used only for setting the | ||
// server port and the publicPath | ||
dotenv.config({ | ||
path: path.resolve(process.cwd(), '.env.development'), | ||
}); | ||
|
||
// Allow private/local overrides of env vars from .env.development for config settings | ||
// that you'd like to persist locally during development, without the risk of checking | ||
// in temporary modifications to .env.development. | ||
resolvePrivateEnvConfig('.env.private'); | ||
|
||
function isDirectoryEmpty(directoryPath) { | ||
try { | ||
const files = fs.readdirSync(directoryPath); | ||
return files.length === 0; | ||
} catch (error) { | ||
if (error.code === 'ENOENT') { | ||
// Directory does not exist, so treat it as empty. | ||
return true; | ||
} | ||
throw error; // Throw the error for other cases | ||
} | ||
} | ||
|
||
const buildPath = path.join(process.cwd(), 'dist'); | ||
const buildPathIndex = path.join(buildPath, 'index.html'); | ||
|
||
const fallbackPort = 8080; | ||
|
||
if (isDirectoryEmpty(buildPath)) { | ||
const formattedBuildCmd = chalk.bold.redBright('``npm run build``'); | ||
console.log(chalk.bold.red(`ERROR: No build found. Please run ${formattedBuildCmd} first.`)); | ||
} else { | ||
let configuredPort; | ||
|
||
try { | ||
configuredPort = require(path.join(process.cwd(), 'env.config.js'))?.PORT; | ||
} catch (error) { | ||
// Pass. Consuming applications may not have an `env.config.js` file. This is OK. | ||
} | ||
|
||
if (!configuredPort) { | ||
configuredPort = process.env.PORT; | ||
} | ||
|
||
// No `PORT` found in `env.config.js` and/or `.env.development|private`, so output a warning. | ||
if (!configuredPort) { | ||
const formattedEnvDev = chalk.bold.yellowBright('.env.development'); | ||
const formattedEnvConfig = chalk.bold.yellowBright('env.config.js'); | ||
const formattedPort = chalk.bold.yellowBright(fallbackPort); | ||
console.log(chalk.yellow(`No port found in ${formattedEnvDev} and/or ${formattedEnvConfig} file(s). Falling back to port ${formattedPort}.\n`)); | ||
} | ||
|
||
const app = express(); | ||
|
||
// Fallback to standard example port if no PORT config is set. | ||
const PORT = configuredPort || fallbackPort; | ||
|
||
app.use(express.static(buildPath)); | ||
|
||
app.use('*', (req, res) => { | ||
res.sendFile(buildPathIndex); | ||
}); | ||
|
||
app.listen(PORT, () => { | ||
const formattedServedFile = chalk.bold.cyanBright(buildPathIndex); | ||
const formattedPort = chalk.bold.cyanBright(PORT); | ||
console.log(chalk.greenBright(`Serving ${formattedServedFile} on port ${formattedPort}...`)); | ||
}); | ||
} |
Oops, something went wrong.