Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
77 changes: 5 additions & 72 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,89 +18,24 @@ It will replace:

The new frontend framework will completely take over responsibility for the functionality of those libraries, and will also include a "shell" application.

It will enable Open edX frontends to be loaded as "module plugins" via Webpack module federation, or as "direct plugins" as part of a single, unified application. It will also support creation of "project" repositories as a central place to check in an Open edX instance's frontend customizations and extensions.
It will enable Open edX frontends to be loaded as "direct plugins" as part of a single, unified application. It will also support creation of "project" repositories as a central place to check in an Open edX instance's frontend customizations and extensions.

## Further reading

- [Frontend Glossary](./docs/frontend-glossary.md)
- [OEP-65: Frontend composability](https://open-edx-proposals.readthedocs.io/en/latest/architectural-decisions/oep-0065-arch-frontend-composability.html)
- [ADR 0001: Create a unified platform library](https://github.com/openedx/open-edx-proposals/pull/598)
- [Discourse discussion on frontend projects](https://discuss.openedx.org/t/oep-65-adjacent-a-frontend-architecture-vision/13223)

## Communication

This project uses the [#module-federation](https://openedx.slack.com/archives/C06HRLTP3E0) channel in Open edX Slack.

You can follow ongoing progress on the project's [Github project board](https://github.com/orgs/openedx/projects/65/views/1).

Feel free to reach out to David Joy ([Github](https://github.com/davidjoy), [Slack](https://openedx.slack.com/team/UFM4FEN0J)) with any questions.
Feel free to reach out in [#wg-frontend on Slack](https://openedx.slack.com/archives/C04BM6YC7A6) with any questions.

## Development

This library is under development and has not yet been published to npm.

Its functionality can be tested with a few other companion repositories that have been built to work with it:

- https://github.com/davidjoy/frontend-app-base-test
- https://github.com/davidjoy/frontend-project-test
- https://github.com/davidjoy/frontend-project-module-test

To start the whole thing together:

- Check out https://github.com/davidjoy/frontend-base and the above three repositories as siblings.
- Run `npm install` on all of them.
- Run `npm run temp:refresh-all` in frontend-base.
- Run `npm run pack frontend-project-test` in frontend-app-base-test.
- Run `npm run pack frontend-project-module-test` in frontend-app-base-test.
- You'll need 3 terminal windows.
- Run `npm run dev` in `frontend-project-test`
- Run `npm run dev:module` in `frontend-app-base-test`
- Run `npm run dev:module` in `frontend-project-module-test
- Visit `http://localhost:8080` in your browser to see the unified site.

What this site is showing you:

- The shell (header, footer, app initialization) is being loaded from `frontend-base` through `frontend-project-test`. The `site.config.dev.tsx` file in `frontend-project-test` has configured the site.
- `ModuleOne` from `frontend-app-base-test` is being loaded _through_ the `site.config.dev.tsx` file in `frontend-project-test` as an imported dependency.
- `ModuleTwo` is being loaded at runtime from the module federation dev server in `frontend-app-base-test`.
- `ModuleThree` is being loaded at runtime from the module federation dev server in `frontend-project-module-test`.

Read below for more details about the companion repositories.

### frontend-app-base-test

https://github.com/davidjoy/frontend-app-base-test

This is an "MFE" repository with three modules in it which can be loaded into a shell. It can be tested in a few different ways.

- `npm run dev:module` - This will run a dev server and build the app as modules for module federation.
- `npm run dev` - This will run the a dev server and build the app as part of a shell with three imported modules.
- `npm run pack <frontend-project-test|frontend-project-module-test>` - this will package the library into an npm compatible `.tgz` file for use with the project repositories below.

### frontend-project-test

This is a "project" repository, which is a new thing. A project is where you put your customizations to the frontend.

The `frontend-project-test` project has been configured in its `site.config.dev.tsx` file to load the three modules from `frontend-app-base-test` in three different ways:

- Module One is loaded as an imported app, using frontend-app-base-test as a dependency of the project installed via `npm run pack` above.
- Module Two is loaded via module federation from the `npm run dev:module` dev server in `frontend-app-base-test`
- Module Three is loaded via module federation from the `npm run dev:module` dev server in `frontend-project-module-test`.

It can be tested with:

- `npm run dev` - This will start up a dev server with the new shell application and load the three modules into it via the methods described above.

### frontend-project-module-test

This is also a "project" repository, demonstrating that you can use module federation with a released library version of `frontend-app-base-test`, rather than by cloning the app and running a dev server in it. This is more appropriate for customizations of the app because you can check all your customizations in to the project, rather than needing to copy/paste them into the frontend-app-* repository at build time, which is awkward.

It can be tested with:

- `npm run dev:module` - This starts up a dev server that serves the modules from `frontend-app-base-test` for module federation, the same as running `npm run dev:module` in the `frontend-app-base-test` repository itself.

It's worth noting that this project has a new type of file: `build.dev.config.js` which is necessary to configure webpack to understand what modules it should be packaging for module federation. We can't use `site.config.dev.tsx` for this purpose, since that's runtime code.

## Migrating an MFE to `frontend-base` (Work in progress)

See the [Frontend App Migration How To](./docs/how_tos/migrate-frontend-app.md).
Expand All @@ -121,19 +56,18 @@ Then move the files out of the way (move src to some other sub-dir, mostly) to m

### Latest repository merges

- frontend-component-header - Up to date as of 9/12/2024
- frontend-component-footer - Up to date as of 9/12/2024
- frontend-build - Up to date as of 9/12/2024

- frontend-platform - Up to date as of 9/13/2024
- frontend-plugin-framework - Up to date as of 9/13/2024
- frontend-component-header - Up to date as of 9/12/2024
- frontend-component-footer - Up to date as of 9/12/2024

# Other notable changes

- Cease using `AUTHN_MINIMAL_HEADER`, replace it with an actual minimal header.
- No more using `process.env` in runtime code.
- Removed dotenv. Use site.config.tsx.
- Removed Purge CSS. We do not believe that Purge CSS works properly with Paragon in general, and it is also fundamentally incompatible with module federation as an architecture.
- Removed Purge CSS. We do not believe that Purge CSS works properly with Paragon in general.
- Removed `ensureConfig` function. This sort of type safety should happen with TypeScript types in the site config file.
- Removed `ensureDefinedConfig` function. Similar to ensureConfig, this sort of type safety should be handled by TypeScript.
- A number of site config variables now have sensible defaults:
Expand Down Expand Up @@ -188,7 +122,6 @@ MFE_CONFIG = {
"""
)
)

```

Customizing the MFE config API:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ We will move the code from these libraries into `frontend-base`. We decided we

### Migration Order

We chose to move `frontend-build` first as the foundation upon which all the others will be built. A modified version of `frontend-build` will be used to build the shell and provide build scripts to the frontend apps which support webpack module federation, amongst other things.
We chose to move `frontend-build` first as the foundation upon which all the others will be built. A modified version of `frontend-build` will be used to build the shell, amongst other things.

Following frontend build, we will move `frontend-platform` and validate that this repository can act as a replacement for `frontend-build` and `frontend-platform` together. At this point, micro-frontend repositories could be migrated to use this library instead of `frontend-build` and `frontend-platform`.

Expand Down
29 changes: 1 addition & 28 deletions docs/how_tos/migrate-frontend-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,7 @@ With the exception of any custom scripts, replace the `scripts` section of your
"scripts": {
"build": "PORT=YOUR_PORT openedx build",
"build:legacy": "openedx build:legacy", // TODO: Does this target exist?
"build:module": "PORT=YOUR_PORT openedx build:module",
"dev": "PORT=YOUR_PORT openedx dev",
"dev:module": "PORT=YOUR_PORT openedx dev:module",
"dev:legacy": "PORT=YOUR_PORT openedx dev:legacy",
"i18n_extract": "openedx formatjs extract",
"lint": "openedx lint .",
Expand All @@ -136,11 +134,10 @@ With the exception of any custom scripts, replace the `scripts` section of your

## 5. Other package.json edits

- `main` and `module`
- `main`

```diff
+ "main": "src/index.ts",
+ "module": "src/index.ts",
```

- `sideEffects`
Expand All @@ -156,30 +153,6 @@ This means that the code from the library can be safely tree-shaken by webpack.

// TODO: Maybe put scss and css files in side effects. They have side effects and need to be excluded so they get bundled.

- `config`

You must add a "config" section to package.json that describes the modules that the library exports. This includes a camelCase `name` for the remote that hosts all your packages. This name must be unique across all the libraries in a frontend, and so including your organization name is encouraged. For an Open edX default library called `frontend-app-my-library`, a good name would be `openedxMyLibrary`.

The config block must also include an `exposes` configuration that describes your modules.

```diff
+ "config": {
+ "name": "openedxMyLibrary",
+ "exposes": {
+ "./ModuleOne": "./src/module-one",
+ "./ModuleTwo": "./src/module-two",
+ "./ModuleThree": "./src/module-three"
+ }
+ },
```

If you used the "exports" field in package.json it changes the way importing/requiring/TS/node works and everything starts to break.

The entries in `exposes` are:

1. A key that is compatible with the [Package entry points](https://nodejs.org/api/packages.html#package-entry-points) specification. Generally the name of your module prefixed with `./`.
2. The actual path to the module in your source code. In the above example, `./ModuleOne` is the name that module federation will refer to, and `./src/module-one` is pointing to an `./src/module-one/index.tsx` file that exports the module. It is also acceptable to point at a non-index file such as `./src/module-one/ModuleOne.tsx` if that's how your code is structured.

## 6. Add a Type Declaration file (app.d.ts)

Create an `app.d.ts` file in the root of your MFE with the following contents:
Expand Down
Loading
Loading