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

CLI bug: Error: ENOENT: no such file or directory, open 'out/perf.json' (when using --perf alongside --unpacker-output / --unminify-output) #85

Closed
0xdevalias opened this issue Dec 21, 2023 · 15 comments · Fixed by #90 or #101
Labels
bug Something isn't working scope: cli

Comments

@0xdevalias
Copy link

0xdevalias commented Dec 21, 2023

I got the error:

Error: ENOENT: no such file or directory, open 'out/perf.json'

When running the following command, on this code (Ref):

⇒ CHUNK_NAME="framework"; npx @wakaru/cli all unpacked/_next/static/chunks/${CHUNK_NAME}.js --unpacker-output stage2-unpacked/${CHUNK_NAME} --unminify-output stage3-unminified/${CHUNK_NAME} --perf

┌   Wakaru CLI v0.0.2
│
└  Selected features: Unpacker, Unminify

┌   Unpacker
│
◇  Unpacking...
│
◇  Finished
│
◆  Successfully generated 9 modules (4.51s)
│
└  Output directory: ./stage2-unpacked/framework

┌   Unminify
│
◇  Unminifying... (concurrency: 1)
│
◇  Finished
│
◆  Successfully unminified 9 files (2m21s)
│
└  Output directory: ./stage3-unminified/framework

..snip..

Error: ENOENT: no such file or directory, open 'out/perf.json'
    at Object.openSync (node:fs:592:3)
    at Object.writeFileSync (node:fs:2323:35)
    at Object.writeFileSync (/Users/devalias/.npm/_npx/adacf4dfcf214674/node_modules/jsonfile/index.js:78:13)
    at writePerfStats (/Users/devalias/.npm/_npx/adacf4dfcf214674/node_modules/@wakaru/cli/dist/cli.cjs:1676:21)
    at nonInteractive (/Users/devalias/.npm/_npx/adacf4dfcf214674/node_modules/@wakaru/cli/dist/cli.cjs:1653:7)
    at async Object.handler (/Users/devalias/.npm/_npx/adacf4dfcf214674/node_modules/@wakaru/cli/dist/cli.cjs:1301:5) {
  errno: -2,
  syscall: 'open',
  code: 'ENOENT',
  path: 'out/perf.json'
}
Full Output
⇒ CHUNK_NAME="framework"; npx @wakaru/cli all unpacked/_next/static/chunks/${CHUNK_NAME}.js --unpacker-output stage2-unpacked/${CHUNK_NAME} --unminify-output stage3-unminified/${CHUNK_NAME} --perf

┌   Wakaru CLI v0.0.2
│
└  Selected features: Unpacker, Unminify

┌   Unpacker
│
◇  Unpacking...
│
◇  Finished
│
◆  Successfully generated 9 modules (4.51s)
│
└  Output directory: ./stage2-unpacked/framework

┌   Unminify
│
◇  Unminifying... (concurrency: 1)
│
◇  Finished
│
◆  Successfully unminified 9 files (2m21s)
│
└  Output directory: ./stage3-unminified/framework


