@edx/frontend-platform 4.6.2 → 4.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/.env.development +0 -30
- package/.env.test +0 -30
- package/.eslintignore +0 -6
- package/.eslintrc.js +0 -28
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -13
- package/.github/workflows/add-depr-ticket-to-depr-board.yml +0 -19
- package/.github/workflows/add-remove-label-on-comment.yml +0 -20
- package/.github/workflows/ci.yml +0 -42
- package/.github/workflows/commitlint.yml +0 -10
- package/.github/workflows/lockfileversion-check.yml +0 -13
- package/.github/workflows/manual-publish.yml +0 -43
- package/.github/workflows/npm-deprecate.yml +0 -22
- package/.github/workflows/release.yml +0 -45
- package/.github/workflows/self-assign-issue.yml +0 -12
- package/.github/workflows/update-browserslist-db.yml +0 -12
- package/.nvmrc +0 -1
- package/.releaserc +0 -32
- package/catalog-info.yaml +0 -21
- package/dist/LICENSE +0 -661
- package/dist/README.md +0 -155
- package/dist/package.json +0 -86
- package/docs/addTagsPlugin.js +0 -10
- package/docs/auth-API.md +0 -114
- package/docs/decisions/0001-record-architecture-decisions.rst +0 -32
- package/docs/decisions/0002-frontend-base-design-goals.rst +0 -222
- package/docs/decisions/0003-consolidation-into-frontend-platform.rst +0 -71
- package/docs/decisions/0004-axios-caching-implementation.rst +0 -88
- package/docs/decisions/0005-token-null-after-successful-refresh.rst +0 -69
- package/docs/decisions/0006-middleware-support-for-http-clients.rst +0 -44
- package/docs/decisions/0007-javascript-file-configuration.rst +0 -143
- package/docs/how_tos/automatic-case-conversion.rst +0 -58
- package/docs/how_tos/caching.rst +0 -93
- package/docs/how_tos/i18n.rst +0 -305
- package/docs/removeExport.js +0 -24
- package/docs/template/edx/README.md +0 -12
- package/docs/template/edx/publish.js +0 -713
- package/docs/template/edx/static/fonts/OpenSans-Bold-webfont.eot +0 -0
- package/docs/template/edx/static/fonts/OpenSans-Bold-webfont.svg +0 -1830
- package/docs/template/edx/static/fonts/OpenSans-Bold-webfont.woff +0 -0
- package/docs/template/edx/static/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
- package/docs/template/edx/static/fonts/OpenSans-BoldItalic-webfont.svg +0 -1830
- package/docs/template/edx/static/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
- package/docs/template/edx/static/fonts/OpenSans-Italic-webfont.eot +0 -0
- package/docs/template/edx/static/fonts/OpenSans-Italic-webfont.svg +0 -1830
- package/docs/template/edx/static/fonts/OpenSans-Italic-webfont.woff +0 -0
- package/docs/template/edx/static/fonts/OpenSans-Light-webfont.eot +0 -0
- package/docs/template/edx/static/fonts/OpenSans-Light-webfont.svg +0 -1831
- package/docs/template/edx/static/fonts/OpenSans-Light-webfont.woff +0 -0
- package/docs/template/edx/static/fonts/OpenSans-LightItalic-webfont.eot +0 -0
- package/docs/template/edx/static/fonts/OpenSans-LightItalic-webfont.svg +0 -1835
- package/docs/template/edx/static/fonts/OpenSans-LightItalic-webfont.woff +0 -0
- package/docs/template/edx/static/fonts/OpenSans-Regular-webfont.eot +0 -0
- package/docs/template/edx/static/fonts/OpenSans-Regular-webfont.svg +0 -1831
- package/docs/template/edx/static/fonts/OpenSans-Regular-webfont.woff +0 -0
- package/docs/template/edx/static/scripts/linenumber.js +0 -25
- package/docs/template/edx/static/scripts/prettify/Apache-License-2.0.txt +0 -202
- package/docs/template/edx/static/scripts/prettify/lang-css.js +0 -2
- package/docs/template/edx/static/scripts/prettify/prettify.js +0 -28
- package/docs/template/edx/static/styles/jsdoc-default.css +0 -356
- package/docs/template/edx/static/styles/prettify-jsdoc.css +0 -111
- package/docs/template/edx/static/styles/prettify-tomorrow.css +0 -132
- package/docs/template/edx/tmpl/augments.tmpl +0 -10
- package/docs/template/edx/tmpl/container.tmpl +0 -196
- package/docs/template/edx/tmpl/details.tmpl +0 -143
- package/docs/template/edx/tmpl/example.tmpl +0 -2
- package/docs/template/edx/tmpl/examples.tmpl +0 -13
- package/docs/template/edx/tmpl/exceptions.tmpl +0 -32
- package/docs/template/edx/tmpl/layout.tmpl +0 -39
- package/docs/template/edx/tmpl/mainpage.tmpl +0 -10
- package/docs/template/edx/tmpl/members.tmpl +0 -38
- package/docs/template/edx/tmpl/method.tmpl +0 -131
- package/docs/template/edx/tmpl/modifies.tmpl +0 -14
- package/docs/template/edx/tmpl/params.tmpl +0 -131
- package/docs/template/edx/tmpl/properties.tmpl +0 -108
- package/docs/template/edx/tmpl/returns.tmpl +0 -19
- package/docs/template/edx/tmpl/source.tmpl +0 -8
- package/docs/template/edx/tmpl/tutorial.tmpl +0 -19
- package/docs/template/edx/tmpl/type.tmpl +0 -7
- package/env.config.js +0 -8
- package/jsdoc.json +0 -36
- package/openedx.yaml +0 -12
- package/service-interface.png +0 -0
- package/src/analytics/MockAnalyticsService.js +0 -71
- package/src/analytics/SegmentAnalyticsService.js +0 -243
- package/src/analytics/index.js +0 -12
- package/src/analytics/interface.js +0 -142
- package/src/auth/AxiosCsrfTokenService.js +0 -60
- package/src/auth/AxiosJwtAuthService.js +0 -364
- package/src/auth/AxiosJwtTokenService.js +0 -134
- package/src/auth/LocalForageCache.js +0 -78
- package/src/auth/MockAuthService.js +0 -285
- package/src/auth/index.js +0 -19
- package/src/auth/interceptors/createCsrfTokenProviderInterceptor.js +0 -37
- package/src/auth/interceptors/createJwtTokenProviderInterceptor.js +0 -38
- package/src/auth/interceptors/createProcessAxiosRequestErrorInterceptor.js +0 -20
- package/src/auth/interceptors/createRetryInterceptor.js +0 -72
- package/src/auth/interface.js +0 -309
- package/src/auth/utils.js +0 -105
- package/src/config.js +0 -327
- package/src/constants.js +0 -66
- package/src/i18n/countries.js +0 -57
- package/src/i18n/index.js +0 -123
- package/src/i18n/injectIntlWithShim.jsx +0 -45
- package/src/i18n/languages.js +0 -60
- package/src/i18n/lib.js +0 -282
- package/src/i18n/scripts/README.md +0 -29
- package/src/i18n/scripts/intl-imports.js +0 -259
- package/src/i18n/scripts/transifex-utils.js +0 -75
- package/src/index.js +0 -42
- package/src/initialize.js +0 -357
- package/src/logging/MockLoggingService.js +0 -31
- package/src/logging/NewRelicLoggingService.js +0 -181
- package/src/logging/index.js +0 -9
- package/src/logging/interface.js +0 -110
- package/src/pubSub.js +0 -47
- package/src/react/AppContext.jsx +0 -24
- package/src/react/AppProvider.jsx +0 -93
- package/src/react/AuthenticatedPageRoute.jsx +0 -60
- package/src/react/ErrorBoundary.jsx +0 -44
- package/src/react/ErrorPage.jsx +0 -76
- package/src/react/LoginRedirect.jsx +0 -16
- package/src/react/OptionalReduxProvider.jsx +0 -28
- package/src/react/PageRoute.jsx +0 -31
- package/src/react/hooks.js +0 -50
- package/src/react/index.js +0 -16
- package/src/scripts/GoogleAnalyticsLoader.js +0 -53
- package/src/scripts/index.js +0 -2
- package/src/testing/index.js +0 -9
- package/src/testing/initializeMockApp.js +0 -77
- package/src/testing/mockMessages.js +0 -21
- package/src/utils.js +0 -167
- /package/{dist/analytics → analytics}/MockAnalyticsService.js +0 -0
- /package/{dist/analytics → analytics}/MockAnalyticsService.js.map +0 -0
- /package/{dist/analytics → analytics}/SegmentAnalyticsService.js +0 -0
- /package/{dist/analytics → analytics}/SegmentAnalyticsService.js.map +0 -0
- /package/{dist/analytics → analytics}/index.js +0 -0
- /package/{dist/analytics → analytics}/index.js.map +0 -0
- /package/{dist/analytics → analytics}/interface.js +0 -0
- /package/{dist/analytics → analytics}/interface.js.map +0 -0
- /package/{dist/auth → auth}/AxiosCsrfTokenService.js +0 -0
- /package/{dist/auth → auth}/AxiosCsrfTokenService.js.map +0 -0
- /package/{dist/auth → auth}/AxiosJwtAuthService.js +0 -0
- /package/{dist/auth → auth}/AxiosJwtAuthService.js.map +0 -0
- /package/{dist/auth → auth}/AxiosJwtTokenService.js +0 -0
- /package/{dist/auth → auth}/AxiosJwtTokenService.js.map +0 -0
- /package/{dist/auth → auth}/LocalForageCache.js +0 -0
- /package/{dist/auth → auth}/LocalForageCache.js.map +0 -0
- /package/{dist/auth → auth}/MockAuthService.js +0 -0
- /package/{dist/auth → auth}/MockAuthService.js.map +0 -0
- /package/{dist/auth → auth}/index.js +0 -0
- /package/{dist/auth → auth}/index.js.map +0 -0
- /package/{dist/auth → auth}/interceptors/createCsrfTokenProviderInterceptor.js +0 -0
- /package/{dist/auth → auth}/interceptors/createCsrfTokenProviderInterceptor.js.map +0 -0
- /package/{dist/auth → auth}/interceptors/createJwtTokenProviderInterceptor.js +0 -0
- /package/{dist/auth → auth}/interceptors/createJwtTokenProviderInterceptor.js.map +0 -0
- /package/{dist/auth → auth}/interceptors/createProcessAxiosRequestErrorInterceptor.js +0 -0
- /package/{dist/auth → auth}/interceptors/createProcessAxiosRequestErrorInterceptor.js.map +0 -0
- /package/{dist/auth → auth}/interceptors/createRetryInterceptor.js +0 -0
- /package/{dist/auth → auth}/interceptors/createRetryInterceptor.js.map +0 -0
- /package/{dist/auth → auth}/interface.js +0 -0
- /package/{dist/auth → auth}/interface.js.map +0 -0
- /package/{dist/auth → auth}/utils.js +0 -0
- /package/{dist/auth → auth}/utils.js.map +0 -0
- /package/{dist/config.js → config.js} +0 -0
- /package/{dist/config.js.map → config.js.map} +0 -0
- /package/{dist/constants.js → constants.js} +0 -0
- /package/{dist/constants.js.map → constants.js.map} +0 -0
- /package/{dist/i18n → i18n}/countries.js +0 -0
- /package/{dist/i18n → i18n}/countries.js.map +0 -0
- /package/{dist/i18n → i18n}/index.js +0 -0
- /package/{dist/i18n → i18n}/index.js.map +0 -0
- /package/{dist/i18n → i18n}/injectIntlWithShim.js +0 -0
- /package/{dist/i18n → i18n}/injectIntlWithShim.js.map +0 -0
- /package/{dist/i18n → i18n}/languages.js +0 -0
- /package/{dist/i18n → i18n}/languages.js.map +0 -0
- /package/{dist/i18n → i18n}/lib.js +0 -0
- /package/{dist/i18n → i18n}/lib.js.map +0 -0
- /package/{dist/i18n → i18n}/scripts/README.md +0 -0
- /package/{dist/i18n → i18n}/scripts/intl-imports.js +0 -0
- /package/{dist/i18n → i18n}/scripts/intl-imports.js.map +0 -0
- /package/{dist/i18n → i18n}/scripts/transifex-utils.js +0 -0
- /package/{dist/i18n → i18n}/scripts/transifex-utils.js.map +0 -0
- /package/{dist/index.js → index.js} +0 -0
- /package/{dist/index.js.map → index.js.map} +0 -0
- /package/{dist/initialize.js → initialize.js} +0 -0
- /package/{dist/initialize.js.map → initialize.js.map} +0 -0
- /package/{dist/logging → logging}/MockLoggingService.js +0 -0
- /package/{dist/logging → logging}/MockLoggingService.js.map +0 -0
- /package/{dist/logging → logging}/NewRelicLoggingService.js +0 -0
- /package/{dist/logging → logging}/NewRelicLoggingService.js.map +0 -0
- /package/{dist/logging → logging}/index.js +0 -0
- /package/{dist/logging → logging}/index.js.map +0 -0
- /package/{dist/logging → logging}/interface.js +0 -0
- /package/{dist/logging → logging}/interface.js.map +0 -0
- /package/{dist/pubSub.js → pubSub.js} +0 -0
- /package/{dist/pubSub.js.map → pubSub.js.map} +0 -0
- /package/{dist/react → react}/AppContext.js +0 -0
- /package/{dist/react → react}/AppContext.js.map +0 -0
- /package/{dist/react → react}/AppProvider.js +0 -0
- /package/{dist/react → react}/AppProvider.js.map +0 -0
- /package/{dist/react → react}/AuthenticatedPageRoute.js +0 -0
- /package/{dist/react → react}/AuthenticatedPageRoute.js.map +0 -0
- /package/{dist/react → react}/ErrorBoundary.js +0 -0
- /package/{dist/react → react}/ErrorBoundary.js.map +0 -0
- /package/{dist/react → react}/ErrorPage.js +0 -0
- /package/{dist/react → react}/ErrorPage.js.map +0 -0
- /package/{dist/react → react}/LoginRedirect.js +0 -0
- /package/{dist/react → react}/LoginRedirect.js.map +0 -0
- /package/{dist/react → react}/OptionalReduxProvider.js +0 -0
- /package/{dist/react → react}/OptionalReduxProvider.js.map +0 -0
- /package/{dist/react → react}/PageRoute.js +0 -0
- /package/{dist/react → react}/PageRoute.js.map +0 -0
- /package/{dist/react → react}/hooks.js +0 -0
- /package/{dist/react → react}/hooks.js.map +0 -0
- /package/{dist/react → react}/index.js +0 -0
- /package/{dist/react → react}/index.js.map +0 -0
- /package/{dist/scripts → scripts}/GoogleAnalyticsLoader.js +0 -0
- /package/{dist/scripts → scripts}/GoogleAnalyticsLoader.js.map +0 -0
- /package/{dist/scripts → scripts}/index.js +0 -0
- /package/{dist/scripts → scripts}/index.js.map +0 -0
- /package/{dist/testing → testing}/index.js +0 -0
- /package/{dist/testing → testing}/index.js.map +0 -0
- /package/{dist/testing → testing}/initializeMockApp.js +0 -0
- /package/{dist/testing → testing}/initializeMockApp.js.map +0 -0
- /package/{dist/testing → testing}/mockMessages.js +0 -0
- /package/{dist/testing → testing}/mockMessages.js.map +0 -0
- /package/{dist/utils.js → utils.js} +0 -0
- /package/{dist/utils.js.map → utils.js.map} +0 -0
package/dist/README.md
DELETED
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
[](https://github.com/openedx/frontend-platform/actions/workflows/ci.yml)
|
|
2
|
-
[](https://codecov.io/gh/edx/frontend-platform)
|
|
3
|
-
[](https://www.npmjs.com/package/@edx/frontend-platform)
|
|
4
|
-
[](https://www.npmjs.com/package/@edx/frontend-platform)
|
|
5
|
-
[](https://github.com/openedx/frontend-platform/blob/master/LICENSE)
|
|
6
|
-
[](https://github.com/semantic-release/semantic-release)
|
|
7
|
-
|
|
8
|
-
# Overview
|
|
9
|
-
|
|
10
|
-
See the [GitHub Pages site for the complete documentation](https://openedx.github.io/frontend-platform/).
|
|
11
|
-
|
|
12
|
-
frontend-platform is a modest application framework for Open edX micro-frontend applications and their supporting libraries. It provides several foundational services that all Open edX micro-frontends should have:
|
|
13
|
-
|
|
14
|
-
| Service | Module location |
|
|
15
|
-
|------------------------------------|----------------------------------|
|
|
16
|
-
| Analytics | @edx/frontend-platform/analytics |
|
|
17
|
-
| Logging | @edx/frontend-platform/logging |
|
|
18
|
-
| Authenticated API client (auth) | @edx/frontend-platform/auth |
|
|
19
|
-
| Internationalization (i18n) | @edx/frontend-platform/i18n |
|
|
20
|
-
| Misc (init, config, pubSub, utils) | @edx/frontend-platform |
|
|
21
|
-
|
|
22
|
-
-------------------------------------------------------------------------
|
|
23
|
-
|
|
24
|
-
In addition, frontend-platform provides an extensible application initialization lifecycle to help manage the configuration of the above services, freeing application developers to focus on feature development.
|
|
25
|
-
|
|
26
|
-
## Getting started
|
|
27
|
-
|
|
28
|
-
### One-time setup if you have not upgraded node/npm
|
|
29
|
-
IMPORTANT: There is now a new node/npm version being used by frontend-platform as of
|
|
30
|
-
https://github.com/openedx/frontend-platform/pull/259
|
|
31
|
-
|
|
32
|
-
#### Install nvm
|
|
33
|
-
This is highly recommended to be able to leverage different node/npm versions.
|
|
34
|
-
For a some time, different repositories may be using different versions of node/npm.
|
|
35
|
-
|
|
36
|
-
Alternatively, please install node16 and npm8 for use with this repository.
|
|
37
|
-
|
|
38
|
-
#### Switch to node/npm version for this repo
|
|
39
|
-
```nvm use```
|
|
40
|
-
if you don't have the right node/npm versions, nvm will instruct you to install those
|
|
41
|
-
|
|
42
|
-
#### Clean out old node modules and reinstall
|
|
43
|
-
This step is needed because node now uses a different package lock format, and it's important to reinstall
|
|
44
|
-
dependencies based on this new package file. Delete node_modules, and issue an `npm ci`
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
### Standard getting started steps
|
|
48
|
-
|
|
49
|
-
1. `npm install`
|
|
50
|
-
2. `npm start`
|
|
51
|
-
3. Open http://localhost:8080 to view the example app.
|
|
52
|
-
|
|
53
|
-
## Architecture
|
|
54
|
-
|
|
55
|
-
The four foundational services listed above (analytics, auth, i18n, and logging) are provided as imports to applications via frontend-platform's API layer. The initialization sequence creates an instance of each service and exposes its methods as functional exports, creating a layer of abstraction between service implementations and their usage in application code.
|
|
56
|
-
|
|
57
|
-
Each type of service has a documented API contract which service implementations must fulfill. This allows different service implementations to be used as necessary without updates to consuming applications.
|
|
58
|
-
|
|
59
|
-
### Service architecture
|
|
60
|
-
|
|
61
|
-
Internally, service implementations are strictly isolated from the rest of the platform. They are classes that take their dependencies as arguments to their constructor. This means, for instance, if analytics depends on logging, it takes a reference to an instance fulfilling the `LoggingService` interface as an option when it's instantiated. It cannot import from the logging module directly. Put another way, the default service implementations may be co-located with the service interfaces for convenience, but they can theoretically live in their own repository and it wouldn't require any refactoring.
|
|
62
|
-
|
|
63
|
-
Likewise, platform code should not make use of service methods that are not part of the documented interface for the same reasons.
|
|
64
|
-
|
|
65
|
-
### Application initialization
|
|
66
|
-
|
|
67
|
-
frontend-platform provides an `initialize()` function which bootstraps and configures an application. The `initialize()` function uses a set of [sensible defaults](https://en.wikipedia.org/wiki/Convention_over_configuration) unless otherwise specified, bootstrapping the application with services reflecting Open edX's best practices around analytics, authentication, internationalization, and logging.
|
|
68
|
-
|
|
69
|
-
The initialization process proceeds in a series of phases, giving the initializing application code opportunities to hook into the process and do custom setup as desired:
|
|
70
|
-
|
|
71
|
-
- Before initialization
|
|
72
|
-
- Pub/Sub initialized
|
|
73
|
-
- Environment config document loaded
|
|
74
|
-
- Logging service initialized
|
|
75
|
-
- Authentication service initialized
|
|
76
|
-
- Analytics service initialized
|
|
77
|
-
- Internationalization service initialized
|
|
78
|
-
- Application ready
|
|
79
|
-
|
|
80
|
-
Most applications won't need to do anything special at all.
|
|
81
|
-
|
|
82
|
-
### Application configuration
|
|
83
|
-
|
|
84
|
-
When the application loads, a list of known environment variables is loaded from `process.env` into an object which it exposes via `getConfig` - the point here is primarily to isolate our code from usages of `process.env` which may not always be the way we choose to configure our apps. The application initialization lifecycle supports runtime configuration as well via the `config` handler, documented in the [initialize function](https://edx.github.io/frontend-platform/module-Initialization.html#~initialize). If you want to get a variable into the config that it’s not expecting, you can use [`mergeConfig`](https://edx.github.io/frontend-platform/module-Config.html#~mergeConfig) during initialization to add it in from `process.env`.
|
|
85
|
-
|
|
86
|
-
Such an example might look like this:
|
|
87
|
-
|
|
88
|
-
```
|
|
89
|
-
initialize({
|
|
90
|
-
// ... other initialization options
|
|
91
|
-
handlers: {
|
|
92
|
-
config: () => {
|
|
93
|
-
mergeConfig({
|
|
94
|
-
CUSTOM_VARIABLE: process.env.CUSTOM_VARIABLE || null,
|
|
95
|
-
}, 'Custom app config');
|
|
96
|
-
},
|
|
97
|
-
},
|
|
98
|
-
});
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
When using runtime configuration via `mergeConfig` noted above, `getConfig` must be called within a component's render lifecycle for the added keys and values to be returned in the configuration object. If `getConfig` is called outside of a component's render lifecycle, the custom configuration key/value pairs will not initially be part of the object returned by `getConfig`. For example:
|
|
102
|
-
|
|
103
|
-
```jsx
|
|
104
|
-
import { getConfig } from '@edx/frontend-platform/config';
|
|
105
|
-
|
|
106
|
-
// The runtime configuration `CUSTOM_VARIABLE` added in the above code snippet will not appear here. This is
|
|
107
|
-
// because `getConfig` is called before `mergeConfig` is executed to add the custom runtime configuration.
|
|
108
|
-
console.log(getConfig().CUSTOM_VARIABLE); // returns undefined
|
|
109
|
-
|
|
110
|
-
const ExampleComponent = () => {
|
|
111
|
-
// This returns the value as expected since it is called after `mergeConfig` has already been executed.
|
|
112
|
-
console.log(getConfig().CUSTOM_VARIABLE)
|
|
113
|
-
};
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
### Service interfaces
|
|
117
|
-
|
|
118
|
-
Each service (analytics, auth, i18n, logging) provided by frontend-platform has an API contract which all implementations of that service are guaranteed to fulfill. Applications that use frontend-platform can use its configured services via a convenient set of exported functions. An application that wants to use the service interfaces need only initialize them via the initialize() function, optionally providing custom service interfaces as desired (you probably won't need to).
|
|
119
|
-
|
|
120
|
-

|
|
121
|
-
|
|
122
|
-
### Service implementations
|
|
123
|
-
|
|
124
|
-
This repository contains default service implementations for convenience. These implementations are co-located with their consuming service interfaces for ease of development, though the two should remain _strictly_ modular and separate.
|
|
125
|
-
|
|
126
|
-
The included service implementations are:
|
|
127
|
-
|
|
128
|
-
- New Relic (logging)
|
|
129
|
-
- Segment (analytics)
|
|
130
|
-
- Axios/JWT (auth)
|
|
131
|
-
- React Intl (i18n)
|
|
132
|
-
|
|
133
|
-
NOTE: As of this writing, i18n is _not_ configurable. The `initialize()` function does not allow applications to supply an alternate i18n implementation; this is because the interface and implementation for i18n has not yet been separated and modularized.
|
|
134
|
-
|
|
135
|
-
# Local Development & Testing Locally
|
|
136
|
-
|
|
137
|
-
When making changes to frontend-platform, be sure to manually run the included example app located in `./example`. The example app includes 2 routes to test for both unauthenticated and authenticated users. To start the example app, run `npm start` from the root directory.
|
|
138
|
-
|
|
139
|
-
If you want to test changes to frontend-platform against a micro-frontend locally, follow the directions here: https://github.com/openedx/frontend-build#local-module-configuration-for-webpack
|
|
140
|
-
|
|
141
|
-
# Production Deployment Strategy
|
|
142
|
-
|
|
143
|
-
For any MFE built on top of the frontend-platform, the deployment strategy will be something like the following:
|
|
144
|
-
|
|
145
|
-
1. Run the build script with environment variables on the command line to pass in any relevant config. Example:
|
|
146
|
-
|
|
147
|
-
```bash
|
|
148
|
-
NODE_ENV=development BASE_URL=open.edx.org ETC=etc npm run build
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
This will create a dist/ directory that contains the deployable artifacts.
|
|
152
|
-
|
|
153
|
-
2. Copy the contents of dist/ to a web server.
|
|
154
|
-
|
|
155
|
-
3. Configure the platform to point at your MFE. (details on this coming soon)
|
package/dist/package.json
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@edx/frontend-platform",
|
|
3
|
-
"version": "4.6.2",
|
|
4
|
-
"description": "Foundational application framework for Open edX micro-frontend applications.",
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"publishConfig": {
|
|
7
|
-
"access": "public"
|
|
8
|
-
},
|
|
9
|
-
"sideEffects": false,
|
|
10
|
-
"scripts": {
|
|
11
|
-
"build": "make build",
|
|
12
|
-
"docs": "jsdoc -c jsdoc.json",
|
|
13
|
-
"docs-watch": "nodemon -w src -w docs/template -w README.md -e js,jsx --exec npm run docs",
|
|
14
|
-
"lint": "fedx-scripts eslint --ext .js --ext .jsx .",
|
|
15
|
-
"snapshot": "fedx-scripts jest --updateSnapshot",
|
|
16
|
-
"start": "fedx-scripts webpack-dev-server --progress",
|
|
17
|
-
"test": "fedx-scripts jest --coverage",
|
|
18
|
-
"test:watch": "npm run test -- --watch"
|
|
19
|
-
},
|
|
20
|
-
"bin": {
|
|
21
|
-
"intl-imports.js": "i18n/scripts/intl-imports.js",
|
|
22
|
-
"transifex-utils.js": "i18n/scripts/transifex-utils.js"
|
|
23
|
-
},
|
|
24
|
-
"repository": {
|
|
25
|
-
"type": "git",
|
|
26
|
-
"url": "git+https://github.com/openedx/frontend-platform.git"
|
|
27
|
-
},
|
|
28
|
-
"author": "edX",
|
|
29
|
-
"license": "AGPL-3.0",
|
|
30
|
-
"bugs": {
|
|
31
|
-
"url": "https://github.com/openedx/frontend-platform/issues"
|
|
32
|
-
},
|
|
33
|
-
"homepage": "https://github.com/openedx/frontend-platform#readme",
|
|
34
|
-
"devDependencies": {
|
|
35
|
-
"@edx/brand": "npm:@edx/brand-openedx@1.2.0",
|
|
36
|
-
"@edx/browserslist-config": "1.2.0",
|
|
37
|
-
"@edx/frontend-build": "12.9.3",
|
|
38
|
-
"@edx/paragon": "^20.44.0",
|
|
39
|
-
"@testing-library/react-hooks": "^8.0.1",
|
|
40
|
-
"@wojtekmaj/enzyme-adapter-react-17": "0.8.0",
|
|
41
|
-
"axios-mock-adapter": "^1.21.5",
|
|
42
|
-
"core-js": "3.32.0",
|
|
43
|
-
"enzyme": "3.11.0",
|
|
44
|
-
"husky": "8.0.3",
|
|
45
|
-
"jsdoc": "^4.0.0",
|
|
46
|
-
"nodemon": "2.0.22",
|
|
47
|
-
"prop-types": "15.8.1",
|
|
48
|
-
"react": "17.0.2",
|
|
49
|
-
"react-dom": "17.0.2",
|
|
50
|
-
"react-redux": "7.2.9",
|
|
51
|
-
"react-router-dom": "5.3.4",
|
|
52
|
-
"redux": "4.2.1",
|
|
53
|
-
"regenerator-runtime": "0.13.11"
|
|
54
|
-
},
|
|
55
|
-
"dependencies": {
|
|
56
|
-
"@cospired/i18n-iso-languages": "4.1.0",
|
|
57
|
-
"@formatjs/intl-pluralrules": "4.3.3",
|
|
58
|
-
"@formatjs/intl-relativetimeformat": "10.0.1",
|
|
59
|
-
"axios": "0.27.2",
|
|
60
|
-
"axios-cache-interceptor": "0.10.7",
|
|
61
|
-
"form-urlencoded": "4.1.4",
|
|
62
|
-
"glob": "7.2.3",
|
|
63
|
-
"history": "4.10.1",
|
|
64
|
-
"i18n-iso-countries": "4.3.1",
|
|
65
|
-
"jwt-decode": "3.1.2",
|
|
66
|
-
"localforage": "1.10.0",
|
|
67
|
-
"localforage-memoryStorageDriver": "0.9.2",
|
|
68
|
-
"lodash.camelcase": "4.3.0",
|
|
69
|
-
"lodash.memoize": "4.1.2",
|
|
70
|
-
"lodash.merge": "4.6.2",
|
|
71
|
-
"lodash.snakecase": "4.1.1",
|
|
72
|
-
"pubsub-js": "1.9.4",
|
|
73
|
-
"react-intl": "^5.25.0",
|
|
74
|
-
"universal-cookie": "4.0.4"
|
|
75
|
-
},
|
|
76
|
-
"peerDependencies": {
|
|
77
|
-
"@edx/frontend-build": ">= 8.1.0 || ^12.9.0-alpha.1",
|
|
78
|
-
"@edx/paragon": ">= 10.0.0 < 22.0.0",
|
|
79
|
-
"prop-types": "^15.7.2",
|
|
80
|
-
"react": "^16.9.0 || ^17.0.0",
|
|
81
|
-
"react-dom": "^16.9.0 || ^17.0.0",
|
|
82
|
-
"react-redux": "^7.1.1",
|
|
83
|
-
"react-router-dom": "^5.0.1",
|
|
84
|
-
"redux": "^4.0.4"
|
|
85
|
-
}
|
|
86
|
-
}
|
package/docs/addTagsPlugin.js
DELETED
package/docs/auth-API.md
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
<a name="LoginRedirect"></a>
|
|
2
|
-
|
|
3
|
-
## LoginRedirect : <code>ReactComponent</code>
|
|
4
|
-
**Kind**: global class
|
|
5
|
-
<a name="redirectToLogin"></a>
|
|
6
|
-
|
|
7
|
-
## redirectToLogin(redirectUrl)
|
|
8
|
-
Redirect the user to login
|
|
9
|
-
|
|
10
|
-
**Kind**: global function
|
|
11
|
-
|
|
12
|
-
| Param | Type | Description |
|
|
13
|
-
| --- | --- | --- |
|
|
14
|
-
| redirectUrl | <code>string</code> | the url to redirect to after login |
|
|
15
|
-
|
|
16
|
-
<a name="redirectToLogout"></a>
|
|
17
|
-
|
|
18
|
-
## redirectToLogout(redirectUrl)
|
|
19
|
-
Redirect the user to logout
|
|
20
|
-
|
|
21
|
-
**Kind**: global function
|
|
22
|
-
|
|
23
|
-
| Param | Type | Description |
|
|
24
|
-
| --- | --- | --- |
|
|
25
|
-
| redirectUrl | <code>string</code> | the url to redirect to after logout |
|
|
26
|
-
|
|
27
|
-
<a name="getAuthenticatedApiClient"></a>
|
|
28
|
-
|
|
29
|
-
## getAuthenticatedApiClient(config) ⇒ [<code>HttpClient</code>](#HttpClient)
|
|
30
|
-
Gets the apiClient singleton which is an axios instance.
|
|
31
|
-
|
|
32
|
-
**Kind**: global function
|
|
33
|
-
**Returns**: [<code>HttpClient</code>](#HttpClient) - Singleton. A configured axios http client
|
|
34
|
-
|
|
35
|
-
| Param | Type | Description |
|
|
36
|
-
| --- | --- | --- |
|
|
37
|
-
| config | <code>object</code> | |
|
|
38
|
-
| [config.appBaseUrl] | <code>string</code> | |
|
|
39
|
-
| [config.authBaseUrl] | <code>string</code> | |
|
|
40
|
-
| [config.loginUrl] | <code>string</code> | |
|
|
41
|
-
| [config.logoutUrl] | <code>string</code> | |
|
|
42
|
-
| [config.loggingService] | <code>object</code> | requires logError and logInfo methods |
|
|
43
|
-
| [config.refreshAccessTokenEndpoint] | <code>string</code> | |
|
|
44
|
-
| [config.accessTokenCookieName] | <code>string</code> | |
|
|
45
|
-
| [config.csrfTokenApiPath] | <code>string</code> | |
|
|
46
|
-
|
|
47
|
-
<a name="getAuthenticatedUser"></a>
|
|
48
|
-
|
|
49
|
-
## getAuthenticatedUser() ⇒ [<code>Promise.<UserData></code>](#UserData) \| <code>Promise.<null></code>
|
|
50
|
-
Gets the authenticated user's access token. Resolves to null if the user is unauthenticated.
|
|
51
|
-
|
|
52
|
-
**Kind**: global function
|
|
53
|
-
**Returns**: [<code>Promise.<UserData></code>](#UserData) \| <code>Promise.<null></code> - Resolves to the user's access token if they are logged in.
|
|
54
|
-
<a name="ensureAuthenticatedUser"></a>
|
|
55
|
-
|
|
56
|
-
## ensureAuthenticatedUser(route) ⇒ [<code>Promise.<UserData></code>](#UserData)
|
|
57
|
-
Ensures a user is authenticated. It will redirect to login when not authenticated.
|
|
58
|
-
|
|
59
|
-
**Kind**: global function
|
|
60
|
-
|
|
61
|
-
| Param | Type | Description |
|
|
62
|
-
| --- | --- | --- |
|
|
63
|
-
| route | <code>string</code> | to return user after login when not authenticated. |
|
|
64
|
-
|
|
65
|
-
<a name="PrivateRoute"></a>
|
|
66
|
-
|
|
67
|
-
## PrivateRoute() : <code>ReactComponent</code>
|
|
68
|
-
**Kind**: global function
|
|
69
|
-
<a name="HttpClient"></a>
|
|
70
|
-
|
|
71
|
-
## HttpClient
|
|
72
|
-
A configured axios client. See axios docs for more
|
|
73
|
-
info https://github.com/axios/axios. All the functions
|
|
74
|
-
below accept isPublic and isCsrfExempt in the request
|
|
75
|
-
config options. Setting these to true will prevent this
|
|
76
|
-
client from attempting to refresh the jwt access token
|
|
77
|
-
or a csrf token respectively.
|
|
78
|
-
|
|
79
|
-
```
|
|
80
|
-
// A public endpoint (no jwt token refresh)
|
|
81
|
-
apiClient.get('/path/to/endpoint', { isPublic: true });
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
```
|
|
85
|
-
// A csrf exempt endpoint
|
|
86
|
-
apiClient.post('/path/to/endpoint', { data }, { isCsrfExempt: true });
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
**Kind**: global typedef
|
|
90
|
-
**Properties**
|
|
91
|
-
|
|
92
|
-
| Name | Type | Description |
|
|
93
|
-
| --- | --- | --- |
|
|
94
|
-
| get | <code>function</code> | |
|
|
95
|
-
| head | <code>function</code> | |
|
|
96
|
-
| options | <code>function</code> | |
|
|
97
|
-
| delete | <code>function</code> | (csrf protected) |
|
|
98
|
-
| post | <code>function</code> | (csrf protected) |
|
|
99
|
-
| put | <code>function</code> | (csrf protected) |
|
|
100
|
-
| patch | <code>function</code> | (csrf protected) |
|
|
101
|
-
|
|
102
|
-
<a name="UserData"></a>
|
|
103
|
-
|
|
104
|
-
## UserData
|
|
105
|
-
**Kind**: global typedef
|
|
106
|
-
**Properties**
|
|
107
|
-
|
|
108
|
-
| Name | Type |
|
|
109
|
-
| --- | --- |
|
|
110
|
-
| userId | <code>string</code> |
|
|
111
|
-
| username | <code>string</code> |
|
|
112
|
-
| roles | <code>array</code> |
|
|
113
|
-
| administrator | <code>bool</code> |
|
|
114
|
-
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
1. Record Architecture Decisions
|
|
2
|
-
--------------------------------
|
|
3
|
-
|
|
4
|
-
Status
|
|
5
|
-
------
|
|
6
|
-
|
|
7
|
-
Accepted
|
|
8
|
-
|
|
9
|
-
Context
|
|
10
|
-
-------
|
|
11
|
-
|
|
12
|
-
We would like to keep a historical record on the architectural
|
|
13
|
-
decisions we make with this app as it evolves over time.
|
|
14
|
-
|
|
15
|
-
Decision
|
|
16
|
-
--------
|
|
17
|
-
|
|
18
|
-
We will use Architecture Decision Records, as described by
|
|
19
|
-
Michael Nygard in `Documenting Architecture Decisions`_
|
|
20
|
-
|
|
21
|
-
.. _Documenting Architecture Decisions: http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions
|
|
22
|
-
|
|
23
|
-
Consequences
|
|
24
|
-
------------
|
|
25
|
-
|
|
26
|
-
See Michael Nygard's article, linked above.
|
|
27
|
-
|
|
28
|
-
References
|
|
29
|
-
----------
|
|
30
|
-
|
|
31
|
-
* https://resources.sei.cmu.edu/asset_files/Presentation/2017_017_001_497746.pdf
|
|
32
|
-
* https://github.com/npryce/adr-tools/tree/master/doc/adr
|
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
frontend-base Design Goals
|
|
2
|
-
==========================
|
|
3
|
-
|
|
4
|
-
Status
|
|
5
|
-
------
|
|
6
|
-
|
|
7
|
-
Accepted
|
|
8
|
-
|
|
9
|
-
Goals
|
|
10
|
-
-----
|
|
11
|
-
|
|
12
|
-
The creation of frontend-base framework was motivated by a few desires
|
|
13
|
-
and concerns.
|
|
14
|
-
|
|
15
|
-
Code reuse
|
|
16
|
-
~~~~~~~~~~
|
|
17
|
-
|
|
18
|
-
We wanted to "DRY" up boilerplate code that was being copied from
|
|
19
|
-
repository to repository each time we created a new micro-frontend.
|
|
20
|
-
|
|
21
|
-
We observed that as the code was copied around, it tended to drift, and
|
|
22
|
-
later implementations had different - and often better - best practices
|
|
23
|
-
than the ones that came before. Worse, if a fix went in to an older
|
|
24
|
-
application, we had no way to easily carry that forward. This meant we
|
|
25
|
-
had no guarantee that our applications had the correct infrastructure
|
|
26
|
-
for analytics, logging, i18n, error handling, observability, and
|
|
27
|
-
authentication.
|
|
28
|
-
|
|
29
|
-
Configuration standardization
|
|
30
|
-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
31
|
-
|
|
32
|
-
Similar to code drift, we found our set of environment configuration
|
|
33
|
-
variables were not standardized, creating a maintenance overhead and the
|
|
34
|
-
potential for 1) applications being given variables they were unlikely
|
|
35
|
-
to need, or worse 2) lacking required variables. We observed that it was
|
|
36
|
-
tedious and error prone to add a new variable across multiple
|
|
37
|
-
applications.
|
|
38
|
-
|
|
39
|
-
Ease of use
|
|
40
|
-
~~~~~~~~~~~
|
|
41
|
-
|
|
42
|
-
In writing some of our first micro-frontends, it was becoming difficult
|
|
43
|
-
to pass some information around the application (environment
|
|
44
|
-
configuration, authenticated user data, and the authenticated API
|
|
45
|
-
client, specifically), while still maintaining a sense of modularity. We
|
|
46
|
-
were using dependency injection, but it was a heavy-handed
|
|
47
|
-
implementation that involved a hierarchical set of "configure()" methods
|
|
48
|
-
to help pass the data around. We wanted to address this and make it
|
|
49
|
-
straightforward to use top-level data effortlessly.
|
|
50
|
-
|
|
51
|
-
.. _consistency-vs-flexibility:
|
|
52
|
-
|
|
53
|
-
Consistency vs. flexibility
|
|
54
|
-
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
55
|
-
|
|
56
|
-
We were concerned - with the creation of a "base" library to contain and
|
|
57
|
-
tie together all this code - that we would hamper our ability to enable
|
|
58
|
-
experimentation and independently deployed applications, one of our most
|
|
59
|
-
fundamental goals in adopting a micro-frontend architecture.
|
|
60
|
-
|
|
61
|
-
This functions on two levels: 1) we wanted to maintain our ability to
|
|
62
|
-
allow new micro-frontends to forge ahead and experiment with new
|
|
63
|
-
technology and library features, and 2) we also wanted to ensure that
|
|
64
|
-
our "base" library was not too prescriptive about exactly what it means
|
|
65
|
-
to be an Open edX micro-frontend.
|
|
66
|
-
|
|
67
|
-
Exploration of frontend pluggability
|
|
68
|
-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
69
|
-
|
|
70
|
-
In preparation for efforts related to enabling frontend pluggability, we
|
|
71
|
-
felt it valuable to create a layer of abstraction for applications that
|
|
72
|
-
enabled application pages to start being "plugged into" the top-level
|
|
73
|
-
application bootstrapping and lifecycle management code. In doing so, we
|
|
74
|
-
hoped to start understanding what we might encounter as we move forward
|
|
75
|
-
with pluggability. (This is the softest of these desires, but a helpful
|
|
76
|
-
learning experience)
|
|
77
|
-
|
|
78
|
-
Implementation
|
|
79
|
-
--------------
|
|
80
|
-
|
|
81
|
-
``frontend-base`` is an attempt to address the above desires and
|
|
82
|
-
concerns.
|
|
83
|
-
|
|
84
|
-
Addressing code reuse
|
|
85
|
-
~~~~~~~~~~~~~~~~~~~~~
|
|
86
|
-
|
|
87
|
-
It provides a home for application initialization/configuration code,
|
|
88
|
-
allowing us to use semantic versioning to manage its implementations
|
|
89
|
-
across our micro-frontends. This code will cease to be copied from
|
|
90
|
-
repository to repository, and will instead be imported from published
|
|
91
|
-
versions of ``frontend-base``. This allows us to know at a glance what
|
|
92
|
-
boilerplate features/bug fixes a given application has, and a clear,
|
|
93
|
-
documented path to upgrade and deal with breaking changes.
|
|
94
|
-
|
|
95
|
-
Addressing ease of use
|
|
96
|
-
~~~~~~~~~~~~~~~~~~~~~~
|
|
97
|
-
|
|
98
|
-
``frontend-base`` makes use of a singleton class - ``App`` which can be
|
|
99
|
-
imported into arbitrary code and provides access to commonly used sets
|
|
100
|
-
of data, such as configuration variables, authenticated user
|
|
101
|
-
information, and an API client. This makes it trivial to access all this
|
|
102
|
-
top level data, removing the need to manually pass it around.
|
|
103
|
-
|
|
104
|
-
Addressing configuration standardization
|
|
105
|
-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
106
|
-
|
|
107
|
-
The library ingests and provides access to a known set of environment
|
|
108
|
-
variable-based configuration variables. It validates that these
|
|
109
|
-
variables have been set with non-\ ``undefined`` values, and provides
|
|
110
|
-
utility methods for performing similar checks on any custom
|
|
111
|
-
configuration that a consuming application may need. It provides
|
|
112
|
-
extension hooks for doing dynamic configuration at runtime, if
|
|
113
|
-
necessary, leaving the door open for other configuration methods. An
|
|
114
|
-
arbitrary piece of application code can assert that it requires certain
|
|
115
|
-
variables, throwing runtime exceptions immediately if they weren't set.
|
|
116
|
-
This gives developers immediate, definitive feedback of any
|
|
117
|
-
configuration issues in their deployment pipelines.
|
|
118
|
-
|
|
119
|
-
.. _addressing-consistency-vs-flexibility:
|
|
120
|
-
|
|
121
|
-
Addressing consistency vs. flexibility
|
|
122
|
-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
123
|
-
|
|
124
|
-
``frontend-base`` is published to npm as ES6 modules with
|
|
125
|
-
``peerDependencies`` in its package.json. This means that consuming apps
|
|
126
|
-
are told exactly what versions of supporting libraries
|
|
127
|
-
(``@edx/frontend-auth``, ``@edx/frontend-i18n``, ``@edx/paragon``,
|
|
128
|
-
React, etc.) are compatible with a given version of ``frontend-base``.
|
|
129
|
-
Beyond that, applications are free to use any compatible version. This
|
|
130
|
-
prevents ``frontend-base`` from being a bottleneck for updating library
|
|
131
|
-
versions, and helps application authors avoid situations where they have
|
|
132
|
-
to consume multiple breaking changes just to get a new feature in *one*
|
|
133
|
-
supporting library.
|
|
134
|
-
|
|
135
|
-
The library has an extensible and fully customizable initialization
|
|
136
|
-
sequence. Any phase of initialization can be modified to support
|
|
137
|
-
unforeseen use cases while maintaining the framework as a whole.
|
|
138
|
-
|
|
139
|
-
Addressing exploration of frontend pluggability
|
|
140
|
-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
141
|
-
|
|
142
|
-
The process of creating ``frontend-base`` was conducted using
|
|
143
|
-
``@edx/frontend-app-profile`` as a test bed. As a result, we learned how
|
|
144
|
-
to modularize the application-specific code in the Profile
|
|
145
|
-
micro-frontend to allow it to be consumed by a more generic application
|
|
146
|
-
framework. We also, tangentially, explored ways of customizing the
|
|
147
|
-
header and footer and ensured that they could be reasonably separated
|
|
148
|
-
from both the framework and the application code.
|
|
149
|
-
|
|
150
|
-
This resulted in a loose coupling of the ``frontend-base`` framework and
|
|
151
|
-
the application code it was consuming. The UI modules (header, footer,
|
|
152
|
-
and profile page) are starting to coalesce around a simple interface of
|
|
153
|
-
exports:
|
|
154
|
-
|
|
155
|
-
- A default export of the top-level React component.
|
|
156
|
-
- A ``messages`` export for i18n resources.
|
|
157
|
-
- A ``reducer`` export for Redux reducers.
|
|
158
|
-
- A ``saga`` export for the redux-saga middleware.
|
|
159
|
-
|
|
160
|
-
Furthermore, as part of ``frontend-base``, we were able to separate out
|
|
161
|
-
the application initialization sequence from the rendering of the
|
|
162
|
-
application UI. This means that - with the exception of its optional
|
|
163
|
-
React component helpers and our usage of @edx/frontend-i18n -
|
|
164
|
-
frontend-base is nearly UI framework agnostic. It can initialize
|
|
165
|
-
completely without being concerned about the UI framework in use, and
|
|
166
|
-
then gracefully handoff to React or whichever else.
|
|
167
|
-
|
|
168
|
-
Adoption
|
|
169
|
-
--------
|
|
170
|
-
|
|
171
|
-
We intend to update existing micro-frontends to make use of
|
|
172
|
-
``frontend-base``. We've started with frontend-app-profile and are
|
|
173
|
-
following up with frontend-app-payment. Newer micro-frontends will be
|
|
174
|
-
created with it as a dependency. Other, older micro-frontends will be
|
|
175
|
-
prioritized over time.
|
|
176
|
-
|
|
177
|
-
Consequences
|
|
178
|
-
------------
|
|
179
|
-
|
|
180
|
-
The library should go a long way toward standardizing our application
|
|
181
|
-
initialization code and helping us keep all our micro-frontends up to
|
|
182
|
-
date. That's the big win.
|
|
183
|
-
|
|
184
|
-
It also provides micro-frontend developers with a strong, flexible
|
|
185
|
-
foundation on which to build their applications. As we discover bugs or
|
|
186
|
-
new, fundamental features that we want our apps to be able to handle, we
|
|
187
|
-
have one centralized place to implement them.
|
|
188
|
-
|
|
189
|
-
It was also a useful exploration of pluggability, abstraction, and
|
|
190
|
-
separation of concerns, which should help inform our work going forward.
|
|
191
|
-
|
|
192
|
-
Furthermore, reading the tea leaves a bit, we can foresee a future where
|
|
193
|
-
our Open edX micro-frontends are lazy-loaded modules that are plugged
|
|
194
|
-
into frontend-base at runtime, allowing independently deployable 'pages'
|
|
195
|
-
of a larger single-page app, which should pay dividends in user
|
|
196
|
-
experience and application runtime performance.
|
|
197
|
-
|
|
198
|
-
Concerns and Limitations
|
|
199
|
-
------------------------
|
|
200
|
-
|
|
201
|
-
The choice to create ``frontend-base`` involves a few concerns:
|
|
202
|
-
|
|
203
|
-
One, we hope that we've made a framework that is simple, unobtrustive,
|
|
204
|
-
extensible, and effective. This is, admittedly, hard to do, and it's
|
|
205
|
-
possible that as time goes on we'll find that it has certain limitations
|
|
206
|
-
and may need to revisit it. Specifically, it remains to be seen the
|
|
207
|
-
extent to which it is compatible with GatsbyJS's initialization hooks
|
|
208
|
-
(``onClientInit`` and ``wrapRootElement``, for instance).
|
|
209
|
-
|
|
210
|
-
Two, the library also assumes that environment-variable based
|
|
211
|
-
configuration - via ``process.env``, is sufficient for most of our needs
|
|
212
|
-
across the organization. This seems to be the case, but has yet to be
|
|
213
|
-
scrutinized. While the library allows for dynamic run-time configuration
|
|
214
|
-
or replacing the environment variable configuration, it does not
|
|
215
|
-
postulate on or provide another mechanism for doing so.
|
|
216
|
-
|
|
217
|
-
Three, ``peerDependencies`` manifest as warnings, not errors, and can be
|
|
218
|
-
easily ignored. In general it would be better if there was stronger
|
|
219
|
-
enforcement of frontend-base's peer dependency requirements, but we're
|
|
220
|
-
limited by what ``npm`` will provide. It's slightly concerning that a
|
|
221
|
-
dependency could be incompatible and we potentially wouldn't know it
|
|
222
|
-
until runtime.
|