-
Notifications
You must be signed in to change notification settings - Fork 12k
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
Optimization with esbuild breaks the code since 12.2.0 #21654
Comments
Can you cause this issue without any custom builders present (or |
@clydin yes, the same issue can be reproduced without the
|
The same thing described here happened to the angular-oauth2-oidc library. It was resolved by swapping out the sha256 implementation: manfredsteyer/angular-oauth2-oidc#1120 I hope this is at least somewhat useful information, that this bug is not isolated to one project. |
@LeonEck By any chance did you try the opposite, (i.e., disabling terser and only running esbuild)? |
@micschro can you look into this, tomorrow, please? |
@clydin I just tried this out with the latest angular version and the previous angular-oauth2-oidc library to force the broken build. I commented out the optimizeWithTerser call and returned the esbuildResult.code in the end. With that, the build is still broken in the same way. It still reuses a variable name that it shouldn't. Setting @yGuy You can go into |
@LeonEck Thank you for helping to diagnose the issue. Would it be possible for you to try out an additional change? If so, can you keep |
@clydin Here are the results:
Let me know if there is anything else that I should test. |
@clydin we ran our build again with I'm not sure why disabling We ran the builds with these angular versions today:
|
@micschro I am also confused why disabling buildOptimizer all of a sudden fixes the build. I remember this not being the case when I originally tested it two weeks ago (at that time I had to disable both buildOptimizer and optimization). Since this whole error only surfaces when exact conditions are met, and even slight changes to the input code toggle between the error appearing or disappearing, this could be a red herring. |
I just came across this, and I'm the developer of esbuild. It looks like this is a bug in esbuild, likely having to do with the use of return function($) {
function foo(arg) {
return arg + $;
}
// "eval" prevents "$" from being renamed
// Repeated "$" puts "$" at the top of the character frequency histogram
return eval(foo($$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$))
}(2); and the command return function($) {
function foo($) {
return $ + $;
}
return eval(foo($$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$));
}(2); The problem is that the use of Note that use of direct |
Thanks @evanw for taking a look at this, much appreciated 😀 |
@evanw Thank you for the help and insight. I was trying to narrow down a minimal reproduction using the |
The newly-released esbuild version 0.12.24 should fix this issue. |
One my application got broken and seems like this was causing it because it failing in prod and local working where optimization is off. This version should be marked as broken, as there this will break lots of applications and developers will break their head unnecessary as this is a very complicated issue to capture. |
I just tested it by forcing esbuild to version 0.12.24 and that produces working builds! |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
🐞 Bug report
Command (mark with an
x
)Is this a regression?
Yes, the previous version in which this bug was not present was: ~12.1.0Description
Our application started to break in what we found literally hundreds of places in the source code when we (accidentally) switched to ~12.2.0(in fact this happened on a project without a package lock file, that used
~12.0.5
for all angular dependencies, but @angular-builders/custom-webpack internally uses^12.0.0
which resulted in yarn installing12.2
of @angular-devkit/build-angular which is the first version using esbuild - side note: so be careful if you use yarn and builders/custom-webpack without a lock file as it will not honor the version ranges!)What happens since version 12.2.0 is that during final optimization/minification esbuild often renames variables that are used locally with names that are already defined in an outer scope and which are still accessed from within the local to the outer scope. This almost always invalidates all references to the outer scope resulting in code that immediately breaks at runtime.
esbuild tries to use names for variables that are used most frequently, but for some reasons it does not always seem to check whether these names don't clash with other variable usages in the same scope.
The code that breaks has the following structure (not exactly this code):
(this is a kind of a function declaration that uses external dependencies and the other dependencies are injected via the $ parameter in the outer scope. Then these dependencies are used in functions that will later get "exported".)
In the original code, before minification indeed the outer
$
is already named$
, but the innervar $
is something else in the original code - similar to this:And of course, in the optimized code
new $.ClassName()
does not work, because$
is undefined at that point because of the variable (re-)declaration.We have identified literally dozens of cases in our code where the code is broken after being optimized by the 12.2.0 build. It seems it assigns a new name to local variables, without properly checking whether they are already used in the scope.
Another (part of an) example for a minified, obviously broken code:
(again
$
is being accessed/used before its initialized)and we also have code where due to hoisting a
var $ = something
resulted in previous usages of$
in the same scope also yieldingundefined
errors.Similar to this:
🔬 Minimal Reproduction
That's the problem. We have not been able to strip down the code to reasonable size, yet. This seems to happen with larger code bases, only, so far. If we remove parts of the code before and after the broken parts, sometimes the error does not show (because a different, non-clashing variable renaming happens). We have not been able so far to reduce the code to below a few thousand lines of code.
We hope that someone who knows more about esbuild or the integration with the angular build has some idea what might be going so terribly wrong here. We manually forced esbuild to the newest available release (0.12.23 instead of the currently used 0.12.17), but the problem remained. Disabling
optimization
or switching to versions before 12.2.0 immediately fixes the problem.I am aware that this bug might get closed because it is not easily reproducible, and I will continue to find a smaller repro, but at the moment the repro contains commercially licensed code and thus cannot be easily published.
You can reproduce the "not at all minimized use-case" by downloading the trial of yFiles for HTML, building the angular CLI example (check the README for details) with angular >=12.2.0 in "production mode" and the app will immediately break on startup with errors similar to the ones above. Looking through the generated code, there are dozens, maybe hundreds of broken/wrong variable renamings. With <12.2.0 everything works as expected.
🌍 Your Environment
See above. The below combination breaks and we found that the very last (at the time of writing) 12.1.x release works, whereas 12.2.0 breaks.
Anything else relevant?
Any input that might help us in reducing this to a smaller repro would be greatly appreciated. E.g. could we reduce this to just the esbuild step so that bisecting does not always take minutes for each step? Is there an easy way to tweak the esbuild configuration?
The text was updated successfully, but these errors were encountered: