-
-
Notifications
You must be signed in to change notification settings - Fork 601
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
refactor(webpack-cli): don't spawn needless shells and replace execa with cross-spawn #3146
Conversation
|
||
try { | ||
await execa(commandToBeRun, [], { stdio: "inherit", shell: true }); | ||
sync(packageManager, commandArguments, { stdio: "inherit" }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't understand why this is the only spot where sync
was not used and shell
was set to true
. Could be that it was a way to make passing all the arguments in a single string work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good questions, maybe it was just mistake
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With execa
wee need shell: true
for running npm
commands.
npm
is not a binary but a shell file.npm
requires usingcmd.exe
orBash
to be loaded. The shell option does that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there also a reason the shell must run async? Intuitively it does not seem the case, as there is no way the program can continue if the install does not finish.
It's true that npm is a bash script on Unix and a cmd file on Windows.
But later on the comment you've linked adds
If you specify a shell file (as opposed to a binary), on Windows, and do not use the shell option, Execa emulates that option for you (through the dependency node-cross-spawn) by basically running cmd /d /s /c /q "npm run tsc" instead of npm run tsc
I think that must be true, because f the shell option is required, the previous execa
calls, all without shell: true
would fail and I think someone would have reported the bug. I think the shell: true
is really needed if you want the shell to expand or replace something in the command string.
@@ -275,6 +268,10 @@ class WebpackCLI implements IWebpackCLI { | |||
}); | |||
}; | |||
|
|||
// yarn uses 'add' command, rest npm and pnpm both use 'install' | |||
const commandArguments = [packageManager === "yarn" ? "add" : "install", "-D", packageName]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can re-use the argument array if we keep it separate instead of concatenating immediately into a single string.
I should have fixed the failing install tests now. I hope all tests pass on CI because I can't fix one test that's always failed for me locally (even on master).
The string does contain the substring so I have little idea of what's wrong. |
The smoketests all pass on my machine, so I can't say why they fail now. They also passed on the previous CI run. |
Can you try to update lock file? |
I've updated all versions in |
Oh, looks like we should update types when we updating lock file |
ad239b5
to
e9ca015
Compare
I think it's the opposite, updating |
hm, we have a problems with:
That is weird... |
I think the problem is webpack-cli/smoketests/helpers.js Line 45 in 80ae4a2
but it's set to 30 seconds, which should be plenty (on my machine each tests runs in a second or so). |
Can we try to increase timeout? Sorry for this, don't have time on deep investigation for this |
Remove 9 dependencies on a production install: - execa - get-stream - human-signals - is-stream - mimic-fn - npm-run-path - onetime - signal-exit - strip-final-newline
Execute install command synchronously instead of spawning a shell asynchronously. - The requested action cannot proceed until the required install completes, so I don't see an advantage to an asynchronous process - Starting the subprocess directly should be more performant. It should also be more cross-plattform and secure, since it prevents interpolations and expansions.
Mock the `sync` property. Split command into command name and argument array.
70b1721
to
db9c10c
Compare
I've increased the timeout to 60 seconds. |
Codecov Report
@@ Coverage Diff @@
## master #3146 +/- ##
==========================================
- Coverage 91.50% 91.44% -0.06%
==========================================
Files 23 23
Lines 1719 1719
Branches 519 519
==========================================
- Hits 1573 1572 -1
- Misses 146 147 +1
Continue to review full report at Codecov.
|
Maybe we need increase some more |
I'm not sure, that timeout only affects the smoketests but now it's the other tests hanging. Anyway, this time the smoketests passed in less than 1 min on Ubuntu, I think either the containers are too slow or there is some deadlock issue. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/cc @webpack/cli-team Let's review
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks
What kind of change does this PR introduce?
Refactor: use a simple child process instead of a shell and replace
execa
withcross-spawn
.Did you add tests for your changes?
No, I only replaced the
execa
mocks withcross-spawn
mocks, as the functionality should be identical as before.I've tested
webpack init
on my local machine.Summary
Executing a shell is less performant, less secure and less cross-platform, according to both the execa and cross-spawn documentation.
Replacing
execa
withcross-spawn
removes 9 dependencies on a production install:I can't find any options unique to execa in the codebase and cross-spawn should take care of the Windows compatibility issues.
Does this PR introduce a breaking change?
No.
Other information
execa uses
cross-spawn
under the hood to parse the command arguments, so nothing should change in that regard: https://github.com/sindresorhus/execa/blob/main/index.js