@mdn/fred 1.1.1 → 1.3.0
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/.env-dist +3 -3
- package/CHANGELOG.md +33 -0
- package/README.md +4 -0
- package/build/env.js +11 -2
- package/build/render.js +4 -8
- package/build/ssr.js +3 -2
- package/components/env/README.md +28 -0
- package/components/env/index.js +9 -30
- package/components/env/runtime.js +6 -0
- package/components/env/types.d.ts +5 -0
- package/components/env/utils.js +56 -0
- package/components/outer-layout/server.js +12 -0
- package/components/play-runner/element.js +7 -2
- package/out/service-worker.js +1 -1
- package/out/service-worker.js.map +1 -1
- package/out/static/client/{1231.df3f6728f4b7e36e.js → 1231.84c230e0fa92f2d4.js} +2 -2
- package/out/static/client/{1231.df3f6728f4b7e36e.js.map → 1231.84c230e0fa92f2d4.js.map} +1 -1
- package/out/static/client/{1274.5c4c7493aa8334bf.js → 1274.e98f5c68889cda35.js} +2 -2
- package/out/static/client/{1274.5c4c7493aa8334bf.js.map → 1274.e98f5c68889cda35.js.map} +1 -1
- package/out/static/client/{2936.2446688864e1a136.js → 2936.7d85bf584b89578b.js} +2 -2
- package/out/static/client/{2936.2446688864e1a136.js.map → 2936.7d85bf584b89578b.js.map} +1 -1
- package/out/static/client/{370.85e6b0ff8596c5ae.js → 370.d2e13711140af6d1.js} +3 -3
- package/out/static/client/{370.85e6b0ff8596c5ae.js.map → 370.d2e13711140af6d1.js.map} +1 -1
- package/out/static/client/{451.d36f6f80badd6af6.js → 451.cd85e2808f388a00.js} +2 -2
- package/out/static/client/{451.d36f6f80badd6af6.js.map → 451.cd85e2808f388a00.js.map} +1 -1
- package/out/static/client/{606.221fc4347a8278e8.js → 606.d22d2cf33232a730.js} +2 -2
- package/out/static/client/{606.221fc4347a8278e8.js.map → 606.d22d2cf33232a730.js.map} +1 -1
- package/out/static/client/{8093.81b1b345d454a85e.js → 8093.b03f1cb1e8b0984a.js} +3 -3
- package/out/static/client/{8093.81b1b345d454a85e.js.map → 8093.b03f1cb1e8b0984a.js.map} +1 -1
- package/out/static/client/{9784.0096d3445a2a7e98.js → 9784.214845ec6d3b77e3.js} +3 -3
- package/out/static/client/{9784.0096d3445a2a7e98.js.map → 9784.214845ec6d3b77e3.js.map} +1 -1
- package/out/static/client/{9837.2374d8bd425a9866.js → 9837.6876cb5a9d3ad763.js} +2 -2
- package/out/static/client/{9837.2374d8bd425a9866.js.map → 9837.6876cb5a9d3ad763.js.map} +1 -1
- package/out/static/client/{9914.9b7171874efa4629.js → 9914.0e9589033d2579e2.js} +2 -2
- package/out/static/client/9914.0e9589033d2579e2.js.map +1 -0
- package/out/static/client/{index.dfccf913556b909a.js → index.1e789b86311a8c84.js} +10 -10
- package/out/static/client/index.1e789b86311a8c84.js.map +1 -0
- package/out/static/client/{runtime.05472639a6b3fea7.js → runtime.8c7621b5c39c82eb.js} +2 -2
- package/out/static/client/{runtime.05472639a6b3fea7.js.map → runtime.8c7621b5c39c82eb.js.map} +1 -1
- package/out/static/client/stats.json +332 -332
- package/out/static/client/{styles-a11y-menu.87133247d94d171f.js → styles-a11y-menu.9ef9230de282e800.js} +1 -1
- package/out/static/client/{styles-advertising.a820b0fbd3627483.js → styles-advertising.a44392a700080714.js} +1 -1
- package/out/static/client/{styles-article-footer.6be3444c8d5eb565.js → styles-article-footer.86b64eeebebad91b.js} +1 -1
- package/out/static/client/{styles-banner.bca362a6a4f7c302.js → styles-banner.fbff125bcec971bb.js} +1 -1
- package/out/static/client/styles-baseline-indicator.bf566965786907bc.js +1 -0
- package/out/static/client/{styles-blog-index.acbed372695bc055.js → styles-blog-index.ffc8cf956c8e4373.js} +1 -1
- package/out/static/client/{styles-blog-post.72b868f89027427f.js → styles-blog-post.a91d641515116579.js} +1 -1
- package/out/static/client/{styles-breadcrumbs-bar.0e8d97523444c0fe.js → styles-breadcrumbs-bar.99a04f7eef75930e.js} +1 -1
- package/out/static/client/{styles-breadcrumbs.9160a3861a8ab53a.js → styles-breadcrumbs.efcc208fb9e255c5.js} +1 -1
- package/out/static/client/{styles-button.9ae9af48571a4080.js → styles-button.fbe882b992422121.js} +1 -1
- package/out/static/client/{styles-content-section.ec1b9dc73aceca10.js → styles-content-section.97477ade56571b27.js} +1 -1
- package/out/static/client/styles-contributor-spotlight.f38b65412f05511a.js +1 -0
- package/out/static/client/{styles-curriculum-about.14f748159af30620.js → styles-curriculum-about.f15ed5fd5438c809.js} +1 -1
- package/out/static/client/styles-curriculum-default.e5662ee1eb84c092.js +1 -0
- package/out/static/client/styles-curriculum-landing.6e4b9b74a02421c0.js +1 -0
- package/out/static/client/{styles-curriculum-module.7957e2e3bd0eafb5.js → styles-curriculum-module.4f565696a741e039.js} +1 -1
- package/out/static/client/styles-curriculum-overview.03c8bb59e85f60fc.js +1 -0
- package/out/static/client/{styles-featured-articles.fe5075936dc1689d.js → styles-featured-articles.33d674ab9d0a4b23.js} +1 -1
- package/out/static/client/{styles-footer.5a5264232af3c286.js → styles-footer.61afa985d6c61587.js} +1 -1
- package/out/static/client/{styles-generic-about.bd6c3ab10cbfb61b.js → styles-generic-about.832ee823b2a15f3d.js} +1 -1
- package/out/static/client/{styles-generic-community.01f6a7593bc9268d.js → styles-generic-community.747ac72340973838.js} +1 -1
- package/out/static/client/{styles-generic-content.37bf952fe2b843c3.js → styles-generic-content.a3756d3e18ebaa38.js} +1 -1
- package/out/static/client/{styles-generic-layout.d5a8393d0e416a5a.js → styles-generic-layout.35e962adef8a2f23.js} +1 -1
- package/out/static/client/{styles-generic-sidebar.b3d7d5203335b86b.js → styles-generic-sidebar.0292229bdf97c876.js} +1 -1
- package/out/static/client/{styles-generic-toc.0f2eb841500811fe.js → styles-generic-toc.0cf78fef4fb1ca04.js} +1 -1
- package/out/static/client/{styles-global.1edda3f0378c4985.js → styles-global.73ea7609e20e907a.js} +1 -1
- package/out/static/client/styles-global.d92154c94ac95c1e.css +2 -0
- package/out/static/client/{styles-global.c9f2a49e47bf5c55.css.map → styles-global.d92154c94ac95c1e.css.map} +1 -1
- package/out/static/client/{styles-heading-anchor.459f5d2b6ef27a35.js → styles-heading-anchor.40bbc9df73fbe3ed.js} +1 -1
- package/out/static/client/{styles-homepage-body.1353218dc43e8403.js → styles-homepage-body.4d5de7246b823efb.js} +1 -1
- package/out/static/client/styles-homepage-contributor-spotlight.40146b76a1b9b98d.js +1 -0
- package/out/static/client/{styles-homepage-footer.a2e302b524b9cb41.js → styles-homepage-footer.1d2128d057b63f1c.js} +1 -1
- package/out/static/client/{styles-homepage-header.61d200f9e7261cf9.js → styles-homepage-header.7f9ca8158a115853.js} +1 -1
- package/out/static/client/{styles-homepage-hero.49347a14601630f9.js → styles-homepage-hero.a378110befc1e2cf.js} +1 -1
- package/out/static/client/{styles-homepage.5659711ea0d54c03.js → styles-homepage.5fb3fbe7543e268c.js} +1 -1
- package/out/static/client/{styles-latest-news.c935e3ecd62721be.js → styles-latest-news.9807f67c0586ad37.js} +1 -1
- package/out/static/client/{styles-left-sidebar.d250c9e1d0b8e944.js → styles-left-sidebar.2b2c4b35ffab8b27.js} +1 -1
- package/out/static/client/{styles-logo.d710c44f8c185a20.js → styles-logo.b0bad5a338d3c9d5.js} +1 -1
- package/out/static/client/{styles-mandala.80f6df343c206d80.js → styles-mandala.12a581abb318dbd8.js} +1 -1
- package/out/static/client/{styles-menu.5cf6280521425c6e.js → styles-menu.5b31bb6fde3da1a1.js} +1 -1
- package/out/static/client/{styles-navigation.ce5485bf0d2aa72c.js → styles-navigation.48b5d8d8c84bded3.js} +1 -1
- package/out/static/client/{styles-not-found.ed1a36323c6f034f.js → styles-not-found.d239b62bbdf556a1.js} +1 -1
- package/out/static/client/styles-observatory-landing.35868a8dba7b4d88.js +1 -0
- package/out/static/client/styles-observatory-results.7639a9793cb4d5f4.js +1 -0
- package/out/static/client/{styles-page-layout.ebaba26f8be73ed6.js → styles-page-layout.88f6a1626ac74ab0.js} +1 -1
- package/out/static/client/{styles-pagination.2180f506e667ba5c.js → styles-pagination.cf614f5da0884ae8.js} +1 -1
- package/out/static/client/{styles-playground.022236b630f29462.js → styles-playground.372ea0d0972b1cf7.js} +1 -1
- package/out/static/client/styles-recent-contributions.1381c21c0d5a9068.js +1 -0
- package/out/static/client/{styles-reference-layout.bffd0e6da5605009.js → styles-reference-layout.d9101683510063c5.js} +1 -1
- package/out/static/client/{styles-reference-toc.c8955d29f707494b.js → styles-reference-toc.b16b3ae26546340c.js} +1 -1
- package/out/static/client/{styles-sandbox.6a001e2be84a6688.js → styles-sandbox.c6f491538eb37b5a.js} +1 -1
- package/out/static/client/{styles-site-search.dda21a516b8b58c1.js → styles-site-search.0c4b85eda79571bf.js} +1 -1
- package/out/static/client/{styles-translation-banner.affb41df0468f016.js → styles-translation-banner.89994e4b4025fca7.js} +1 -1
- package/out/static/client/{styles-writer-toolbar.dc0dfffc08e850d6.js → styles-writer-toolbar.8cf64ea391d384dc.js} +1 -1
- package/out/static/client/{styles.a184d8a933a6c3a6.js → styles.7e12510d3d62d6c2.js} +2 -2
- package/out/static/client/{styles.a184d8a933a6c3a6.js.map → styles.7e12510d3d62d6c2.js.map} +1 -1
- package/out/static/legacy/asset-manifest.json +6 -6
- package/out/static/legacy/{index.c10af7d92675e9fd.html → index.7a7a7a6c9ea9fbe7.html} +1 -1
- package/out/static/legacy/{index.4b9e35f28a890bda.js → index.fdfbaab08cf3189a.js} +3 -3
- package/out/static/legacy/{index.4b9e35f28a890bda.js.map → index.fdfbaab08cf3189a.js.map} +1 -1
- package/out/static/legacy/stats.json +7 -7
- package/out/static/legacy/{yari.2771217736dd92b4.js → yari.9ba4e4812214ca1d.js} +3 -3
- package/out/static/legacy/{yari.2771217736dd92b4.js.map → yari.9ba4e4812214ca1d.js.map} +1 -1
- package/out/static/ssr/index.js +11 -8
- package/out/static/ssr/index.js.map +1 -1
- package/out/static/ssr/stats.json +4 -4
- package/package.json +6 -5
- package/rspack.config.js +8 -7
- package/server.js +8 -8
- package/out/static/client/9914.9b7171874efa4629.js.map +0 -1
- package/out/static/client/index.dfccf913556b909a.js.map +0 -1
- package/out/static/client/styles-baseline-indicator.475001c3d152eda6.js +0 -1
- package/out/static/client/styles-contributor-spotlight.08c74d3c426050ed.js +0 -1
- package/out/static/client/styles-curriculum-default.89b14c7bf3342041.js +0 -1
- package/out/static/client/styles-curriculum-landing.4a5fa59933fb70fd.js +0 -1
- package/out/static/client/styles-curriculum-overview.9614bb249432e5e3.js +0 -1
- package/out/static/client/styles-global.c9f2a49e47bf5c55.css +0 -2
- package/out/static/client/styles-homepage-contributor-spotlight.db46ee4b1e184c36.js +0 -1
- package/out/static/client/styles-observatory-landing.987e00f1527a651f.js +0 -1
- package/out/static/client/styles-observatory-results.736e05f4bd6e1487.js +0 -1
- package/out/static/client/styles-recent-contributions.b5366c0daf414e8a.js +0 -1
- /package/out/static/client/{370.85e6b0ff8596c5ae.js.LICENSE.txt → 370.d2e13711140af6d1.js.LICENSE.txt} +0 -0
- /package/out/static/client/{8093.81b1b345d454a85e.js.LICENSE.txt → 8093.b03f1cb1e8b0984a.js.LICENSE.txt} +0 -0
- /package/out/static/client/{9784.0096d3445a2a7e98.js.LICENSE.txt → 9784.214845ec6d3b77e3.js.LICENSE.txt} +0 -0
- /package/out/static/client/{index.dfccf913556b909a.js.LICENSE.txt → index.1e789b86311a8c84.js.LICENSE.txt} +0 -0
- /package/out/static/legacy/{index.4b9e35f28a890bda.js.LICENSE.txt → index.fdfbaab08cf3189a.js.LICENSE.txt} +0 -0
- /package/out/static/legacy/{yari.2771217736dd92b4.js.LICENSE.txt → yari.9ba4e4812214ca1d.js.LICENSE.txt} +0 -0
package/.env-dist
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
CONTENT_ROOT=../content/files
|
|
3
3
|
# https://github.com/mdn/translated-content
|
|
4
4
|
CONTENT_TRANSLATED_ROOT=../translated-content/files
|
|
5
|
-
# https://github.com/mdn/
|
|
6
|
-
BLOG_ROOT=../
|
|
5
|
+
# https://github.com/mdn/blog
|
|
6
|
+
BLOG_ROOT=../blog/content/posts
|
|
7
7
|
# https://github.com/mdn/curriculum/
|
|
8
8
|
CURRICULUM_ROOT=../curriculum
|
|
9
9
|
# https://github.com/mdn/mdn-contributor-spotlight
|
|
@@ -29,4 +29,4 @@ RARI_URL="http://localhost:8083"
|
|
|
29
29
|
REACT_APP_KUMA_HOST="localhost:3000"
|
|
30
30
|
REACT_APP_FXA_SIGNIN_URL="/users/fxa/login/authenticate/"
|
|
31
31
|
REACT_APP_FXA_SETTINGS_URL="https://accounts.stage.mozaws.net/settings/"
|
|
32
|
-
REACT_APP_PLACEMENT_ENABLED="true"
|
|
32
|
+
REACT_APP_PLACEMENT_ENABLED="true"
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.3.0](https://github.com/mdn/fred/compare/v1.2.0...v1.3.0) (2025-09-01)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **package/bin:** add fred-ssr executable ([#678](https://github.com/mdn/fred/issues/678)) ([faa175d](https://github.com/mdn/fred/commit/faa175dbf31d5cc715bccbcb9673572e8323e340))
|
|
9
|
+
* **server:** allow specifiying port from env var ([#679](https://github.com/mdn/fred/issues/679)) ([eea7274](https://github.com/mdn/fred/commit/eea72742ed07d3e2230cc33c30a2f3a1fcc9b4d3))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* **env:** prefix runtime var fallback only once ([eea7274](https://github.com/mdn/fred/commit/eea72742ed07d3e2230cc33c30a2f3a1fcc9b4d3))
|
|
15
|
+
* **server:** omit Playground server link in output ([eea7274](https://github.com/mdn/fred/commit/eea72742ed07d3e2230cc33c30a2f3a1fcc9b4d3))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Miscellaneous
|
|
19
|
+
|
|
20
|
+
* **deps-dev:** bump @mdn/browser-compat-data from 7.1.0 to 7.1.1 ([#677](https://github.com/mdn/fred/issues/677)) ([2a90bc2](https://github.com/mdn/fred/commit/2a90bc213785c778481299ae6fad996d3c5fe890))
|
|
21
|
+
* **deps-dev:** bump the dev group with 2 updates ([#660](https://github.com/mdn/fred/issues/660)) ([08c2d3d](https://github.com/mdn/fred/commit/08c2d3d465ad31dcac9f0722856822d5da8f833c))
|
|
22
|
+
* rename {mdn-studio => blog} ([#681](https://github.com/mdn/fred/issues/681)) ([39ab241](https://github.com/mdn/fred/commit/39ab241bf912f0f395634029d9fd11b784f28be1))
|
|
23
|
+
|
|
24
|
+
## [1.2.0](https://github.com/mdn/fred/compare/v1.1.1...v1.2.0) (2025-08-28)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
### Features
|
|
28
|
+
|
|
29
|
+
* **env:** add runtime variables ([#642](https://github.com/mdn/fred/issues/642)) ([ab504ef](https://github.com/mdn/fred/commit/ab504effc762002df03d709e9ed605f58b6b2b22))
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
### Bug Fixes
|
|
33
|
+
|
|
34
|
+
* **npm:** js/styles/assets weren't being found ([#641](https://github.com/mdn/fred/issues/641)) ([1c4e02a](https://github.com/mdn/fred/commit/1c4e02a2ea20da72e8a43b9362c8a285f060af5c))
|
|
35
|
+
|
|
3
36
|
## [1.1.1](https://github.com/mdn/fred/compare/v1.1.0...v1.1.1) (2025-08-28)
|
|
4
37
|
|
|
5
38
|
|
package/README.md
CHANGED
|
@@ -26,6 +26,10 @@ MDN's next fr(ont)e(n)d.
|
|
|
26
26
|
|
|
27
27
|
## Development principles
|
|
28
28
|
|
|
29
|
+
### Environment variables
|
|
30
|
+
|
|
31
|
+
See [the environment variables README](./components/env/README.md).
|
|
32
|
+
|
|
29
33
|
### Inline JS
|
|
30
34
|
|
|
31
35
|
We need to run some JS as soon as possible at page load, to avoid layout shifts and flashes.
|
package/build/env.js
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
|
|
3
|
+
const defaultOut = path.join(import.meta.dirname, "..", "out");
|
|
4
|
+
const nodeModule = defaultOut.endsWith(
|
|
5
|
+
path.join("node_modules", "@mdn", "fred", "out"),
|
|
6
|
+
);
|
|
7
|
+
|
|
8
|
+
export const RARI_BUILD_ROOT = process.env.BUILD_OUT_ROOT || defaultOut;
|
|
9
|
+
|
|
10
|
+
// When running from an npm package, this needs to be the default output directory,
|
|
11
|
+
// so we can load the pre-built assets
|
|
12
|
+
export const FRED_BUILD_ROOT = nodeModule ? defaultOut : RARI_BUILD_ROOT;
|
package/build/render.js
CHANGED
|
@@ -2,27 +2,23 @@ import { readFile } from "node:fs/promises";
|
|
|
2
2
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
// but when we package it into an npm package, it needs to be a relative path
|
|
7
|
-
// based on the value of BUILD_OUT_ROOT at that point in time
|
|
8
|
-
// https://github.com/mdn/fred/issues/594
|
|
9
|
-
const BUILD_OUT_ROOT = path.resolve(import.meta.dirname, "..", "out");
|
|
5
|
+
import { FRED_BUILD_ROOT } from "./env.js";
|
|
10
6
|
|
|
11
7
|
const { render: distRender } = /** @type {import("../entry.ssr.js")} */ (
|
|
12
|
-
await import(path.resolve(
|
|
8
|
+
await import(path.resolve(FRED_BUILD_ROOT, "static", "ssr", "index.js"))
|
|
13
9
|
);
|
|
14
10
|
|
|
15
11
|
/** @type {import("@rspack/core").StatsCompilation} */
|
|
16
12
|
const clientManifest = JSON.parse(
|
|
17
13
|
await readFile(
|
|
18
|
-
path.join(
|
|
14
|
+
path.join(FRED_BUILD_ROOT, "static", "client", "stats.json"),
|
|
19
15
|
"utf8",
|
|
20
16
|
),
|
|
21
17
|
);
|
|
22
18
|
/** @type {import("@rspack/core").StatsCompilation} */
|
|
23
19
|
const legacyManifest = JSON.parse(
|
|
24
20
|
await readFile(
|
|
25
|
-
path.join(
|
|
21
|
+
path.join(FRED_BUILD_ROOT, "static", "legacy", "stats.json"),
|
|
26
22
|
"utf8",
|
|
27
23
|
),
|
|
28
24
|
);
|
package/build/ssr.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
1
2
|
import { readFile, writeFile } from "node:fs/promises";
|
|
2
3
|
|
|
3
4
|
import { fdir } from "fdir";
|
|
4
5
|
|
|
5
|
-
import {
|
|
6
|
+
import { RARI_BUILD_ROOT } from "./env.js";
|
|
6
7
|
import { render } from "./render.js";
|
|
7
8
|
|
|
8
9
|
/**
|
|
@@ -59,7 +60,7 @@ async function findDocuments() {
|
|
|
59
60
|
.withFullPaths()
|
|
60
61
|
.withErrors()
|
|
61
62
|
.filter((filePath) => filePath.endsWith("/index.json"))
|
|
62
|
-
.crawl(
|
|
63
|
+
.crawl(RARI_BUILD_ROOT);
|
|
63
64
|
const docs = await api.withPromise();
|
|
64
65
|
return docs;
|
|
65
66
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Environment Variables
|
|
2
|
+
|
|
3
|
+
If a component or other part of Fred requires a variable set from the environment, you should define it in the [`./index.js`](./index.js) file, with a safe default value.
|
|
4
|
+
|
|
5
|
+
## Defaults
|
|
6
|
+
|
|
7
|
+
We set safe defaults for prod, unless the risk from doing - and having this set everywhere, across local dev etc. - outweighs the risk of it not being set on prod.
|
|
8
|
+
|
|
9
|
+
E.g. we don't set `GLEAN_ENABLED` to the prod default, as we don't want to send telemetry pings for prod from other environments, and we'll notice in our telemetry if it's not set in prod.
|
|
10
|
+
|
|
11
|
+
## Naming
|
|
12
|
+
|
|
13
|
+
Within Fred, variables are unprefixed, however the environment variable name is prefixed with `FRED_` to avoid conflicts with other environment variables. For example, if you define a variable `MY_VAR` in Fred, the environment variable to set would be `FRED_MY_VAR`.
|
|
14
|
+
|
|
15
|
+
## Secrets
|
|
16
|
+
|
|
17
|
+
Rspack will bundle **all** environment variables prefixed with `FRED_` into the bundle, which is exposed client side.
|
|
18
|
+
|
|
19
|
+
> [!WARNING]
|
|
20
|
+
> **Never set secrets** through `FRED_` environment variables.
|
|
21
|
+
>
|
|
22
|
+
> As secrets can only be used in server-side components, you should simply set them through a non-`FRED_`-prefixed environment variable, and access them using the `process.env` object.
|
|
23
|
+
|
|
24
|
+
## Build-time vs runtime
|
|
25
|
+
|
|
26
|
+
By default, variables are baked into our bundle at build time. However, you can define variables as runtime environment variables, which can be changed when running a version of Fred built with `FRED_RUNTIME_ENV=true`.
|
|
27
|
+
|
|
28
|
+
This is used in our npm package, so we can e.g. set `FRED_WRITER_MODE=true` in the `content` repo, without having to bake that into the npm package for all consumers.
|
package/components/env/index.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
* @file Retrieves environment variables, setting defaults, for other areas of the app.
|
|
3
|
-
*
|
|
4
|
-
* We set safe defaults for prod, unless the risk from doing - and having this set
|
|
5
|
-
* everywhere, across local dev etc. - outweighs the risk of it not being set on prod.
|
|
6
|
-
*/
|
|
1
|
+
import { parseBool, parseInt, parseString } from "./utils.js";
|
|
7
2
|
|
|
8
3
|
export const PLAYGROUND_BASE_HOST = parseString(
|
|
9
4
|
"PLAYGROUND_BASE_HOST",
|
|
10
5
|
"mdnplay.dev",
|
|
11
6
|
);
|
|
12
|
-
export const PLAYGROUND_LOCAL = parseBool("PLAYGROUND_LOCAL", false
|
|
7
|
+
export const PLAYGROUND_LOCAL = parseBool("PLAYGROUND_LOCAL", false, {
|
|
8
|
+
runtime: true,
|
|
9
|
+
});
|
|
10
|
+
export const PORT = parseInt("PORT", 3000, { runtime: true });
|
|
11
|
+
export const PLAYGROUND_PORT = parseInt("PLAYGROUND_PORT", 3001, {
|
|
12
|
+
runtime: true,
|
|
13
|
+
});
|
|
13
14
|
|
|
14
15
|
export const FXA_SIGNIN_URL = parseString(
|
|
15
16
|
"FXA_SIGNIN_URL",
|
|
@@ -33,7 +34,7 @@ export const GLEAN_DEBUG = parseBool("GLEAN_DEBUG", false);
|
|
|
33
34
|
*/
|
|
34
35
|
export const ROBOTS_GLOBAL_ALLOW = parseBool("ROBOTS_GLOBAL_ALLOW", true);
|
|
35
36
|
|
|
36
|
-
export const WRITER_MODE = parseBool("WRITER_MODE", false);
|
|
37
|
+
export const WRITER_MODE = parseBool("WRITER_MODE", false, { runtime: true });
|
|
37
38
|
|
|
38
39
|
export const BCD_BASE_URL = parseString(
|
|
39
40
|
"BCD_BASE_URL",
|
|
@@ -44,25 +45,3 @@ export const OBSERVATORY_API_URL = parseString(
|
|
|
44
45
|
"OBSERVATORY_API_URL",
|
|
45
46
|
"https://observatory-api.mdn.mozilla.net",
|
|
46
47
|
);
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* @param {string} name
|
|
50
|
-
* @param {boolean} fallback
|
|
51
|
-
*/
|
|
52
|
-
function parseBool(name, fallback) {
|
|
53
|
-
try {
|
|
54
|
-
return Boolean(
|
|
55
|
-
JSON.parse(process.env[`FRED_${name}`] || JSON.stringify(fallback)),
|
|
56
|
-
);
|
|
57
|
-
} catch {
|
|
58
|
-
return fallback;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* @param {string} name
|
|
64
|
-
* @param {string} fallback
|
|
65
|
-
*/
|
|
66
|
-
function parseString(name, fallback) {
|
|
67
|
-
return process.env[`FRED_${name}`] || fallback;
|
|
68
|
-
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { parseBool } from "./utils.js";
|
|
2
|
+
|
|
3
|
+
/** @type {string[]} */
|
|
4
|
+
export const runtimeVariables = [];
|
|
5
|
+
/** Overriden to prod default (false) in rspack config, set to true so it works in dev server by default. */
|
|
6
|
+
export const RUNTIME_ENV = parseBool("RUNTIME_ENV", true);
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { RUNTIME_ENV, runtimeVariables } from "./runtime.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {object} Options
|
|
5
|
+
* @property {boolean} [runtime] Allow setting this value at runtime
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {string} name
|
|
10
|
+
* @param {boolean} fallback
|
|
11
|
+
* @param {Options} [options]
|
|
12
|
+
*/
|
|
13
|
+
export function parseBool(name, fallback, options) {
|
|
14
|
+
try {
|
|
15
|
+
return Boolean(
|
|
16
|
+
JSON.parse(getEnv(name, options) || JSON.stringify(fallback)),
|
|
17
|
+
);
|
|
18
|
+
} catch {
|
|
19
|
+
return fallback;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @param {string} name
|
|
25
|
+
* @param {number} fallback
|
|
26
|
+
* @param {Options} [options]
|
|
27
|
+
*/
|
|
28
|
+
export function parseInt(name, fallback, options) {
|
|
29
|
+
const stringValue = getEnv(name, options);
|
|
30
|
+
const numberValue = stringValue ? Number.parseInt(stringValue, 10) : fallback;
|
|
31
|
+
return Number.isNaN(numberValue) ? fallback : numberValue;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @param {string} name
|
|
36
|
+
* @param {string} fallback
|
|
37
|
+
* @param {Options} [options]
|
|
38
|
+
*/
|
|
39
|
+
export function parseString(name, fallback, options) {
|
|
40
|
+
return getEnv(name, options) || fallback;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @param {string} name
|
|
45
|
+
* @param {Options} [options]
|
|
46
|
+
* @returns {string | undefined}
|
|
47
|
+
*/
|
|
48
|
+
function getEnv(name, options = {}) {
|
|
49
|
+
const { runtime } = { runtime: false, ...options };
|
|
50
|
+
const fullName = `FRED_${name}`;
|
|
51
|
+
if (runtime && RUNTIME_ENV) {
|
|
52
|
+
runtimeVariables.push(fullName);
|
|
53
|
+
return process.env[fullName] || getEnv(name);
|
|
54
|
+
}
|
|
55
|
+
return globalThis.__MDNEnv?.[fullName];
|
|
56
|
+
}
|
|
@@ -5,6 +5,7 @@ import { unsafeHTML } from "lit/directives/unsafe-html.js";
|
|
|
5
5
|
|
|
6
6
|
import inlineScript from "../../entry.inline.js?source&csp=true";
|
|
7
7
|
import { ROBOTS_GLOBAL_ALLOW, WRITER_MODE } from "../env/index.js";
|
|
8
|
+
import { RUNTIME_ENV, runtimeVariables } from "../env/runtime.js";
|
|
8
9
|
import Favicon from "../favicon/pure.js";
|
|
9
10
|
import { asyncLocalStorage } from "../server/async-local-storage.js";
|
|
10
11
|
import { ServerComponent } from "../server/index.js";
|
|
@@ -68,6 +69,12 @@ export class OuterLayout extends ServerComponent {
|
|
|
68
69
|
? "learn"
|
|
69
70
|
: undefined;
|
|
70
71
|
|
|
72
|
+
const env = Object.fromEntries(
|
|
73
|
+
Object.entries(process.env).filter(([key]) =>
|
|
74
|
+
runtimeVariables.includes(key),
|
|
75
|
+
),
|
|
76
|
+
);
|
|
77
|
+
|
|
71
78
|
// if you want to put some script inline, put it in entry.inline.js
|
|
72
79
|
// and you'll get CSP generation: see the README
|
|
73
80
|
return html`
|
|
@@ -86,6 +93,11 @@ export class OuterLayout extends ServerComponent {
|
|
|
86
93
|
content="width=device-width, initial-scale=1.0"
|
|
87
94
|
/>
|
|
88
95
|
<title>${context.pageTitle || "MDN"}</title>
|
|
96
|
+
${RUNTIME_ENV
|
|
97
|
+
? unsafeHTML(`<script>process = {
|
|
98
|
+
env: ${JSON.stringify(env)}
|
|
99
|
+
};</script>`)
|
|
100
|
+
: nothing}
|
|
89
101
|
${unsafeHTML(`<script>${inlineScript}</script>`)}
|
|
90
102
|
${styles.map(
|
|
91
103
|
(path) =>
|
|
@@ -5,7 +5,12 @@ import { keyed } from "lit/directives/keyed.js";
|
|
|
5
5
|
import { createRef, ref } from "lit/directives/ref.js";
|
|
6
6
|
|
|
7
7
|
import { ThemeController } from "../color-theme/controller.js";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
PLAYGROUND_BASE_HOST,
|
|
10
|
+
PLAYGROUND_LOCAL,
|
|
11
|
+
PLAYGROUND_PORT,
|
|
12
|
+
PORT,
|
|
13
|
+
} from "../env/index.js";
|
|
9
14
|
import { compressAndBase64Encode } from "../playground/utils.js";
|
|
10
15
|
|
|
11
16
|
import styles from "./element.css?lit";
|
|
@@ -101,7 +106,7 @@ export class MDNPlayRunner extends LitElement {
|
|
|
101
106
|
const url = new URL(
|
|
102
107
|
`${prefix}/runner.html`,
|
|
103
108
|
PLAYGROUND_LOCAL
|
|
104
|
-
? location.origin.replace(
|
|
109
|
+
? location.origin.replace(PORT.toString(), PLAYGROUND_PORT.toString())
|
|
105
110
|
: `${location.protocol}//${this._subdomain}.${PLAYGROUND_BASE_HOST}`,
|
|
106
111
|
);
|
|
107
112
|
// pass the uuid for postMessage isolation
|