11import Resolver from "enhanced-resolve/lib/Resolver"
2+ import mod from "module"
23
34interface IRequest {
45 request ?: string
@@ -8,17 +9,98 @@ interface IRequest {
89type ProcessWithPNP = NodeJS . ProcessVersions & { pnp ?: string }
910
1011/**
11- * To support PNP we have to make sure dependencies resolved from the .cache folder should be resolved from the gatsby package directory
12+ * To support Yarn PNP and pnpm we have to make sure dependencies resolved from
13+ * the .cache folder should be resolved from the gatsby package directory
14+ * If you see error like
15+ *
16+ * ModuleNotFoundError: Module not found: Error: Can't resolve 'prop-types'
17+ * in '<site-directory>/.cache'
18+ *
19+ * it probably means this plugin is not enabled when it should be and there
20+ * might be need to adjust conditions for setting `this.isEnabled` in the
21+ * constructor.
22+ *
23+ * It's not enabled always because of legacy behavior and to limit potential
24+ * regressions. Might be good idea to enable it always in the future
25+ * OR remove the need for the plugin completely by not copying `cache-dir`
26+ * contents to `.cache` folder and instead adjust setup to use those browser/node
27+ * html renderer runtime files directly from gatsby package
1228 */
1329export class CacheFolderResolver {
1430 private requestsFolder : string
31+ private isEnabled = false
1532
1633 constructor ( requestsFolder : string ) {
1734 this . requestsFolder = requestsFolder
35+
36+ if ( ( process . versions as ProcessWithPNP ) . pnp ) {
37+ // Yarn PnP
38+ this . isEnabled = true
39+ } else if ( / n o d e _ m o d u l e s [ / \\ ] \. p n p m / . test ( process . env . NODE_PATH ?? `` ) ) {
40+ // pnpm when executing through `pnpm` CLI
41+ this . isEnabled = true
42+ } else {
43+ // pnpm when executing through regular `gatsby` CLI / `./node_modules/.bin/gatsby`
44+ // would not set NODE_PATH, but node_modules structure would not allow to resolve
45+ // gatsby deps from the cache folder (unless user would install same deps too)
46+ // so we are checking if we can resolve deps from the cache folder
47+ // this check is not limited to pnpm and other package managers could hit this path too
48+
49+ // Hardcoded list of gatsby deps used in gatsby browser and ssr runtimes
50+ // instead of checking if we use Yarn PnP (via `process.versions.pnp`),
51+ // we check if we can resolve the external deps from the cache-dir folder
52+ // to know if we need to enable this plugin so we also cover pnpm
53+ // It might be good idea to always enable it overall, but to limit potential
54+ // regressions we only enable it if we are sure we need it.
55+ const modulesToCheck = [
56+ `prop-types` ,
57+ `lodash/isEqual` ,
58+ `mitt` ,
59+ `shallow-compare` ,
60+ `@gatsbyjs/reach-router` ,
61+ `gatsby-react-router-scroll` ,
62+ `react-server-dom-webpack` ,
63+ `gatsby-link` ,
64+ ]
65+
66+ // test if we can resolve deps from the cache folder
67+ let isEverythingResolvableFromCacheDir = true
68+ const cacheDirReq = mod . createRequire ( requestsFolder )
69+ for ( const cacheDirDep of modulesToCheck ) {
70+ try {
71+ cacheDirReq . resolve ( cacheDirDep )
72+ } catch {
73+ // something is not resolvable from the cache folder, so we should not enable this plugin
74+ isEverythingResolvableFromCacheDir = false
75+ break
76+ }
77+ }
78+
79+ // test if we can resolve deps from the gatsby package
80+ let isEverythingResolvableFromGatsbyPackage = true
81+ for ( const cacheDirDep of modulesToCheck ) {
82+ try {
83+ require . resolve ( cacheDirDep )
84+ } catch {
85+ // something is not resolvable from the gatsby package
86+ isEverythingResolvableFromGatsbyPackage = false
87+ break
88+ }
89+ }
90+
91+ // we only enable this plugin if we are unable to resolve cache-dir deps from .cache folder
92+ // and we can resolve them from gatsby package
93+ if (
94+ ! isEverythingResolvableFromCacheDir &&
95+ isEverythingResolvableFromGatsbyPackage
96+ ) {
97+ this . isEnabled = true
98+ }
99+ }
18100 }
19101
20102 apply ( resolver : Resolver ) : void {
21- if ( ! ( process . versions as ProcessWithPNP ) . pnp ) {
103+ if ( ! this . isEnabled ) {
22104 return
23105 }
24106
0 commit comments