-
-
Notifications
You must be signed in to change notification settings - Fork 1.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
feature: improved logging #1607
Conversation
…d catches syntax errors that alpine does not report in a meaningful way. When debug mode is enabled console errors will include the element where the error was thrown. Can be enabled using: Alpine.enableDebugMode();
You can find a benchmark of execution time differences from If you would like to try this in your own application here is what we did to measure execution time: <script>
window.alpineLoadTime = 0;
document.addEventListener( "alpine:init", () => {
window.alpineLoadTime = (new Date()).getTime();
} );
document.addEventListener( "alpine:initialized", () => {
window.alpineLoadTime = (new Date()).getTime() - window.alpineLoadTime;
console.log("Alpine Loading Took:" + window.alpineLoadTime );
} );
</script> |
|
Please don't merge this. I did some more testing tonight and I think there is better way to do this that won't require the
and it seemed like it was getting hoisted to global scope. The event strategy works because that constructor is evaluated immediately and because it's on different scope, removing the event listener always works (but adding/removing all those event listeners might be expensive).
I think we might have been mistaken so we'll play with this Friday and likely simplify this and tidy tests up. |
Thanks for looking into this. |
@calebporzio what was wrong with the approach we had in v2 of throwing the error and in some cases attaching additional information to it? That didn't require a way to enabled/disable the "debug mode" |
I'm not sure about this, surely we can try/catch or From prior research, if some of the code that is throwing is inside a Promise chain or async function you'll need to handle both "error" and "unhandledrejection", see https://github.com/alpine-collective/alpinejs-devtools/blob/master/packages/shell-chrome/src/backend.js#L108-L120 For reference these are the PRs that added support in v2 (this is probably not relevant to anyone else, but whatever we end up with it would be useful that the solution that ends up being implemented can support displaying errors in the devtools alpine-collective/alpinejs-devtools#247) |
Thanks @HugoDF, we were working under some false assumptions with initial implementation but we have mostly working cleaner version without need for debug mode garbage. We are just trying to sort out side effects but I suspect we'll have working branch for review by 5pm EST |
Sure thing It would be ideal if the implementation was 1-1 with Alpine v2 in terms of adding details to the errors + using |
Okay, sorry we come from react world with dev mode using console.error so we didn't put much thought into it but we'll switch to console.warn |
@HugoDF - nothing was wrong with it. I liked it - I'm not fully tracking what this PR uniquely offers anyways. I'm down for a PR to make it work like V2 |
This is what we're implementing, it should work same/better than V2 and be compatible with devtools (alpine-collective/alpinejs-devtools#247). We're just trying to handle some edge cases right now where V3 bombs in new tests. Likely V2 would've bombed too but we're getting closer. |
…ught with previous iteration
@HugoDF We have updated this, can you confirm this is compatible with devtools? |
@JacobPozaic I'll test it out and let you know but the code looks like it should be compatible 👍 |
I added test to confirm empty error on init is caught/logged correctly related to this (#1652) Note: x-init should probably short circuit itself before evaluation tho |
# Conflicts: # packages/alpinejs/src/directives/x-data.js
Fixed merge conflicts |
This is ready for review or feedback. I've been using this build for a few days of development and it's been solid and useful. There are a few ways to make the tests more sophisticated like attaching error listener and asserting element and expression got added but I'm not sure it's needed? |
packages/alpinejs/src/evaluator.js
Outdated
try { | ||
return new AsyncFunction(['__self', 'scope'], `with (scope) { __self.result = ${rightSideSafeExpression} }; __self.finished = true; return __self.result;`) | ||
} catch ( error ) { | ||
handleError( error, el, expression, false ) |
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.
What's the reason for this swallowing the error?
if the error in x-data
is not thrown Devtools won't pick it up
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.
In those cases I think it was causing crazy down the line side effects as well that were essentially bogus errors because future lifecycle stuff like injecting magics depended on defined data. That's based on my foggy memory since it was last week but I'll know more once I test it a bit more again.
@danddanddand the way this was dealt with in v2 was to intercept all errors and re-throw them out of band using setTimeout, see:
https://github.com/alpinejs/alpine/blob/2.x/src/index.js#L94-L98
Okay we will try 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.
Made a change that should address this now
@danddanddand @JacobPozaic I've tried it out with devtools and it looks like errors during |
@HugoDF I'm a little foggy on it now, but I'm going to get together with @JacobPozaic shortly to go over it. I think it was related to trying to handle test below having multiple errors be displayed and the way javascript interpreter was evaluating it. Seemed to hoist the replaceItems reference error out of the try/catch so there was no longer opportunity to intercept it and append el/expression. I'll dig into it again with him and see how throwing error is handled in those cases. I think we just came to conclusion since we couldn't actually stop evaluation on that one and we know expression is invalid, safer to continue with safe expression and because syntax error was hoisted it was in console anyway (just not with el/expression). In those cases I think it was causing crazy down the line side effects as well that were essentially bogus errors because future lifecycle stuff like injecting magics depended on defined data. That's based on my foggy memory since it was last week but I'll know more once I test it a bit more again.
|
@danddanddand the way this was dealt with in v2 was to re-throw errors out of band using setTimeout, see: Lines 94 to 98 in ffba225
|
I'm getting an interesting issue with a broken Chrome stack trace
Firefox stack trace
|
@HugoDF I think I'm going to try going back to strategy of having the safeAsyncFunction return a valid result every time because in trying to use this version, it's not as good of a dev experience with errors like yours above. There are more down stream side effects that just a result of having func that is a ticking time bomb like in your examples. I'll play with it some more today. Our tests are proving that exceptions that get through have el/expression added and console warning is there with element/expression. We just have to be more careful about swallowing the exception. If you'd like to discuss or peer program with us just chat me on discord. |
Yeah maybe We could dispatch |
Any update on this? Mainly looking for @HugoDF to approve of this PR. I think he originally implemented the handling in V2 so I'd like for his stamp of approval before going any further. Thanks |
I have not looked at it in a while but I’ve used this branch a lot for development because it was only way to find needle in the haystack errors (if you have a lot of Alpine components on the page and get unexpected error). I’ll bring it up to date tomorrow at work and review it again. My main issue with branch is the way evaluations were being evaluated asynchronously I don’t like catching and re-throwing error as in many cases it lead to down the stream errors. I think it would work better if evaluation wasn’t async but I’m guessing you have reasons for it. I’d personally prefer to return empty object and not throw the error (just log it and dispatch event like @HugoDF suggested). That also seemed to be strategy of petite vue which was done after this branch (see last line of https://github.com/vuejs/petite-vue/blob/main/src/eval.ts). They aren’t doing async evaluation so less balls in air. Anyway, I’ll update branch with @JacobPozaic this week and likely recommend @HugoDF reviews again for merge. If you have any thoughts on above might help us. |
Great, thanks @danddanddand |
An alternative implementation @danddanddand and I prefer is here: #1904 Can you please review @HugoDF |
That PR looks reasonable approach wise I'll see what it'll take to make devtools display the right info |
Closed, other PR is preferable. #1904 |
Debug mode improves console errors and catches syntax errors that alpine does not report in a meaningful way. When debug mode is enabled console errors will include the element where the error was thrown.This is an expensive operation because Syntax Errors can only be detected through events on the window, additionally logging elements to the console is expensive. Because of this, by default debug mode is disabled similar to React__DEV__
not being enabled for prod builds.With this feature a variety of common development issues can be resolved faster using browsers development tools to locate broken elements and diagnose issues previously hard decipher from Alpine's original error logs.Can be enabled by calling theAlpine.enableDebugMode()
beforeAlpine.start()
is called.Primarily this will help with debugging the following types of issues:
Here is a codepen example of the feature: https://codepen.io/jacobpozaic/pen/XWMLEmpHere is a codepen example of the feature ( new iteration ) : https://codepen.io/jacobpozaic/pen/eYvqwbg
More examples in tests
Update: