alpine-collective / alpinejs-devtools Goto Github PK
View Code? Open in Web Editor NEWChrome/Firefox DevTools extension for debugging Alpine.js applications.
License: MIT License
Chrome/Firefox DevTools extension for debugging Alpine.js applications.
License: MIT License
Each time I open and close the inspector / devtools, the DOM is being re-evaluated and is quite slow to interact.
Might be worth looking into another approach for watching and tracking Alpine components.
Formatting is inconsistent across files.
I think we can get some smaller bundle / extension sizes by switching to a pure Rollup bundler or Microbundle.
@Te7a-Houdini @ryangjchandler are we happy pushing an update out now?
The changelog is here:
I can submit a PR that bumps the versions & send it off to Firefox to review.
Similar to the $0
of chrome and $vm
of vue, it would be very productive to have this for alpine
maybe $a
Thank you all for the great work.
When I edit a value that's a number, I expect a number value to be set (currently being set to the string representation of the number)
PS. I'm creating this issue after fixing it mainly for accountability purposes eg. tracking which release it's a part of
When I scroll down the Alpine.js in devtool The background will be black. Of course I user black themed devtools.
After I refreshed it, the components and the data can't selectable.
I need to refresh the page, after I need to refresh Alpine.js devtool to work again it.
But the theme is again failed with the black background:
Maybe this problem is same that #1
I use the Firefox Add-on on Firefox Nightly. The alpinejs presence on the page is properly detected in the popup icon, but the components and data panes in the dev tools are empty.
The extension works on the Invoice Generator, but does not work on the Alpine Toolbox. Those sites are from alpinejs examples.
Tests introduced as part of #37 got removed, since then we've re-evaluated our testing strategy #81
We need to add some Cypress tests to deal with:
Scenarios ported from the original issue (should be easier to test now that we've got a backend.js + panel environment):
Notes:
data-testid
's, there are already some in the panel.html
When I'm editing a data property:
This seems to have a script to release to Firefox/Chrome: https://github.com/single-spa/single-spa-inspector#publishing-a-new-version
Uses https://www.npmjs.com/package/@wext/shipit under the hood. That package brings in a lot of dependencies, we might be better off lifting and shifting https://github.com/LinusU/wext-shipit/blob/master/lib/chrome.js and https://github.com/LinusU/wext-shipit/blob/master/lib/firefox.js
Would be ideal to have an action that:
shipit
's to Firefox/ChromeNotes:
{9abd6c79-c126-42cc-bacc-658d531864f1}
Resources:
Potential alternatives:
Alpine.js "latest" version is hardcoded to "2.7.3", see https://github.com/alpine-collective/alpinejs-devtools/blob/master/packages/shell-chrome/src/state.js#L10
Couple of options to improve this
require('./package.json').devDependencies.alpinejs
(we'll need to strip the semver range), or load a clean version from package-lock
, require('./package-lock.json').dependencies.alpinejs.version
https://registry.npmjs.org/alpinejs
, get the ['dist-tags'].latest
field, sample request + extraction: curl https://registry.npmjs.org/alpinejs | jq ".[\"dist-tags\"].latest"
Key question to answer is:
__version__
)? or at runtime/extension startup (we would probably prefer the npm registry fetch approach in this case)?Note: this is probably not super high priority, Alpine release cadence isn't very high.
Update:
We should fetch the version from https://registry.npmjs.org/alpinejs
, if that fails fall back to a version injected from the package-lock.json.
We need to update the way we compare versions, instead of latest === version
we should do isLaterSemverVersion(latest, version)
(semver would checks that major, minor and patch are greater than or equal to latest).
When an "outdated" version is detected, the "Alpine version" text should be a link to https://github.com/alpinejs/alpine/releases
You can't set a value to false
. I think it thinks we mean the string "false"
and evaluates it as true.
Follow-up from #78, #80 we've fixed the x-data="{ el: $el }"
case. We also detect functions and replace their values with 'function'
.
However we get the same error in the following case: x-data="{ els: [$el], elObj: { el: $el, fn: function() {} } }"
since we only do a top-level value detection pass.
Update: as part of #101 #102 nested elements/elements in arrays are considered "unserializable", ideally only the key that can't be serialized should be marked as such.
Note: having started a WIP branch, doing this within the current setup might be relatively complicated particularly in flattenData
I'm not a big fan of the 'Alpine.js is ready' heading at the top of the dev tools. If anything, it's wasted space.
I'm suggesting we move everything up and add a cleaner title bar to the top that would maybe output the Alpine version if we can find it (maybe using the script src) along with other information like the number of components, etc.
When updating a user's component data on panel data edit, it would be ideal to update a single field directly instead of replacing the x-data
attribute, could be something like the following & remove the 3-step "read data, create new data with updated value, inject updated data"
set(component.__x.$data, attributeSequence, attributeValue)
if (attributeSequence.includes('.')) {
component.__x.updateElements(component) // force re-render on Array/Object update?
}
Code to replace in backend.js: component.__x.$el.setAttribute('x-data', JSON.stringify(data))
Original discussion #80 (comment)_
Would be good to have some editing tests/check performance before/after.
We should upgrade to Tailwind v2, note that there are some changes to how purge works and also to some classes https://tailwindcss.com/docs/upgrading-to-v2.
We should also look at whether or not Tailwind UI classes are used and remove the npm package if it's not used. If it is used, we'll need to upgrade as well to match Tailwind v2.
This is again inspired by Vue.js Devtool's "events" tab, obviously Alpine.js doesn't use synthetic events or emit events to communicate between components.
Instead we should register a top-level listener for events being dispatched with $dispatch
(which we can detect) eg. we can read @click="$dispatch('my-custom-event')
which means we should listen to 'my-custom-event'
at the top-level (using document.addEventListener) and then report their contents in a tab.
Any thoughts/ideas limitations you can think of @ryangjchandler @Te7a-Houdini ?
We probably want a new panel for this.
With Alpine latest we can overwrite $dispatch
and instrument it (see #48 (comment)):
It turns out that it's possible to overwrite a magic property ๐ , so we can inject some code that will replace
$dispatch
and send debug info on call ๐
https://codepen.io/hugodf/pen/xxOvqpg
Note on this: we should check that the suggested $dispatch
function override works the same as regular Alpine one, one thing that might be different is which element dispatchEvent is being called on
Overwriting $dispatch
doesn't behave the same as Alpine implementation see https://codepen.io/hugodf/pen/GRjKgNO?editors=1111 the overriden $event.target
is not correct (it's the root of the component, not the element from which $dispatch
is called).
A way to get this to work is to monkey-patch dispatchEvent
with something like this:
const _dispatchEvent = EventTarget.prototype.dispatchEvent;
EventTarget.prototype.dispatchEvent = function(...args) {
// send a message to devtools
// `this` is the element from which `$dispatch` is called
// `args[0]` is the event name, `args[1]` is the options (including `options.detail`)
console.log(this, args);
return _dispatchEvent.apply(this, args);
}
This has the advantage of not being Alpine.js specific (eg. if custom events are sent from vanilla JS) + not locking us into a minimum Alpine version.
When opening the devtools for the first time there's a flash of unstyled content.
It's probably something we can deal with with x-cloak
+ a "Loading..." message that gets hidden on Alpine.js bootstrap.
cc @stephenoldham might have an idea of how to tackle this.
I've found https://github.com/single-spa/single-spa-inspector which has a simpler approach than we've currently got with regards to webpage -> devtools messaging.
Specifically:
Current Alpine.js devtools implementation is based on Vue devtools (https://github.com/vuejs/vue-devtools), which has a few layers of abstraction that we don't have at the moment, React devtools also have a similar approach (with a "bridge" concept, see https://github.com/facebook/react/tree/master/packages/react-devtools-extensions).
Finding other devtools implementations that plug straight into the chrome extension system would be useful to simplify the approach and reduce the risk of bugs relating to interactions with the browser/devtools.
Feedback on submission of 0.0.1
to Firefox Add-ons Gallery was that a longer description + some action screenshots would likely be beneficial to the listing.
When faced with an "Unserializable Value", we should point the user to create a Discussion/Issue and/or explain to them what "Unserializable Value" means.
Follow-on from #101
Current UI
We probably want an (i)
icon, a tooltip and/or a link to create a new discussion.
Example tooltip: https://codepen.io/t7team/pen/XWdyVyB
I implemented this in my extension so I'm happy to make the PR for it. Same thing that Vue does with their devtools.
Sometimes I have many sort of "throw away" components that don't really need to show in DevTools. If you're not opposed to adding more optional attributes, we could add an x-ignore
and have DevTools ignore those components all together.
Currently the CSS is being output as part of the JS "panel" bundle, this isn't good for performance (the CSS needs to be parsed as JS, injected as CSS and parsed as CSS).
Let's try to use Tailwind CLI or a rollup plugin to output the CSS to a styles.css file.
While we're looking into this, it might be useful to enable purging of the styles on production builds.
When a component has elements covering the background-color change, the hover state obviously can't be seen. Probably worth pivoting to an overlay element added to the page and removed again on hover end.
Tests for the panel.html
Alpine.js app were added in #38 but with the UI redesign I removed them ๐ #60
I wonder if there's a way to write E2E tests for a Chrome/Firefox extension, unit testin each of the files doesn't really test much and will break with simple refactors (eg. moving mapping of data from the sender to the receiver of the message).
Vue Devtools have a Cypress + "shell-dev" setup, but we might not be able to do the same (they've got an abstraction over the Devtools APIs)
when there's too many components and clicking on the last component you will have to scroll up again to see this component data .so the intended behavior is something similar to vue js dev tools . is that components and data are two separate things
Caught by @Te7a-Houdini
Referencing the $el in another object attribute will cause a bug when the devtool stringifies the object.
var component = function() {
return(
{
msg: 'Hello Alpine.js',
init() {
this.div = this.$el
}
}
)
}
See this page here with the console opened: https://cdpn.io/pomartel/debug/abmbyNg/xJAjOeOZonJk
The Codepen source here: https://codepen.io/pomartel/pen/abmbyNg
When an Alpine.js component is detected inside of a LiveView view, use view.name
as the name of the component.
Alpine.js uses console.warn
in the following scenarios:
template
https://github.com/alpinejs/alpine/blob/ee019cbc66d2adb3e5126bf3822d9d701a40daf8/src/utils.js#L29template
with more than 1 child node https://github.com/alpinejs/alpine/blob/ee019cbc66d2adb3e5126bf3822d9d701a40daf8/src/utils.js#L31I believe some developers suppress console.warn
, it would be nice to surface the relevant errors/warnings:
For 1. and 2. we should probably re-scan the DOM and to figure out which are the offending Moved to a separate issue to have additional structural checks #141template
's.
For 3. the console.warn
contains the element as well as the expression.
os: macOs
browser: chrome
When components are added or removed on page with AJAX, the devtools node list is not updated accordingly. Closing and reopening the devtools does refresh and update the list.
From @KevinBatdorf
Could we easily extract the panel.html file into separate files to manage it a little better? What would you suggest?
What we need is some sort of templating system that allows partials, maybe nunjucks, https://edge.adonisjs.com/ (which has a blade-like syntax so I assume we could do partials) or even a bunch of JS files with template strings that contain the HTML
We would need to mess around with the build setup in order to do that, probably by pre-processing the HTML. Would likely also involve removing HTML from rollup copy step and running the templating instead.
Not a major one obviously but I think it's nice to have the process automated where possible to reduce friction.
I'm thinking run tests, build and publish on a release / tag. Should be possible, haven't looked into it yet though.
Approach that seems likely to work to add some tests for the frontend part of the app:
panel.html
file without letting panel.js run (it uses browser extension APIs), ie. strip out the script tagalpineState
instance (window.alpineState = ...
)__alpineDevtool.port.postMessage
components
data into alpineState
& get everything to re-render (might need to call Alpine.start()
)Tests should at least contain all the bug/regression fixes that have been completed/are in progress:
Other valuable tests (sanity checks):
Progress:
jest
+ @testing-library/dom
is the best option to test an Alpine app since that's what Alpine.js itself uses #38"Circular structure" error when dealing with jQuery
Thanks for taking care of this guys. It almost works except when I wrap my
$el in a jquery object like this $ ($el). Sorry if I'm doing funny things with my Alpine setup! ๐
I wonder if it's going to be possible to manage all the weird situations like this one. Maybe just wrap it in a try catch and display it as an "Unknown Element"?
Originally posted by @pomartel in #78 (comment)
We can add a check that each field's value is serializable and label it as unserializable if not.
I'll create an "enhancement" piece to add some UI that points the user to create an issue/discussion on the devtools repo when they see that so that we can decide if it's something we want to handle, eg. we might want to unfurl jQuery but not worry about a ton of other generic bugs #103
Thanks for putting this together.
Any idea how difficult it would be to port the extension to Firefox?
I'm happy to contribute something along those lines.
Hey guys, thanks for developing this tool! Would be great to see the name of the Livewire component in the tree if the x-data is attached to the component root. Created a pull request with an initial implementation ๐๐ผ
related #1 but different
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.