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

sync: master to alpha #345

Merged
merged 83 commits into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from 82 commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
922597b
fix(deps): update dependency cssnano to v6 (#344)
renovate[bot] Apr 25, 2023
6460083
fix(deps): update dependency html-webpack-plugin to v5.5.1
renovate[bot] Apr 25, 2023
f39fbdb
fix(deps): update dependency postcss to v8.4.23
renovate[bot] Apr 25, 2023
a35a129
fix(deps): update dependency webpack-cli to v5.0.2
renovate[bot] Apr 25, 2023
691d176
fix(deps): update dependency webpack-dev-server to v4.13.3
renovate[bot] Apr 25, 2023
d31d8d4
fix(deps): update dependency sass to v1.62.1
renovate[bot] Apr 26, 2023
5aacb29
fix: disable dot rule in historyApiFallback in webpack.dev.config.js …
adamstankiewicz May 2, 2023
5b8173e
fix(deps): update eslint (#351)
renovate[bot] May 4, 2023
5cc59c4
fix(deps): update dependency clean-webpack-plugin to v4 (#341)
renovate[bot] May 4, 2023
5fba996
fix(deps): update dependency @svgr/webpack to v7 (#340)
renovate[bot] May 4, 2023
d4ad548
fix(deps): update babel monorepo
renovate[bot] May 4, 2023
123a3cd
fix(deps): update dependency cssnano to v6.0.1
renovate[bot] May 4, 2023
cfc131b
fix(deps): update dependency webpack to v5.82.0 (#355)
renovate[bot] May 5, 2023
7024203
fix(deps): update dependency dotenv-webpack to v8 (#357)
renovate[bot] May 5, 2023
a35b6af
fix(deps): update dependency postcss-loader to v7 (#358)
renovate[bot] May 5, 2023
9661ec6
chore(deps): update dependency typescript to v5 (#338)
renovate[bot] May 5, 2023
4b5de3c
chore(deps): update peter-evans/enable-pull-request-automerge action …
renovate[bot] May 5, 2023
702cd6a
fix(deps): update dependency @edx/new-relic-source-map-webpack-plugin…
renovate[bot] May 5, 2023
a7605ee
fix(deps): update dependency postcss-rtlcss to v4 (#359)
renovate[bot] May 5, 2023
a066e38
fix(deps): update dependency @svgr/webpack to v8 (#364)
renovate[bot] May 26, 2023
d7eb52d
fix(deps): update dependency webpack-cli to v5.1.1 (#363)
renovate[bot] May 26, 2023
ed00478
fix(deps): update dependency postcss-loader to v7.3.1 (#367)
renovate[bot] May 26, 2023
5300a82
fix(deps): update dependency webpack-dev-server to v4.15.0 (#362)
renovate[bot] May 26, 2023
0503d71
fix(deps): update dependency eslint to v8.41.0 (#361)
renovate[bot] May 26, 2023
d5ea781
fix(deps): update dependency style-loader to v3.3.3 (#368)
renovate[bot] May 26, 2023
b90bc6b
fix(deps): update dependency sass-loader to v13 (#360)
renovate[bot] May 26, 2023
0301997
fix(deps): update dependency webpack-merge to v5.9.0 (#371)
renovate[bot] May 26, 2023
658d3d6
fix(deps): update dependency webpack to v5.84.1 (#370)
renovate[bot] May 26, 2023
8c62a1e
fix(deps): update dependency @edx/new-relic-source-map-webpack-plugin…
renovate[bot] May 26, 2023
94591ea
fix(deps): update dependency postcss-loader to v7.3.2
renovate[bot] May 28, 2023
efb62c3
fix(deps): update dependency postcss to v8.4.24
renovate[bot] May 28, 2023
a21bbed
fix(deps): update dependency sass-loader to v13.3.1
renovate[bot] May 28, 2023
0b17a12
fix(deps): update dependency webpack-cli to v5.1.2
renovate[bot] Jun 4, 2023
2353933
fix(deps): update dependency webpack-cli to v5.1.3
renovate[bot] Jun 4, 2023
7dafaa4
fix(deps): update dependency webpack-cli to v5.1.4
renovate[bot] Jun 7, 2023
117cc85
fix(deps): update dependency webpack to v5.86.0 (#376)
renovate[bot] Jun 8, 2023
60109a9
fix(deps): update dependency sass to v1.63.2 (#382)
renovate[bot] Jun 8, 2023
8053dc6
fix(deps): update dependency webpack-bundle-analyzer to v4.9.0 (#377)
renovate[bot] Jun 9, 2023
fabfac6
fix(deps): update babel monorepo to v7.22.5 (#372)
renovate[bot] Jun 9, 2023
4efd1e1
fix(deps): update eslint (#378)
renovate[bot] Jun 9, 2023
f36ad79
fix(deps): update dependency html-webpack-plugin to v5.5.2
renovate[bot] Jun 9, 2023
c58fc18
fix(deps): update dependency sass to v1.63.3
renovate[bot] Jun 9, 2023
d3ddfb3
fix(deps): update dependency webpack-dev-server to v4.15.1
renovate[bot] Jun 9, 2023
562d39c
fix(deps): update dependency sass-loader to v13.3.2
renovate[bot] Jun 10, 2023
3d55a31
fix(deps): update dependency postcss-loader to v7.3.3
renovate[bot] Jun 10, 2023
435c5c9
fix(deps): update dependency html-webpack-plugin to v5.5.3
renovate[bot] Jun 10, 2023
d6449b2
fix(deps): update dependency postcss-custom-media to v9.1.4
renovate[bot] Jun 13, 2023
dff1569
chore(deps): update react monorepo
renovate[bot] Jun 13, 2023
e239829
fix(deps): update dependency sharp to v0.32.1
renovate[bot] Jun 13, 2023
4bcf6a2
fix(deps): update dependency sass to v1.63.4
renovate[bot] Jun 14, 2023
4b77d46
chore(deps): update actions/setup-node action to v3 (#396)
renovate[bot] Jun 22, 2023
020e5bc
chore(deps): update actions/checkout action to v3 (#395)
renovate[bot] Jun 22, 2023
8414012
fix(deps): update dependency image-minimizer-webpack-plugin to v3.8.3
renovate[bot] Jun 22, 2023
b99aced
fix(deps): update dependency postcss-custom-media to v9.1.5
renovate[bot] Jun 22, 2023
f8c9215
fix(deps): update dependency sass to v1.63.6
renovate[bot] Jun 22, 2023
9231eb7
fix(deps): update eslint (#402)
renovate[bot] Jul 6, 2023
b677c39
fix(deps): update dependency postcss to v8.4.25
renovate[bot] Jul 6, 2023
c459497
fix(deps): update dependency babel-loader to v9.1.3
renovate[bot] Jul 7, 2023
23f52e1
fix: updated jest to resolve word-wrap ReDoS vulnerability (#411)
BilalQamar95 Jul 11, 2023
9cd2d02
fix(deps): update dependency sharp to v0.32.2
renovate[bot] Jul 11, 2023
a8b68f7
fix: bump semver from 5.7.1 to 5.7.2 (#414)
dependabot[bot] Jul 12, 2023
467d2fb
fix(deps): update dependency @babel/eslint-parser to v7.22.9
renovate[bot] Jul 12, 2023
51d678d
fix(deps): update dependency postcss to v8.4.26
renovate[bot] Jul 13, 2023
cd30a3f
fix(deps): update dependency sharp to v0.32.3
renovate[bot] Jul 14, 2023
c73a797
fix(deps): update dependency webpack to v5.88.1 (#403)
renovate[bot] Jul 17, 2023
e2d0115
fix(deps): update dependency webpack to v5.88.2
renovate[bot] Jul 18, 2023
5b96343
feat: add fedx-scripts serve (#404)
adamstankiewicz Jul 18, 2023
d3a87bf
fix(deps): update dependency postcss-custom-media to v9.1.5
renovate[bot] Jul 18, 2023
049c0c6
fix(deps): update dependency sharp to v0.32.3
renovate[bot] Jul 18, 2023
4f62b40
fix: ensure .env.development PORT works (#423)
adamstankiewicz Jul 18, 2023
0f8f544
fix: silence sass compiler warnings (#425)
adamstankiewicz Jul 19, 2023
0081949
fix: reverted jest upgrade (#427)
BilalQamar95 Jul 25, 2023
ad42423
fix: update webpack common config to fix errors (#428)
solababs Aug 2, 2023
5b14ea3
fix(deps): update dependency sass to v1.65.1 (#426)
renovate[bot] Aug 15, 2023
5231d82
fix(deps): update dependency postcss-custom-media to v10 (#407)
renovate[bot] Aug 15, 2023
2d1ac6c
chore(deps): update dependency @types/react to v17.0.64
renovate[bot] Aug 15, 2023
c0763cd
fix(deps): update dependency @pmmmwh/react-refresh-webpack-plugin to …
renovate[bot] Aug 15, 2023
8011912
fix(deps): update dependency autoprefixer to v10.4.15
renovate[bot] Aug 15, 2023
2d5e80f
fix(deps): update dependency postcss to v8.4.27
renovate[bot] Aug 15, 2023
9d08508
fix(deps): update dependency postcss-rtlcss to v4.0.7
renovate[bot] Aug 15, 2023
9c4dac8
fix(deps): update dependency sharp to v0.32.4
renovate[bot] Aug 15, 2023
43c42f0
fix(deps): update dependency postcss to v8.4.28
renovate[bot] Aug 15, 2023
25abc90
fix(deps): update dependency sharp to v0.32.5
renovate[bot] Aug 16, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/sync-master-alpha.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ jobs:
name: Syncing branches
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Set up Node
uses: actions/setup-node@v1
uses: actions/setup-node@v3
with:
node-version: 18
- name: Create Pull Request
Expand All @@ -29,7 +29,7 @@ jobs:
pull-request-number: ${{ steps.cpr.outputs.PULL_REQUEST_NUMBER }}
github-token: ${{ secrets.requirements_bot_github_token }}
- name: Enable Pull Request Automerge
uses: peter-evans/enable-pull-request-automerge@v2
uses: peter-evans/enable-pull-request-automerge@v3
with:
pull-request-number: ${{ steps.cpr.outputs.PULL_REQUEST_NUMBER }}
token: ${{ secrets.requirements_bot_github_token }}
15 changes: 13 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Usage
-----

CLI commands are structured: ``fedx-scripts <targetScript> <options>``. Options
are passed on to the target script, so refer to each target script's cli
are passed on to the target script, so refer to each target script's CLI
documentation to learn what options are available. Example package.json::

{
Expand All @@ -31,7 +31,8 @@ documentation to learn what options are available. Example package.json::
"precommit": "npm run lint",
"snapshot": "fedx-scripts jest --updateSnapshot",
"start": "fedx-scripts webpack-dev-server --progress",
"test": "fedx-scripts jest --coverage --passWithNoTests"
"test": "fedx-scripts jest --coverage --passWithNoTests",
"serve": "fedx-scripts serve"
},
"dependencies": {
...
Expand Down Expand Up @@ -157,6 +158,16 @@ You may create a `.env.private` with any overrides of the environment settings c

**Note: .env.private should be added to your project's .gitignore so it does not get checked in.**

Serving a production Webpack build locally
------------------------------------------

In some scenarios, you may want to run a production Webpack build locally. To serve a production build locally:

#. Create an ``env.config.js`` file containing the configuration for local development, with the exception of ``NODE_ENV='production'``.
#. Run ``npm run build`` to build the production assets. The output assets will rely on the local development configuration specified in the prior step.
#. Add an NPM script ``serve`` to your application's ``package.json`` (i.e., ``"serve": "fedx-scripts serve"``).
#. Run ``npm run serve`` to serve your production build assets. It will attempt to run the build on the same port specified in the ``env.config.js`` file.

Development
-----------

Expand Down
8 changes: 7 additions & 1 deletion bin/fedx-scripts.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#!/usr/bin/env node

const chalk = require('chalk');

const presets = require('../lib/presets');

/**
Expand Down Expand Up @@ -65,6 +68,9 @@ switch (commandName) {
ensureConfigOption(presets.webpackDevServer);
require('webpack-dev-server/bin/webpack-dev-server');
break;
case 'serve':
require('../lib/scripts/serve');
break;
default:
console.warn(`fedx-scripts: The command ${commandName} is unsupported`);
console.log(chalk.red(`[ERROR] fedx-scripts: The command ${chalk.bold.red(commandName)} is unsupported.`));
}
18 changes: 18 additions & 0 deletions config/webpack.common.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,22 @@ module.exports = {
},
extensions: ['.js', '.jsx'],
},
ignoreWarnings: [
// Ignore warnings raised by source-map-loader.
// some third party packages may ship miss-configured sourcemaps, that interrupts the build
// See: https://github.com/facebook/create-react-app/discussions/11278#discussioncomment-1780169
/**
*
* @param {import('webpack').WebpackError} warning
* @returns {boolean}
*/
function ignoreSourcemapsloaderWarnings(warning) {
return (
warning.module
&& warning.module.resource.includes('node_modules')
&& warning.details
&& warning.details.includes('source-map-loader')
);
},
],
};
3 changes: 3 additions & 0 deletions config/webpack.dev-stage.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ module.exports = merge(commonConfig, {
path.join(process.cwd(), 'node_modules'),
path.join(process.cwd(), 'src'),
],
// silences compiler warnings regarding deprecation warnings
quietDeps: true,
},
},
},
Expand Down Expand Up @@ -173,6 +175,7 @@ module.exports = merge(commonConfig, {
https: true,
historyApiFallback: {
index: path.join(PUBLIC_PATH, 'index.html'),
disableDotRule: true,
},
// Enable hot reloading server. It will provide WDS_SOCKET_PATH endpoint
// for the WebpackDevServer client so it can learn when the files were
Expand Down
3 changes: 3 additions & 0 deletions config/webpack.dev.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ module.exports = merge(commonConfig, {
path.join(process.cwd(), 'node_modules'),
path.join(process.cwd(), 'src'),
],
// silences compiler warnings regarding deprecation warnings
quietDeps: true,
},
},
},
Expand Down Expand Up @@ -175,6 +177,7 @@ module.exports = merge(commonConfig, {
port: process.env.PORT || 8080,
historyApiFallback: {
index: path.join(PUBLIC_PATH, 'index.html'),
disableDotRule: true,
},
// Enable hot reloading server. It will provide WDS_SOCKET_PATH endpoint
// for the WebpackDevServer client so it can learn when the files were
Expand Down
3 changes: 2 additions & 1 deletion config/webpack.prod.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// optimized bundles at the expense of a longer build time.

const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const { merge } = require('webpack-merge');
Expand Down Expand Up @@ -132,6 +131,8 @@ module.exports = merge(commonConfig, {
path.join(process.cwd(), 'node_modules'),
path.join(process.cwd(), 'src'),
],
// silences compiler warnings regarding deprecation warnings
quietDeps: true,
},
},
},
Expand Down
37 changes: 37 additions & 0 deletions docs/0003-fedx-scripts-serve.md
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 added example/.env
Empty file.
1 change: 1 addition & 0 deletions example/.env.development
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'
3 changes: 2 additions & 1 deletion example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"build": "../bin/fedx-scripts.js webpack",
"lint": "../bin/fedx-scripts.js eslint . --ext .jsx,.js",
"babel": "../bin/fedx-scripts.js babel src --out-dir dist/babel --source-maps --ignore **/*.test.jsx,**/*.test.js --copy-files",
"start": "../bin/fedx-scripts.js webpack-dev-server"
"start": "../bin/fedx-scripts.js webpack-dev-server",
"serve": "../bin/fedx-scripts.js serve"
},
"keywords": [],
"author": "",
Expand Down
78 changes: 78 additions & 0 deletions lib/scripts/serve.js
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}...`));
});
}
Loading