Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't regenerate if input files are older than output file (take 2) #14078

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
79 changes: 46 additions & 33 deletions client/shared/dev/generateGraphQlOperations.js
Expand Up @@ -2,6 +2,7 @@

const { generate } = require('@graphql-codegen/cli')
const path = require('path')
const isInputNewer = require('./isInputNewer')

const ROOT_FOLDER = path.resolve(__dirname, '../../../')

Expand Down Expand Up @@ -32,6 +33,50 @@ const plugins = [`${SHARED_FOLDER}/dev/extractGraphQlOperationCodegenPlugin.js`,
* @param {{ watch?: boolean }} [options]
*/
async function generateGraphQlOperations({ watch } = {}) {
const allGenerateOperations = {
[path.join(BROWSER_FOLDER, './src/graphql-operations.ts')]: {
documents: BROWSER_DOCUMENTS_GLOB,
config: {
onlyOperationTypes: true,
noExport: false,
enumValues: '../../shared/src/graphql-operations',
interfaceNameForOperations: 'BrowserGraphQlOperations',
},
plugins,
},
[path.join(WEB_FOLDER, './src/graphql-operations.ts')]: {
documents: WEB_DOCUMENTS_GLOB,
config: {
onlyOperationTypes: true,
noExport: false,
enumValues: '../../shared/src/graphql-operations',
interfaceNameForOperations: 'WebGraphQlOperations',
},
plugins,
},
[path.join(SHARED_FOLDER, './src/graphql-operations.ts')]: {
documents: SHARED_DOCUMENTS_GLOB,
config: {
onlyOperationTypes: true,
noExport: false,
interfaceNameForOperations: 'SharedGraphQlOperations',
},
plugins,
},
}
const generateOperations = {}
for (const outfile of Object.keys(allGenerateOperations)) {
const inputs = allGenerateOperations[outfile].documents
if (watch || (await isInputNewer(inputs, outfile))) {
generateOperations[outfile] = allGenerateOperations[outfile]
} else {
console.log(`skipping generation of ${outfile}, because all inputs were older`)
}
}
if (Object.keys(generateOperations).length === 0) {
return
}

await generate(
{
watch,
Expand Down Expand Up @@ -64,39 +109,7 @@ async function generateGraphQlOperations({ watch } = {}) {
PublishedValue: "boolean | 'draft'",
},
},
generates: {
[path.join(BROWSER_FOLDER, './src/graphql-operations.ts')]: {
documents: BROWSER_DOCUMENTS_GLOB,
config: {
onlyOperationTypes: true,
noExport: false,
enumValues: '../../shared/src/graphql-operations',
interfaceNameForOperations: 'BrowserGraphQlOperations',
},
plugins,
},

[path.join(WEB_FOLDER, './src/graphql-operations.ts')]: {
documents: WEB_DOCUMENTS_GLOB,
config: {
onlyOperationTypes: true,
noExport: false,
enumValues: '../../shared/src/graphql-operations',
interfaceNameForOperations: 'WebGraphQlOperations',
},
plugins,
},

[path.join(SHARED_FOLDER, './src/graphql-operations.ts')]: {
documents: SHARED_DOCUMENTS_GLOB,
config: {
onlyOperationTypes: true,
noExport: false,
interfaceNameForOperations: 'SharedGraphQlOperations',
},
plugins,
},
},
generates: generateOperations,
},
true
)
Expand Down
24 changes: 24 additions & 0 deletions client/shared/dev/isInputNewer.js
@@ -0,0 +1,24 @@
const { exists, stat } = require('mz/fs')
const glob = require('glob')

// Returns true if ay of the files matched by inputGlobs is newer than the outfile.
async function isInputNewer(inputGlobs, outfile) {
if (!(await exists(outfile))) {
return true
}

const outfileModifiedTime = (await stat(outfile)).mtimeMs
const infileModifiedTimes = await Promise.all(
inputGlobs
.map(inputGlob => glob.sync(inputGlob))
.reduce((a, b) => a.concat(b))
.map(async file => (await stat(file)).mtimeMs)
)
const maxInTime = infileModifiedTimes.reduce((a, b) => (a > b ? a : b), 0)
if (maxInTime > outfileModifiedTime) {
return true
}
return false
}

module.exports = isInputNewer
22 changes: 19 additions & 3 deletions client/shared/gulpfile.js
Expand Up @@ -10,6 +10,7 @@ const path = require('path')
const { format, resolveConfig } = require('prettier')

const { generateGraphQlOperations } = require('./dev/generateGraphQlOperations')
const isInputNewer = require('./dev/isInputNewer')

const GRAPHQL_SCHEMA_PATH = path.join(__dirname, '../../cmd/frontend/graphqlbackend/schema.graphql')

Expand All @@ -20,6 +21,14 @@ const GRAPHQL_SCHEMA_PATH = path.join(__dirname, '../../cmd/frontend/graphqlback
* @returns {Promise<void>}
*/
async function graphQlSchema() {
const outfile = __dirname + '/src/graphql/schema.ts'
if (!(await isInputNewer([GRAPHQL_SCHEMA_PATH], outfile))) {
console.log(
'skipping generation of src/graphql/schema.ts, because input ../cmd/frontend/graphqlbackend/schema.graphql was older'
)
return
}

const schemaString = await readFile(GRAPHQL_SCHEMA_PATH, 'utf8')
const schema = buildSchema(schemaString)

Expand Down Expand Up @@ -54,7 +63,7 @@ async function graphQlSchema() {
postProcessor: code => format(code, { ...formatOptions, parser: 'typescript' }),
}
)
await writeFile(__dirname + '/src/graphql/schema.ts', typings)
await writeFile(outfile, typings)
}

/**
Expand Down Expand Up @@ -101,7 +110,14 @@ async function schema() {
const schemaDirectory = path.join(__dirname, '..', '..', 'schema')
await Promise.all(
['json-schema-draft-07', 'settings', 'site'].map(async file => {
let schema = await readFile(path.join(schemaDirectory, `${file}.schema.json`), 'utf8')
const inputFile = path.join(schemaDirectory, `${file}.schema.json`)
const outputFile = path.join(outputDirectory, `${file}.schema.d.ts`)
if (!(await isInputNewer([inputFile], outputFile))) {
console.log(`skipping generation of ${file}.schema.d.ts, because input ${file}.schema.json was older`)
return
}

let schema = await readFile(inputFile, 'utf8')
// HACK: Rewrite absolute $refs to be relative. They need to be absolute for Monaco to resolve them
// when the schema is in a oneOf (to be merged with extension schemas).
schema = schema.replace(
Expand All @@ -120,7 +136,7 @@ async function schema() {
}),
},
})
await writeFile(path.join(outputDirectory, `${file}.schema.d.ts`), types)
await writeFile(outputFile, types)
})
)
}
Expand Down
6 changes: 5 additions & 1 deletion gulpfile.js
Expand Up @@ -29,7 +29,11 @@ const build = gulp.series(generate, webWebpack)
/**
* Watches everything and rebuilds on file changes.
*/
const dev = gulp.parallel(watchGenerate, webWebpackDevServer)
const dev = gulp.series(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We want to wait for the initial generate steps to complete before running the webpack dev server for 2 reasons:

  • The generated files may be missing when the the webpack dev server expects them to exist, causing errors to be printed.
  • The generate steps will immediately update the generated files, causing webpack dev server to immediately recompile before its first compilation is complete, wasting CPU cycles for no observable improvement in time-to-ready

generate,
gulp.parallel(watchSchema, watchGraphQlSchema, watchGraphQlOperations, webWebpackDevServer)
)


module.exports = {
generate,
Expand Down