┌─────────┬────────────────────────────┬──────┐
│ (index) │            key             │ time │
├─────────┼────────────────────────────┼──────┤
│    0    │        'prettier-1'        │ 692  │
│    1    │         'prettier'         │ 725  │
│    2    │      'module-mapping'      │ 1971 │
│    3    │     'un-curly-braces'      │ 2702 │
│    4    │         'un-iife'          │ 2805 │
│    5    │  'un-assignment-merging'   │ 2880 │
│    6    │      'un-async-await'      │ 2961 │
│    7    │  'un-sequence-expression'  │ 3047 │
│    8    │       'un-infinity'        │ 3063 │
│    9    │   'un-variable-merging'    │ 3071 │
│   10    │        'un-return'         │ 3112 │
│   11    │        'un-boolean'        │ 3118 │
│   12    │   'un-template-literal'    │ 3153 │
│   13    │       'un-es6-class'       │ 3164 │
│   14    │     'un-esmodule-flag'     │ 3218 │
│   15    │          'un-jsx'          │ 3228 │
│   16    │      'un-use-strict'       │ 3326 │
│   17    │      'un-while-loop'       │ 3394 │
│   18    │       'un-undefined'       │ 3489 │
│   19    │   'un-type-constructor'    │ 3527 │
│   20    │         'un-enum'          │ 3529 │
│   21    │     'un-conditionals'      │ 3532 │
│   22    │  'un-nullish-coalescing'   │ 3645 │
│   23    │     'un-export-rename'     │ 3682 │
│   24    │        'un-typeof'         │ 3689 │
│   25    │   'un-builtin-prototype'   │ 3786 │
│   26    │   'un-bracket-notation'    │ 3889 │
│   27    │    'un-numeric-literal'    │ 3931 │
│   28    │       'smart-rename'       │ 3941 │
│   29    │   'un-optional-chaining'   │ 4200 │
│   30    │     'un-indirect-call'     │ 4226 │
│   31    │          'lebab'           │ 4235 │
│   32    │ 'un-sequence-expression-2' │ 4408 │
│   33    │   'un-flip-comparisons'    │ 4549 │
│   34    │ 'un-sequence-expression-1' │ 4666 │
│   35    │    'un-runtime-helper'     │ 5408 │
│   36    │          'un-esm'          │ 5475 │
│   37    │      'un-parameters'       │ 6522 │
│   38    │       'smart-inline'       │ 7163 │
└─────────┴────────────────────────────┴──────┘
Error: ENOENT: no such file or directory, open 'out/perf.json'
    at Object.openSync (node:fs:592:3)
    at Object.writeFileSync (node:fs:2323:35)
    at Object.writeFileSync (/Users/devalias/.npm/_npx/adacf4dfcf214674/node_modules/jsonfile/index.js:78:13)
    at writePerfStats (/Users/devalias/.npm/_npx/adacf4dfcf214674/node_modules/@wakaru/cli/dist/cli.cjs:1676:21)
    at nonInteractive (/Users/devalias/.npm/_npx/adacf4dfcf214674/node_modules/@wakaru/cli/dist/cli.cjs:1653:7)
    at async Object.handler (/Users/devalias/.npm/_npx/adacf4dfcf214674/node_modules/@wakaru/cli/dist/cli.cjs:1301:5) {
  errno: -2,
  syscall: 'open',
  code: 'ENOENT',
  path: 'out/perf.json'
}
@0xdevalias
Copy link
Author

