-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
useReducedMotion: Guard process usage #16679
Conversation
Bundler plugins like webpack `DefinePlugin` may work by replacing the complete `process.env.FORCE_REDUCED_MOTION`, which would make `typeof` checks fail. Use `process.env.FORCE_REDUCED_MOTION` directly in a try block to protect against errors.
// Prefer the try/catch to allow bundlers to replace `process.env.FORCE_REDUCED_MOTION` completely. | ||
// Checks like `typeof process === 'object' && …` will be safe, but may short-circuit if a bundler | ||
// has replaced `process.env.FORCE_REDUCED_MOTION` with `true`, but `window.process` | ||
// remains undefined. |
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.
That makes sense, but it also probably goes against the fact that bundlers try to also tree-shake these. For instance here, the try/catch might be kept (needs testing) while otherwise, the check is completely removed. Thoughts?
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.
A better approach may be to strip this entirely from the published package as I mentioned below, but I'm not sure.
Specifically on this point, here are my thoughts:
- Requiring package consumers to have a special build setup seems unreasonable, so unguarded
process.env.FORCE_REDUCED_MOTION
seems unreasonable. - Ideally, this would be determined at build time, replaced by a constant, and dead code elimination could remove parts of the code. That would require a construct like
if ( process.env.FORCE_REDUCED_MOTION ) { /* block could be dead-code eliminated */ }
. That doesn't seem possible given the previous point. - In order to provide safety for package consumers (guard the
process
usage) without requiring a special build setup, that would require something like:This seems to indicate that we can't have both safety and replacement with dead code elimination. Additionally, depending on the build setup, it's entirely possible to haveif ( typeof process === 'object' && // Check will remain at runtime process.env && // Check will remain at runtime process.env.FORCE_REDUCED_MOTION // Candidate for build-time replacement, may just be `true` or `false` ) { // Dead code elimination is very unlikely to occur here. }
process
beundefined
, butprocess.env.FORCE_REDUCED_MOTION
replaced withtrue
, which would make this snippet completely broken. - If we accept the above points, that seems to leave us with just the
try/catch
version. A consumer could opt-in to theFORCE_REDUCED_MOTION
, consumers don't need any specific build/bundle setup, and there's only a minimal bundle/runtime penalty of a few bytes of JavaScript and a try/catch check on module evaluation. This seems to be the only reasonable approach to me, unless we can completely remove this from the published package.
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 for the detailed explanation. That makes sense. The reason we have this env variable is that we want to disable animations in e2e tests. The ideal scenario would be to allow disabling animations at runtime. I didn't find a way to do it at that time.
Can you elaborate on this? We have full control over how it is bundled. In what real-world scenarios are you considering it otherwise be bundled? |
I ran into this in a real world scenario: Automattic/wp-calypso#34217 (comment) A package upgrade resulted in a broken build artifact with no build-time errors. The problem was fortuitously caught by e2e testing. The inclusion of unguarded React and others do rely on
While
I don't understand what you mean by this. Anyone consuming the I'm not sure what the original intentions of using |
To me, it's a point of setting expectations for the environments we're targeting with our published build artifacts. If our guarantee is that the To be clear, I'm not arguing against making a change for these packages to be easier to use, but I do think we should have a clear understanding about expectations of our target environments. Should we guard against |
My assumption has been that some packages are intended primarily for use in the browser and some are intended to be used in Node. #16227 highlights how many browser globals are used which are problematic in the Node context, such as for server side rendering.
Some packages are build/development tooling like
Portability and ease of use should drive the "why or why not" for all of these questions. If published packages use a subset of the language that is common to Node and the browser, it makes it easier to consume these packages. Globals that are not common to both environments should either be guarded or well documented and added only after careful consideration as these types of changes can cause hard to detect breakage because they depend on bundler configuration. |
Interesting read on how and why React uses |
Noting the pull request at #18453 would have removed this environment variable. As I understand, the work there is still desired but not achievable at the time. |
2all who faced this issue: suggested workaround is here -- https://github.com/Automattic/wp-calypso/pull/34217/files#r310732226 2wp team: guys, please try to find some solution for this. 1+ year passed since PR was created |
The code in question no longer exists. See #34132. I'm going to close the PR. |
Description
The
useReducedMotion
hook provided by@wordpress/compose
has unguarded usage of theprocess
global:gutenberg/packages/compose/src/hooks/use-reduced-motion/index.js
Line 19 in 6ef0222
process
is not a global variable in the browser. Depending on the way this code is bundled, it may work well at runtime, or it may error when theuseReducedMotion
module is evaluated.In
webpack
, this is is controlled by thenode
configuration option. If you attempt to bundle a project like the following:An error will be thrown at runtime when the script is evaluated:
How has this been tested?
Local testing by manipulating the installed module in a minimal test repo.
Types of changes
Bug fix - Unprotected
process
global usage could throw runtime errors when.Checklist: