Skip to content

Commit

Permalink
Building SPAs shouldn"t be part of "yarn build" (mdn#3043)
Browse files Browse the repository at this point in the history
Fixes mdn#3028
  • Loading branch information
peterbe committed Jun 1, 2021
1 parent 8021b98 commit 156b4be
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 112 deletions.
103 changes: 2 additions & 101 deletions build/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,21 @@ const {
Document,
slugToFolder,
translationsOf,
CONTENT_ROOT,
CONTENT_TRANSLATED_ROOT,
} = require("../content");

// eslint-disable-next-line node/no-missing-require
const { renderDocHTML, renderHTML } = require("../ssr/dist/main");
const { renderDocHTML } = require("../ssr/dist/main");

const options = require("./build-options");
const { buildDocument, renderContributorsTxt } = require("./index");
const SearchIndex = require("./search-index");
const {
BUILD_OUT_ROOT,
HOMEPAGE_FEED_URL,
HOMEPAGE_FEED_DISPLAY_MAX,
} = require("./constants");
const { BUILD_OUT_ROOT } = require("./constants");
const { makeSitemapXML, makeSitemapIndexXML } = require("./sitemaps");
const { humanFileSize } = require("./utils");
const {
syncTranslatedContentForAllLocales,
} = require("./sync-translated-content");
const { getFeedEntries } = require("./feedparser");

