From 866f8ae100dbd474bf332000587d86ee134aefec Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Tue, 14 Nov 2023 00:11:37 -0800 Subject: [PATCH 1/3] Remove `wait-on` dependency Fixes https://github.com/facebook/docusaurus/issues/9537 This change removes usage of `wait-on`, and replaces it with an effective copy of the algorithm it ends up taking for our use case. 1. `wait-on` sees a file as present when `fs.stat` on the path stops throwing 2. It polls on a timer (which WaitPlugin sets to 300ms) 3. It waits until a time has passed without file size changing (defaults to 750ms) 4. `wait-on` defaults to no timout, so we poll forever. See https://github.com/jeffbski/wait-on/blob/master/lib/wait-on.js for reference --- packages/docusaurus/package.json | 2 - .../src/webpack/plugins/WaitPlugin.ts | 54 ++++++++++++------- yarn.lock | 32 ++--------- 3 files changed, 39 insertions(+), 49 deletions(-) diff --git a/packages/docusaurus/package.json b/packages/docusaurus/package.json index a554f5a3441e..0c251b419e6c 100644 --- a/packages/docusaurus/package.json +++ b/packages/docusaurus/package.json @@ -97,7 +97,6 @@ "tslib": "^2.6.0", "update-notifier": "^6.0.2", "url-loader": "^4.1.1", - "wait-on": "^7.0.1", "webpack": "^5.88.1", "webpack-bundle-analyzer": "^4.9.0", "webpack-dev-server": "^4.15.1", @@ -113,7 +112,6 @@ "@types/rtl-detect": "^1.0.0", "@types/serve-handler": "^6.1.1", "@types/update-notifier": "^6.0.4", - "@types/wait-on": "^5.3.1", "@types/webpack-bundle-analyzer": "^4.6.0", "react-test-renderer": "^18.0.0", "tmp-promise": "^3.0.3", diff --git a/packages/docusaurus/src/webpack/plugins/WaitPlugin.ts b/packages/docusaurus/src/webpack/plugins/WaitPlugin.ts index 2ace27913e4c..e5d5ceed7047 100644 --- a/packages/docusaurus/src/webpack/plugins/WaitPlugin.ts +++ b/packages/docusaurus/src/webpack/plugins/WaitPlugin.ts @@ -5,9 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import path from 'path'; -import fs from 'fs-extra'; -import waitOn from 'wait-on'; +import {stat} from 'fs/promises'; import type {Compiler} from 'webpack'; type WaitPluginOptions = { @@ -23,21 +21,41 @@ export default class WaitPlugin { apply(compiler: Compiler): void { // Before finishing the compilation step - compiler.hooks.make.tapAsync('WaitPlugin', (compilation, callback) => { - // To prevent 'waitFile' error on waiting non-existing directory - fs.ensureDir(path.dirname(this.filepath), {}, () => { - // Wait until file exist - waitOn({ - resources: [this.filepath], - interval: 300, - }) - .then(() => { - callback(); - }) - .catch((error: Error) => { - console.warn(`WaitPlugin error: ${error}`); - }); - }); + compiler.hooks.make.tapPromise('WaitPlugin', () => waitOn(this.filepath)); + } +} + +async function waitOn(filepath: string): Promise { + const pollingIntervalMs = 300; + const stabilityWindowMs = 750; + + let lastFileSize = -1; + let lastFileTime = -1; + + for (;;) { + const size = await fileSize(filepath); + + if (size !== null) { + if (size === lastFileSize) { + if (performance.now() - lastFileTime >= stabilityWindowMs) { + return; + } + } else { + lastFileSize = size; + lastFileTime = performance.now(); + } + } + + await new Promise((resolve) => { + setTimeout(resolve, pollingIntervalMs); }); } } + +async function fileSize(filepath: string): Promise { + try { + return (await stat(filepath)).size; + } catch (err) { + return null; + } +} diff --git a/yarn.lock b/yarn.lock index acf3e4715673..b8d68f24f90a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3691,13 +3691,6 @@ "@types/configstore" "*" boxen "^7.0.0" -"@types/wait-on@^5.3.1": - version "5.3.1" - resolved "https://registry.yarnpkg.com/@types/wait-on/-/wait-on-5.3.1.tgz#bc5520d1d8b90b9caab1bef23315685ded73320d" - integrity sha512-2FFOKCF/YydrMUaqg+fkk49qf0e5rDgwt6aQsMzFQzbS419h2gNOXyiwp/o2yYy27bi/C1z+HgfncryjGzlvgQ== - dependencies: - "@types/node" "*" - "@types/webpack-bundle-analyzer@^4.6.0": version "4.6.0" resolved "https://registry.yarnpkg.com/@types/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.6.0.tgz#8863d62d2432126c2b3a9239cafa469215981c24" @@ -4461,14 +4454,6 @@ axe-core@^4.6.2: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.2.tgz#040a7342b20765cb18bb50b628394c21bccc17a0" integrity sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g== -axios@^0.27.2: - version "0.27.2" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972" - integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ== - dependencies: - follow-redirects "^1.14.9" - form-data "^4.0.0" - axios@^1, axios@^1.0.0, axios@^1.5.0: version "1.5.1" resolved "https://registry.yarnpkg.com/axios/-/axios-1.5.1.tgz#11fbaa11fc35f431193a9564109c88c1f27b585f" @@ -7776,7 +7761,7 @@ flux@~4.0.1: fbemitter "^3.0.0" fbjs "^3.0.1" -follow-redirects@^1.0.0, follow-redirects@^1.14.9, follow-redirects@^1.15.0: +follow-redirects@^1.0.0, follow-redirects@^1.15.0: version "1.15.2" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== @@ -9958,7 +9943,7 @@ jkroso-type@1: resolved "https://registry.yarnpkg.com/jkroso-type/-/jkroso-type-1.1.1.tgz#bc4ced6d6c45fe0745282bafc86a9f8c4fc9ce61" integrity sha512-zZgay+fPG6PgMUrpyFADmQmvLo39+AZa7Gc5pZhev2RhDxwANEq2etwD8d0e6rTg5NkwOIlQmaEmns3draC6Ng== -joi@^17.7.0, joi@^17.9.2: +joi@^17.9.2: version "17.9.2" resolved "https://registry.yarnpkg.com/joi/-/joi-17.9.2.tgz#8b2e4724188369f55451aebd1d0b1d9482470690" integrity sha512-Itk/r+V4Dx0V3c7RLFdRh12IOjySm2/WGPMubBT92cQvRfYZhPM2W0hZlctjj72iES8jsRCwp7S/cRmWBnJ4nw== @@ -11804,7 +11789,7 @@ minimist-options@4.1.0: is-plain-obj "^1.1.0" kind-of "^6.0.3" -minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.7: +minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -16574,17 +16559,6 @@ w3c-xmlserializer@^4.0.0: dependencies: xml-name-validator "^4.0.0" -wait-on@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-7.0.1.tgz#5cff9f8427e94f4deacbc2762e6b0a489b19eae9" - integrity sha512-9AnJE9qTjRQOlTZIldAaf/da2eW0eSRSgcqq85mXQja/DW3MriHxkpODDSUEg+Gri/rKEcXUZHe+cevvYItaog== - dependencies: - axios "^0.27.2" - joi "^17.7.0" - lodash "^4.17.21" - minimist "^1.2.7" - rxjs "^7.8.0" - walk-up-path@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/walk-up-path/-/walk-up-path-1.0.0.tgz#d4745e893dd5fd0dbb58dd0a4c6a33d9c9fec53e" From 16a4d3468e7728552833298fec111fe546e4db81 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Tue, 14 Nov 2023 00:27:55 -0800 Subject: [PATCH 2/3] . --- .../src/webpack/plugins/WaitPlugin.ts | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/packages/docusaurus/src/webpack/plugins/WaitPlugin.ts b/packages/docusaurus/src/webpack/plugins/WaitPlugin.ts index e5d5ceed7047..aeb61368f0f4 100644 --- a/packages/docusaurus/src/webpack/plugins/WaitPlugin.ts +++ b/packages/docusaurus/src/webpack/plugins/WaitPlugin.ts @@ -33,16 +33,17 @@ async function waitOn(filepath: string): Promise { let lastFileTime = -1; for (;;) { - const size = await fileSize(filepath); - - if (size !== null) { - if (size === lastFileSize) { - if (performance.now() - lastFileTime >= stabilityWindowMs) { - return; - } - } else { + let size = -1; + try { + size = (await stat(filepath)).size; + } catch (err) {} + + if (size !== -1) { + if (lastFileTime === -1 || size !== lastFileSize) { lastFileSize = size; lastFileTime = performance.now(); + } else if (performance.now() - lastFileTime >= stabilityWindowMs) { + return; } } @@ -51,11 +52,3 @@ async function waitOn(filepath: string): Promise { }); } } - -async function fileSize(filepath: string): Promise { - try { - return (await stat(filepath)).size; - } catch (err) { - return null; - } -} From 3fb71b34bcfee64ada0bec28aba37f8240c5411d Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Mon, 20 Nov 2023 06:07:25 -0800 Subject: [PATCH 3/3] PR Feedback --- packages/docusaurus/src/webpack/plugins/WaitPlugin.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/docusaurus/src/webpack/plugins/WaitPlugin.ts b/packages/docusaurus/src/webpack/plugins/WaitPlugin.ts index aeb61368f0f4..362205c2e860 100644 --- a/packages/docusaurus/src/webpack/plugins/WaitPlugin.ts +++ b/packages/docusaurus/src/webpack/plugins/WaitPlugin.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {stat} from 'fs/promises'; +import fs from 'fs-extra'; import type {Compiler} from 'webpack'; type WaitPluginOptions = { @@ -25,6 +25,8 @@ export default class WaitPlugin { } } +// This is a re-implementation of the algorithm used by the "wait-on" package +// https://github.com/jeffbski/wait-on/blob/master/lib/wait-on.js#L200 async function waitOn(filepath: string): Promise { const pollingIntervalMs = 300; const stabilityWindowMs = 750; @@ -35,7 +37,7 @@ async function waitOn(filepath: string): Promise { for (;;) { let size = -1; try { - size = (await stat(filepath)).size; + size = (await fs.stat(filepath)).size; } catch (err) {} if (size !== -1) {