When --perf is called, unminify (not unpack, see #84) will cause performance stats to be displayed (printPerfStats), and written to the output file (writePerfStats):

if (perf) {
printPerfStats(measurements)
writePerfStats(measurements, path.join(outputBase, 'perf.json'))
}

function writePerfStats(measurements: Measurement[], outputPath: string) {
fsa.writeJSONSync(outputPath, measurements.flat(), {
encoding: 'utf-8',
spaces: 2,
})
console.log()
console.log(`Performance statistics generated at ${c.green(getRelativePath(process.cwd(), outputPath))}`)
console.log()
}

It seems that writePerfStats is using path.join(outputBase, 'perf.json') for the output file.

outputBase defaults to ./out/:

const defaultOutputBase = './out/'

When --output is used, the default is overriden; but we could also use --unpacker-output / --unminify-output to change the output paths for those 2 steps, without causing the main output path to change:

const outputBase = _output ?? defaultOutputBase
const singleFeature = features.length === 1
const unpackerOutput = _unpackerOutput ?? (singleFeature ? outputBase : path.join(outputBase, defaultUnpackerOutputFolder))
const unminifyOutput = _unminifyOutput ?? (singleFeature ? outputBase : path.join(outputBase, defaultUnminifyOutputFolder))

I assume (haven't looked in the code) that under usual cases, unpack and unminify will create the folder of their output path if needed; but if we override both of those paths, then neither will be using the default output path.

In that case, if the ./out/ folder doesn't already exist, we will get the error shown above.

@0xdevalias
Copy link
Author

If the ./out/ directory already exists (or we make it, as a workaround to this bug), then we get the following message:

⇒ mkdir out

⇒ CHUNK="pages/_app"; npx @wakaru/cli all unpacked/_next/static/chunks/${CHUNK}.js --unpacker-output stage2-unpacked/${CHUNK} --unminify-output stage3-unminified/${CHUNK} --perf

┌   Wakaru CLI v0.0.2
│
■  Output directory already exists at ./out/. Pass --force to overwrite

@pionxzh pionxzh added bug Something isn't working scope: cli labels Dec 21, 2023
@pionxzh
Copy link
Owner

pionxzh commented Dec 28, 2023

Now the file should be generated under the overridden folder

@0xdevalias
Copy link
Author

Now the file should be generated under the overridden folder

@pionxzh Guessing that won't be true for the released version via npx until this is merged, right?

@pionxzh
Copy link
Owner

pionxzh commented Dec 30, 2023

Not yet released 🙏

@pionxzh
Copy link
Owner

pionxzh commented Dec 30, 2023

released

@pionxzh
Copy link
Owner

pionxzh commented Dec 30, 2023

wait, I forgot to modify both interactive and non interactive
Interative does not support overriding the path, so no issues.

@0xdevalias
Copy link
Author

0xdevalias commented Jan 2, 2024

released

@pionxzh Still seems to be an issue in 0.0.3?

⇒ CHUNK_NAME="framework"; npx @wakaru/cli all unpacked/_next/static/chunks/${CHUNK_NAME}.js --unpacker-output stage2XXX-unpacked/${CHUNK_NAME} --unminify-output stage3XXX-unminified/${CHUNK_NAME} --perf

┌   Wakaru CLI v0.0.3
│
└  Selected features: Unpacker, Unminify

┌   Unpacker
│
◇  Unpacking...
│
◇  Finished
│
◆  Successfully generated 9 modules (4.44s)
│
└  Output directory: ./stage2XXX-unpacked/framework

┌   Unminify
│
◇  Unminifying... (concurrency: 1)
│
◇  Finished
│
◆  Successfully unminified 9 files (2m16s)
│
└  Output directory: ./stage3XXX-unminified/framework


┌─────────┬────────────────────────────┬──────┐
│ (index) │            key             │ time │
├─────────┼────────────────────────────┼──────┤
│    0    │        'prettier-1'        │ 644  │
│    1    │         'prettier'         │ 700  │
│    2    │      'module-mapping'      │ 2261 │
│    3    │   'un-variable-merging'    │ 2596 │
│    4    │   'un-template-literal'    │ 2894 │
│    5    │        'un-boolean'        │ 2999 │
│    6    │  'un-sequence-expression'  │ 3024 │
│    7    │         'un-iife'          │ 3037 │
│    8    │   'un-type-constructor'    │ 3078 │
│    9    │    'un-numeric-literal'    │ 3084 │
│   10    │       'un-infinity'        │ 3111 │
│   11    │     'un-esmodule-flag'     │ 3136 │
│   12    │      'un-use-strict'       │ 3157 │
│   13    │  'un-assignment-merging'   │ 3191 │
│   14    │       'un-es6-class'       │ 3281 │
│   15    │          'un-jsx'          │ 3312 │
│   16    │       'un-undefined'       │ 3329 │
│   17    │   'un-bracket-notation'    │ 3416 │
│   18    │     'un-curly-braces'      │ 3434 │
│   19    │   'un-flip-comparisons'    │ 3437 │
│   20    │   'un-builtin-prototype'   │ 3559 │
│   21    │     'un-export-rename'     │ 3582 │
│   22    │         'un-enum'          │ 3629 │
│   23    │     'un-indirect-call'     │ 3629 │
│   24    │   'un-optional-chaining'   │ 3631 │
│   25    │     'un-conditionals'      │ 3652 │
│   26    │       'smart-rename'       │ 3672 │
│   27    │  'un-nullish-coalescing'   │ 3710 │
│   28    │      'un-async-await'      │ 3715 │
│   29    │        'un-typeof'         │ 3789 │
│   30    │ 'un-sequence-expression-1' │ 3794 │
│   31    │          'lebab'           │ 3820 │
│   32    │ 'un-sequence-expression-2' │ 3910 │
│   33    │        'un-return'         │ 4004 │
│   34    │      'un-while-loop'       │ 4139 │
│   35    │       'smart-inline'       │ 5291 │
│   36    │    'un-runtime-helper'     │ 5399 │
│   37    │          'un-esm'          │ 5519 │
│   38    │      'un-parameters'       │ 6761 │
└─────────┴────────────────────────────┴──────┘
Error: ENOENT: no such file or directory, open 'out/perf.json'
    at Object.openSync (node:fs:592:3)
    at Object.writeFileSync (node:fs:2323:35)
    at Object.writeFileSync (/Users/devalias/dev/0xdevalias/chatgpt-source-watch/node_modules/jsonfile/index.js:78:13)
    at writePerfStats (/Users/devalias/dev/0xdevalias/chatgpt-source-watch/node_modules/@wakaru/cli/dist/cli.cjs:2399:21)
    at nonInteractive (/Users/devalias/dev/0xdevalias/chatgpt-source-watch/node_modules/@wakaru/cli/dist/cli.cjs:2349:7)
    at async Object.handler (/Users/devalias/dev/0xdevalias/chatgpt-source-watch/node_modules/@wakaru/cli/dist/cli.cjs:2010:5) {
  errno: -2,
  syscall: 'open',
  code: 'ENOENT',
  path: 'out/perf.json'
}

@pionxzh
Copy link
Owner

pionxzh commented Jan 2, 2024

Yes, becasue it still need 14e8928 😢

@0xdevalias
Copy link
Author

Ah true, so should be in 0.0.4 when it's released then:

@0xdevalias
Copy link
Author

I'm still seeing this issue on CLI 0.0.5, is that expected?

Though still seeing the out/perf.json issue:

And there were a bunch of unminify errors that I will open a new issue for.


⇒ npm run-script wakaru:unminify-chunk pages/_app

> [email protected] wakaru:unminify-chunk
> f() { CHUNK="$1"; npx @wakaru/cli all unpacked/_next/static/chunks/${CHUNK}.js --unpacker-output stage2-unpacked/${CHUNK} --unminify-output stage3-unminified/${CHUNK} --perf; }; f pages/_app


┌   Wakaru CLI v0.0.5
│
└  Selected features: Unpacker, Unminify

┌   Unpacker
│
◇  Unpacking unpacked/_next/static/chunks/pages/_app.js
│
◇  Finished
│
◆  Successfully generated 1224 modules (3m2s)
│
└  Output directory: ./stage2-unpacked/pages/_app

┌   Unminify
│
◇  Unminifying... (concurrency: 1)
│
◒  ..Multiple exports of "default" found, only the last one will be kept
◐

..snip: many unminify errors here (will open a new issue for them)..

◇  Finished
│
◆  Successfully unminified 1224 files (19m44s)
│
└  Output directory: ./stage3-unminified/pages/_app


┌─────────┬──────────────────────────┬────────┐
│ (index) │           key            │  time  │
├─────────┼──────────────────────────┼────────┤
│    0    │     'un-while-loop'      │  2070  │
│    1    │  'un-flip-comparisons'   │  2079  │
│    2    │   'un-numeric-literal'   │  2160  │
│    3    │       'un-return'        │  2167  │
│    4    │  'un-bracket-notation'   │  2181  │
│    5    │       'un-boolean'       │  2203  │
│    6    │  'un-template-literal'   │  2220  │
│    7    │     'un-use-strict'      │  2287  │
│    8    │      'un-undefined'      │  2634  │
│    9    │  'un-variable-merging'   │  2823  │
│   10    │ 'un-assignment-merging'  │  2990  │
│   11    │     'module-mapping'     │  3587  │
│   12    │     'un-async-await'     │  4060  │
│   13    │        'un-iife'         │  4164  │
│   14    │       'un-typeof'        │  4247  │
│   15    │      'un-infinity'       │  4316  │
│   16    │    'un-esmodule-flag'    │  4557  │
│   17    │  'un-type-constructor'   │  6155  │
│   18    │    'un-conditionals'     │  6688  │
│   19    │        'un-enum'         │  6848  │
│   20    │      'un-es6-class'      │  8848  │
│   21    │    'un-export-rename'    │ 10312  │
│   22    │     'un-parameters'      │ 11368  │
│   23    │  'un-builtin-prototype'  │ 12446  │
│   24    │       'prettier-1'       │ 14311  │
│   25    │        'prettier'        │ 15642  │
│   26    │         'un-jsx'         │ 16243  │
│   27    │      'smart-inline'      │ 16392  │
│   28    │    'un-curly-braces'     │ 17804  │
│   29    │ 'un-nullish-coalescing'  │ 21042  │
│   30    │  'un-optional-chaining'  │ 21216  │
│   31    │      'smart-rename'      │ 26297  │
│   32    │   'jscodeshift-print'    │ 30003  │
│   33    │   'un-runtime-helper'    │ 70873  │
│   34    │ 'un-sequence-expression' │ 76342  │
│   35    │  'un-parameters-lebab'   │ 96794  │
│   36    │    'un-indirect-call'    │ 130591 │
│   37    │         'lebab'          │ 134495 │
│   38    │         'un-esm'         │ 141852 │
│   39    │        'unpacker'        │ 182051 │
│   40    │   'jscodeshift-parse'    │ 235709 │
└─────────┴──────────────────────────┴────────┘
Error: ENOENT: no such file or directory, open 'out/perf.json'
    at Object.openSync (node:fs:592:3)
    at Object.writeFileSync (node:fs:2323:35)
    at Object.writeFileSync (/Users/devalias/dev/0xdevalias/chatgpt-source-watch/node_modules/jsonfile/index.js:78:13)
    at writePerfStats (/Users/devalias/dev/0xdevalias/chatgpt-source-watch/node_modules/@wakaru/cli/dist/cli.cjs:2421:21)
    at nonInteractive (/Users/devalias/dev/0xdevalias/chatgpt-source-watch/node_modules/@wakaru/cli/dist/cli.cjs:2372:5)
    at async Object.handler (/Users/devalias/dev/0xdevalias/chatgpt-source-watch/node_modules/@wakaru/cli/dist/cli.cjs:2014:5) {
  errno: -2,
  syscall: 'open',
  code: 'ENOENT',
  path: 'out/perf.json'
}

Originally posted by @0xdevalias in #98 (comment)

@pionxzh
Copy link
Owner

pionxzh commented Jan 7, 2024

Sorry, the logic of these path things are too complex. Now I feel it's a little bit confusing. Where should I write the perf.json to if we actually have two output folders 🤔 Maybe the perf.json should be split by feature and put into their own folder.

@0xdevalias
Copy link
Author

0xdevalias commented Jan 7, 2024

If I hadn't specified a specific folder for it, I would have just expected it to output where I'm running my command from as perf.json (no folder prefix).

Perhaps you could add a new CLI arg that lets the perf.json output path be set directly as well, if there was a case someone needed to move it elsewhere.

I'm of 2 minds about splitting the file; I think generally if I was looking at performance I'd probably want it all in one. If I wanted to get performance for an individual part I would just trigger only that part (eg. Not using all, just calling unpack or unminify)


You could also potentially check if the unpack and unminify output paths have a common base and use that for the perf.json output. While that would work in my situation, it would be easy to create a situation where it doesn't/it did something weird/unexpected; so probably not a good choice.

Not sure if it's a limitation you would want to enforce, but you could potentially force them to have a common base as well; but it would reduce the flexibility of having the 2 args for it.


One last thought; while it doesn't necessarily solve the "where is the best place for perf.json to go when there are 2 output paths" part of things; the specific error here could be resolved by ensuring that the code that writes out perf.json is ensuring its folder/path exists first.

@pionxzh
Copy link
Owner

pionxzh commented Jan 9, 2024

Let's do the "common base" solution first. The worst case would be having cwd as the common base. I will open another feature request for supporting --perf-output

@0xdevalias
Copy link
Author

0xdevalias commented Jan 10, 2024

@pionxzh Sounds good :)

cwd being the worst case seems totally fine to me 👌🏻

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working scope: cli
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants