refactor(client): speed up client updates (#65025)

This commit is contained in:
Oliver Eyton-Williams
2026-02-10 13:39:55 +01:00
committed by GitHub
parent d6d452dfac
commit e6eb338fe6
6 changed files with 258 additions and 106 deletions
+1 -87
View File
@@ -8,7 +8,6 @@ const webpack = require('webpack');
const { SuperBlocks } = require('@freecodecamp/shared/config/curriculum');
const env = require('./config/env.json');
const {
createChallengePages,
createBlockIntroPages,
createSuperBlockIntroPages
} = require('./utils/gatsby');
@@ -60,62 +59,11 @@ exports.createPages = async function createPages({
const result = await graphql(`
{
allChallengeNode(
sort: {
fields: [
challenge___superOrder
challenge___order
challenge___challengeOrder
]
}
) {
allChallengeNode {
edges {
node {
id
challenge {
block
blockLabel
blockLayout
certification
challengeType
dashedName
demoType
disableLoopProtectTests
disableLoopProtectPreview
fields {
slug
blockHashSlug
}
id
isLastChallengeInBlock
order
required {
link
src
}
challengeOrder
challengeFiles {
name
ext
contents
head
tail
history
fileKey
}
saveSubmissionToDB
solutions {
contents
ext
history
fileKey
}
superBlock
superOrder
template
usesMultifileEditor
chapter
module
}
}
}
@@ -140,40 +88,6 @@ exports.createPages = async function createPages({
}
`);
const allChallengeNodes = result.data.allChallengeNode.edges.map(
({ node }) => node
);
const createIdToNextPathMap = nodes =>
nodes.reduce((map, node, index) => {
const nextNode = nodes[index + 1];
const nextPath = nextNode ? nextNode.challenge.fields.slug : null;
if (nextPath) map[node.id] = nextPath;
return map;
}, {});
const createIdToPrevPathMap = nodes =>
nodes.reduce((map, node, index) => {
const prevNode = nodes[index - 1];
const prevPath = prevNode ? prevNode.challenge.fields.slug : null;
if (prevPath) map[node.id] = prevPath;
return map;
}, {});
const idToNextPathCurrentCurriculum =
createIdToNextPathMap(allChallengeNodes);
const idToPrevPathCurrentCurriculum =
createIdToPrevPathMap(allChallengeNodes);
// Create challenge pages.
result.data.allChallengeNode.edges.forEach(
createChallengePages(createPage, {
idToNextPathCurrentCurriculum,
idToPrevPathCurrentCurriculum
})
);
const blocks = uniq(
result.data.allChallengeNode.edges.map(
({
-1
View File
@@ -51,7 +51,6 @@ exports.replaceChallengeNodes = () => {
const block = path.basename(parentDir);
const filename = path.basename(filePath);
console.log(`Replacing challenge nodes for ${filePath}`);
const meta = getBlockStructure(block);
const superblocks = getSuperblocks(block);
+13 -11
View File
@@ -69,23 +69,25 @@ const views = {
examDownload
};
function getIsFirstStepInBlock(id, edges) {
const current = edges[id];
const previous = edges[id - 1];
function getIsFirstStepInBlock(id, nodes) {
const current = nodes[id];
const previous = nodes[id - 1];
if (!previous) return true;
return previous.node.challenge.block !== current.node.challenge.block;
return previous.challenge.block !== current.challenge.block;
}
function getTemplateComponent(challengeType) {
return views[viewTypes[challengeType]];
}
exports.getTemplateComponent = getTemplateComponent;
exports.createChallengePages = function (
createPage,
{ idToNextPathCurrentCurriculum, idToPrevPathCurrentCurriculum }
) {
return function ({ node }, index, allChallengeEdges) {
return function (node, index, allChallengeNodes) {
const {
dashedName,
disableLoopProtectTests,
@@ -118,7 +120,7 @@ exports.createChallengePages = function (
chapter,
module,
block,
isFirstStep: getIsFirstStepInBlock(index, allChallengeEdges),
isFirstStep: getIsFirstStepInBlock(index, allChallengeNodes),
template,
required,
isLastChallengeInBlock: isLastChallengeInBlock,
@@ -129,7 +131,7 @@ exports.createChallengePages = function (
},
projectPreview: getProjectPreviewConfig(
node.challenge,
allChallengeEdges
allChallengeNodes
),
id: node.id
}
@@ -140,12 +142,12 @@ exports.createChallengePages = function (
// TODO: figure out a cleaner way to get the last challenge in a block. Create
// it during the curriculum build process and attach it to the first challenge?
// That would remove the need to analyse allChallengeEdges.
function getProjectPreviewConfig(challenge, allChallengeEdges) {
function getProjectPreviewConfig(challenge, allChallengeNodes) {
const { block } = challenge;
const challengesInBlock = allChallengeEdges
.filter(({ node: { challenge } }) => challenge.block === block)
.map(({ node: { challenge } }) => challenge);
const challengesInBlock = allChallengeNodes
.filter(({ challenge }) => challenge.block === block)
.map(({ challenge }) => challenge);
const lastChallenge = challengesInBlock[challengesInBlock.length - 1];
const solutionFiles = lastChallenge.solutions[0] ?? [];
const lastChallengeFiles = lastChallenge.challengeFiles ?? [];