esbuild icon indicating copy to clipboard operation
esbuild copied to clipboard

Yarn PNP still not working on Windows

Open demigor opened this issue 2 years ago • 6 comments

Hi, just gave esbuild+Yarn pnp a fresh try, but still not getting it working despite being declared as compatible. The smallest ever setup fails to load react libs. Platform: Windows 11.

Separate cache folder for PNP used on build machines to avoid redownloading/relinking node_modules due to clean check outs.

package.json

{
  "name": "my-yarn-test",
  "version": "1.0.0",
  "main": "./index.js",
  "private": true,
  "scripts": {
    "build": "esbuild --bundle ./index.js --loader:.js=jsx --minify --outdir=dist --sourcemap --format=esm --splitting"
  },
  "devDependencies": {
    "esbuild": "^0.19.2"
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "packageManager": "[email protected]"
}

index.js

import { createRoot } from 'react-dom/client'

let root = createRoot(document.getElementById("root"))
root.render(<div/>)

Steps to reproduce:

yarn set version stable
yarn config set cacheFolder d:\yarn.cache 
yarn
yarn build

My results:

D:\test-yarn>yarn set version stable
➤ YN0000: Retrieving https://repo.yarnpkg.com/3.6.3/packages/yarnpkg-cli/bin/yarn.js
➤ YN0000: Saving the new release in .yarn/releases/yarn-3.6.3.cjs
➤ YN0000: Done in 0s 924ms

D:\test-yarn>yarn
➤ YN0000: ┌ Resolution step
➤ YN0000: └ Completed in 3s 312ms
➤ YN0000: ┌ Fetch step
➤ YN0013: │ js-tokens@npm:4.0.0 can't be found in the cache and will be fetched from the remote registry
➤ YN0013: │ loose-envify@npm:1.4.0 can't be found in the cache and will be fetched from the remote registry
➤ YN0013: │ react-dom@npm:18.2.0 can't be found in the cache and will be fetched from the remote registry
➤ YN0013: │ react@npm:18.2.0 can't be found in the cache and will be fetched from the remote registry
➤ YN0013: │ scheduler@npm:0.23.0 can't be found in the cache and will be fetched from the remote registry
➤ YN0000: └ Completed
➤ YN0000: ┌ Link step
➤ YN0007: │ esbuild@npm:0.19.2 must be built because it never has been before or the last one failed
➤ YN0000: └ Completed in 0s 220ms
➤ YN0000: Done in 3s 572ms

D:\test-yarn>yarn build
X [ERROR] Could not resolve "react-dom/client"

    index.js:1:27:
      1 │ import { createRoot } from 'react-dom/client'
        ╵                            ~~~~~~~~~~~~~~~~~~

  You can mark the path "react-dom/client" as external to exclude it from the bundle, which will
  remove this error.

1 error
node:child_process:924
    throw err;
    ^

Error: Command failed: D:\test-yarn\.yarn\unplugged\@esbuild-win32-x64-npm-0.19.2-faf4190546\node_modules\@esbuild\win32-x64\esbuild.exe --bundle ./index.js --loader:.js=jsx --minify --outdir=dist --sourcemap --format=esm --splitting
    at checkExecSyncError (node:child_process:885:11)
    at Object.execFileSync (node:child_process:921:15)
    at Object.<anonymous> (D:\test-yarn\.yarn\unplugged\esbuild-npm-0.19.2-84addf679d\node_modules\esbuild\bin\esbuild:220:28)
    at Module._compile (node:internal/modules/cjs/loader:1256:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1310:10)
    at require$$0.Module._extensions..js (D:\test-yarn\.pnp.cjs:9203:33)
    at Module.load (node:internal/modules/cjs/loader:1119:32)
    at Module._load (node:internal/modules/cjs/loader:960:12)
    at require$$0.Module._load (D:\test-yarn\.pnp.cjs:9048:31) {
  status: 1,
  signal: null,
  output: [ null, null, null ],
  pid: 22264,
  stdout: null,
  stderr: null
}

Node.js v18.16.1

Hope this helps to pinpoint and fix the issue.

Cheers, Lex

demigor avatar Sep 01 '23 00:09 demigor

I've managed to get esbuild to build this simple project by changing cache folder to \yarn.cache This is not what is exactly needed, but at least this way it produces the bundle.

yarn set version stable
yarn config set cacheFolder \yarn.cache 
yarn
yarn build

demigor avatar Sep 01 '23 01:09 demigor

The next step was to add some plugins (for example esbuild-plugin-less, esbuild-plugin-copy,esbuild-plugin-svgr), so we add one more file.

build.mjs (settings the same parameters)

import { build } from 'esbuild'

build({
  entryPoints: ['index.js'],
  bundle: true,
  minify: true,
  format: 'esm',
  sourcemap: true,
  splitting: true,
  outdir: 'dist',
  plugins: [],
  loader: {
    '.js': 'jsx',
  },
})

and add new script line in package.json

  "build2": "node ./build.mjs"

Run it:

D:\test-yarn>yarn build2   
node:internal/process/esm_loader:97
    internalBinding('errors').triggerUncaughtException(
                              ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'esbuild' imported from D:\test-yarn\build.mjs
Did you mean to import esbuild-npm-0.19.2-84addf679d/node_modules/esbuild/lib/main.js?
    at new NodeError (node:internal/errors:399:5)
    at packageResolve (node:internal/modules/esm/resolve:889:9)
    at moduleResolve (node:internal/modules/esm/resolve:938:20)
    at defaultResolve (node:internal/modules/esm/resolve:1153:11)
    at nextResolve (node:internal/modules/esm/loader:163:28)
    at ESMLoader.resolve (node:internal/modules/esm/loader:838:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:424:18)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:77:40)
    at link (node:internal/modules/esm/module_job:76:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

Node.js v18.16.1

The question is how to use esbuild API to enable plugins?

demigor avatar Sep 01 '23 01:09 demigor

yarn node currently does not work on es modules (.mjs). You have to write CJS to let yarn hack into the script.

hyrious avatar Sep 01 '23 01:09 hyrious

In fact it does. I have just found how.

yarn config set pnpEnableEsmLoader true

So now we can you esbuild script with yarn. Next step is to enable some plugins.

yarn add -D esbuild-plugin-less esbuild-plugin-copy esbuild-plugin-svgr
```

Now update the build.mjs. Adding following imports and updating plugins:

import { lessLoader } from 'esbuild-plugin-less' import { copy } from 'esbuild-plugin-copy' import svgr from 'esbuild-plugin-svgr'

... plugins: [lessLoader(), copy(), svgr()], ...


Problem again. This time 'less' could not be loaded. If I add 'less' in dev dependencies, then comes similar problem with another lib.

If I do not change the cacheFolder setting in Yarn (as per my second thread post), everything works as expected.

However this defeats the whole idea of not having node_modules under your project root (because now we have another folder called .yarn\cache under the same project root).

I have no idea, what component causes the issue - esbuild or yarn. The fact is Yarn PNP (for purpose of not having megabytes of node_modules) is not working as expected.

demigor avatar Sep 01 '23 04:09 demigor

For your initial problem, logLevel: 'verbose' would have given you some insight as to why Esbuild wasn't using PnP for resolving. I don't know why it required you to set an explicit cache, but perhaps that would reveal the reason.

Your later problem aren't related to Esbuild, so I'd tend to close this issue and let you open a new one on the Yarn tracker - but I encourage you to post a full repro, with the exact error messages you get.

arcanis avatar Sep 07 '23 07:09 arcanis

Here is another example with this kind of error.

{
  "name": "Bug,
  "packageManager": "[email protected]",
  "type": "module",
  "scripts": {
    "build": "esbuild index.js --bundle --outfile=test.js --platform=node --target=node20 --log-level=verbose"
  },
  "dependencies": {
    "@aws-sdk/client-secrets-manager": "^3.535.0",
    "@aws-sdk/rds-signer": "^3.535.0",
    "postgres": "^3.4.3"
  },
  "devDependencies": {
    "esbuild": "^0.20.2"
  }
}

yarn
yarn build

fails with

Could not resolve "@aws-sdk/credential-provider-node"

    .yarn/__virtual__/@aws-sdk-client-sts-virtual-1a1ba46154/6/.yarn/berry/cache/@aws-sdk-client-sts-npm-3.535.0-747ab576b1-10c0.zip/node_modules/@aws-sdk/client-sts/dist-cjs/credentialDefaultProvider.js:28:67:
      28 │     return () => Promise.resolve().then(() => __importStar(require("@aws-sdk/credential-provider-node"))).then(({ defaultProvider }) => defaultProvider(input)());
         ╵                                                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  The Yarn Plug'n'Play manifest says this package has a peer dependency on
  "@aws-sdk/credential-provider-node", but the package "@aws-sdk/credential-provider-node" has not
  been installed:

T3rm1 avatar Mar 18 '24 18:03 T3rm1