async function buildDocumentInteractive(
documentPath,
Expand Down Expand Up @@ -240,10 +234,8 @@ async function buildDocuments(
sitemapsBuilt.push(sitemapFilePath);
}

// Only if you've just built all of CONTENT_ROOT and all of CONTENT_TRANSLATED_ROOT
// do we bother generating the combined sitemaps index file.
// That means, that if you've done this at least once, consequent runs of
// *only* CONTENT_ROOT will just keep overwriting the sitemaps/en-us/sitemap.xml.gz.
if (CONTENT_TRANSLATED_ROOT) {
const sitemapIndexFilePath = path.join(BUILD_OUT_ROOT, "sitemap.xml");
fs.writeFileSync(
Expand All @@ -264,85 +256,6 @@ async function buildDocuments(
return { slugPerLocale: docPerLocale, peakHeapBytes, totalFlaws };
}

async function buildOtherSPAs(options) {
// The URL isn't very important as long as it triggers the right route in the <App/>
const url = "/en-US/404.html";
const html = renderHTML(url, { pageNotFound: true });
const outPath = path.join(BUILD_OUT_ROOT, "en-us", "_spas");
fs.mkdirSync(outPath, { recursive: true });
fs.writeFileSync(path.join(outPath, path.basename(url)), html);
if (!options.quiet) {
console.log("Wrote", path.join(outPath, path.basename(url)));
}

// Basically, this builds one `search/index.html` for every locale we intend
// to build.
for (const root of [CONTENT_ROOT, CONTENT_TRANSLATED_ROOT]) {
if (!root) {
continue;
}
for (const locale of fs.readdirSync(root)) {
if (!fs.statSync(path.join(root, locale)).isDirectory()) {
continue;
}
const url = `/${locale}/search`;
const html = renderHTML(url);
const outPath = path.join(BUILD_OUT_ROOT, locale, "search");
fs.mkdirSync(outPath, { recursive: true });
const filePath = path.join(outPath, "index.html");
fs.writeFileSync(filePath, html);
if (!options.quiet) {
console.log("Wrote", filePath);
}
}
}

// Build all the home pages in all locales.
// Have the feed entries ready before building the home pages.
// XXX disk caching?
const feedEntries = (await getFeedEntries(HOMEPAGE_FEED_URL)).slice(
0,
HOMEPAGE_FEED_DISPLAY_MAX
);
for (const root of [CONTENT_ROOT, CONTENT_TRANSLATED_ROOT]) {
if (!root) {
continue;
}
for (const locale of fs.readdirSync(root)) {
if (!fs.statSync(path.join(root, locale)).isDirectory()) {
continue;
}
const url = `/${locale}/`;
// Each .pubDate in feedEntries is a Date object. That has to be converted
// to a string. That way the SSR rendering is
const dateFormatter = new Intl.DateTimeFormat(locale, {
dateStyle: "full",
});
const context = {
feedEntries: feedEntries.map((entry) => {
const pubDateString = dateFormatter.format(entry.pubDate);
return Object.assign({}, entry, { pubDate: pubDateString });
}),
};
const html = renderHTML(url, context);
const outPath = path.join(BUILD_OUT_ROOT, locale);
fs.mkdirSync(outPath, { recursive: true });
const filePath = path.join(outPath, "index.html");
fs.writeFileSync(filePath, html);
if (!options.quiet) {
console.log("Wrote", filePath);
}
// Also, dump the feed entries as a JSON file so the data can be gotten
// in client-side rendering.
const filePathContext = path.join(outPath, "index.json");
fs.writeFileSync(filePathContext, JSON.stringify(context));
if (!options.quiet) {
console.log("Wrote", filePathContext);
}
}
}
}

function formatTotalFlaws(flawsCountMap, header = "Total_Flaws_Count") {
if (!flawsCountMap.size) {
return "";
Expand All @@ -362,8 +275,6 @@ function formatTotalFlaws(flawsCountMap, header = "Total_Flaws_Count") {

program
.name("build")
.option("--spas", "Build the SPA pages", { default: true }) // PR builds
.option("--spas-only", "Only build the SPA pages", { default: false })
.option(
"--sync-translated-content",
"Sync translated content in all locales (apply en-us redirects to locales)",
Expand All @@ -377,16 +288,6 @@ program
.argument("[files...]", "specific files to build")
.action(async ({ args, options }) => {
try {
if (options.spas) {
if (!options.quiet) {
console.log("\nBuilding SPAs...");
}
await buildOtherSPAs(options);
}
if (options.spasOnly) {
return;
}

if (options.syncTranslatedContent && CONTENT_TRANSLATED_ROOT) {
const documentsMoved = syncTranslatedContentForAllLocales();
if (documentsMoved !== 0) {
Expand Down
2 changes: 2 additions & 0 deletions build/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const { getPageTitle } = require("./page-title");
const { syntaxHighlight } = require("./syntax-highlight");
const buildOptions = require("./build-options");
const { gather: gatherGitHistory } = require("./git-history");
const { buildSPAs } = require("./spas");
const { renderCache: renderKumascriptCache } = require("../kumascript");

const DEFAULT_BRANCH_NAME = "main"; // That's what we use for github.com/mdn/content
Expand Down Expand Up @@ -565,4 +566,5 @@ module.exports = {

options: buildOptions,
gatherGitHistory,
buildSPAs,
};
93 changes: 93 additions & 0 deletions build/spas.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
const fs = require("fs");
const path = require("path");

const { CONTENT_ROOT, CONTENT_TRANSLATED_ROOT } = require("../content");
const {
BUILD_OUT_ROOT,
HOMEPAGE_FEED_URL,
HOMEPAGE_FEED_DISPLAY_MAX,
} = require("./constants");
const { getFeedEntries } = require("./feedparser");
// eslint-disable-next-line node/no-missing-require
const { renderHTML } = require("../ssr/dist/main");

async function buildSPAs(options) {
// The URL isn't very important as long as it triggers the right route in the <App/>
const url = "/en-US/404.html";
const html = renderHTML(url, { pageNotFound: true });
const outPath = path.join(BUILD_OUT_ROOT, "en-us", "_spas");
fs.mkdirSync(outPath, { recursive: true });
fs.writeFileSync(path.join(outPath, path.basename(url)), html);
if (!options.quiet) {
console.log("Wrote", path.join(outPath, path.basename(url)));
}

// Basically, this builds one `search/index.html` for every locale we intend
// to build.
for (const root of [CONTENT_ROOT, CONTENT_TRANSLATED_ROOT]) {
if (!root) {
continue;
}
for (const locale of fs.readdirSync(root)) {
if (!fs.statSync(path.join(root, locale)).isDirectory()) {
continue;
}
const url = `/${locale}/search`;
const html = renderHTML(url);
const outPath = path.join(BUILD_OUT_ROOT, locale, "search");
fs.mkdirSync(outPath, { recursive: true });
const filePath = path.join(outPath, "index.html");
fs.writeFileSync(filePath, html);
if (!options.quiet) {
console.log("Wrote", filePath);
}
}
}

// Build all the home pages in all locales.
// Have the feed entries ready before building the home pages.
// XXX disk caching?
const feedEntries = (await getFeedEntries(HOMEPAGE_FEED_URL)).slice(
0,
HOMEPAGE_FEED_DISPLAY_MAX
);
for (const root of [CONTENT_ROOT, CONTENT_TRANSLATED_ROOT]) {
if (!root) {
continue;
}
for (const locale of fs.readdirSync(root)) {
if (!fs.statSync(path.join(root, locale)).isDirectory()) {
continue;
}
const url = `/${locale}/`;
// Each .pubDate in feedEntries is a Date object. That has to be converted
// to a string. That way the SSR rendering is
const dateFormatter = new Intl.DateTimeFormat(locale, {
dateStyle: "full",
});
const context = {
feedEntries: feedEntries.map((entry) => {
const pubDateString = dateFormatter.format(entry.pubDate);
return Object.assign({}, entry, { pubDate: pubDateString });
}),
};
const html = renderHTML(url, context);
const outPath = path.join(BUILD_OUT_ROOT, locale);
fs.mkdirSync(outPath, { recursive: true });
const filePath = path.join(outPath, "index.html");
fs.writeFileSync(filePath, html);
if (!options.quiet) {
console.log("Wrote", filePath);
}
// Also, dump the feed entries as a JSON file so the data can be gotten
// in client-side rendering.
const filePathContext = path.join(outPath, "index.json");
fs.writeFileSync(filePathContext, JSON.stringify(context));
if (!options.quiet) {
console.log("Wrote", filePathContext);
}
}
}
}

module.exports = { buildSPAs };
9 changes: 1 addition & 8 deletions docs/spas.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,7 @@ For example the `404` page. These are rendered server-side but without a "doc".
To build these you run:

```sh
yarn build --spas-only
```

By default, running only `yarn build` will build all documents _and_ all SPAs.
Should you wish to only build documents, use:

```sh
yarn build --no-spas
yarn tool spas
```

The SPAs are also built when running `yarn prepare-build` or `yarn start`.
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
"filecheck": "cd filecheck && node cli.js",
"fiori:build": "cd client && build-storybook",
"fiori:start": "cd client && start-storybook -p 6006",
"prepare-build": "yarn build:client && yarn build:ssr && yarn tool google-analytics-code && yarn build --spas-only && yarn tool gather-git-history --verbose",
"prepare-build": "yarn build:client && yarn build:ssr && yarn tool google-analytics-code && yarn tool spas && yarn tool gather-git-history --verbose",
"prettier-check": "prettier --check .",
"prettier-format": "prettier --write .",
"start": "(test -f client/build/index.html || yarn build:client) && (test -f ssr/dist/main.js || yarn build:ssr) && (test -d client/build/en-us/_spas || yarn build --spas-only) && nf -j Procfile.start start",
"start": "(test -f client/build/index.html || yarn build:client) && (test -f ssr/dist/main.js || yarn build:ssr) && (test -d client/build/en-us/_spas || yarn tool spas) && nf -j Procfile.start start",
"start:client": "cd client && cross-env BROWSER=none PORT=3000 react-scripts start",
"start:dev-server": "nodemon server --watch server --watch build --watch content --watch kumascript --ext js --watch ssr/dist",
"start:server": "node server",
Expand Down
9 changes: 8 additions & 1 deletion tool/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const {
Document,
buildURL,
} = require("../content");
const { buildDocument, gatherGitHistory } = require("../build");
const { buildDocument, gatherGitHistory, buildSPAs } = require("../build");
const {
BUILD_OUT_ROOT,
GOOGLE_ANALYTICS_ACCOUNT,
Expand Down Expand Up @@ -740,6 +740,13 @@ if (Mozilla && !Mozilla.dntEnabled()) {
logger.info(chalk.yellow("No Google Analytics code file generated"));
}
})
)

.command("spas", "Build (SSR) all the skeleton apps for single page apps")
.action(
tryOrExit(async ({ options }) => {
await buildSPAs(options);
})
);

program.run();

0 comments on commit 156b4be

Please sign in to comment.