Closed bramus closed 3 years ago
For reference, in case it helps with a decision on the issue.
The reason for the leaf demo not working after the code switch is that it internally the leaf demo is building a URL blob and calling window.CSS.paintWorklet.addModule
with the blob.
https://unpkg.com/houdini-leaf@1.0.6/houdini-leaf.js
const worklet = `
...
class LeafPainter {}
registerPaint('leaf', LeafPainter);
...
`;
const workletBlob = URL.createObjectURL(new Blob([worklet], { type: 'application/javascript' }));
window.CSS.paintWorklet.addModule(workletBlob);
It appears the reason for the design is so the end user can just include a script tag to load the worklet rather than call the worklet API:
https://www.npmjs.com/package/houdini-leaf
<script src="https://unpkg.com/houdini-leaf"></script>
I did some testing locally with both css-houdin-voronoi
and houdini-leaf
and found I could get them both working (and all other demos) using the proposed pull request and pointing the Leaf demo from the build version to the worklet version:
File: https://github.com/GoogleChromeLabs/houdini.how/blob/main/worklets/houdini-leaf.json
Before: "cdnUrl": "https://unpkg.com/houdini-leaf",
After: "cdnUrl": "https://unpkg.com/houdini-leaf@1.0.6/worklet.js",
The build script for houdini-leaf
is here:
https://github.com/zhenyanghua/houdini/blob/master/leaf/build.mjs
Additionally I tried this on the original coded script.type = 'module'
but that broke both demos.
@ConradSollitt Upon inspecting the houdini-leaf
package and your information I've updated this PR so that the leaf worklet itself will be loaded from https://unpkg.com/houdini-leaf/worklet.js
Hi, thanks for this PR! Would it be possible to include all dependancies in the file? For example, how iamvdo's conic gradient worklet "injects" the TinyColor library?
Hi Una,
All dependencies for css-houdini-voronoi
are included in its file, similar to how iamvdo's conic-gradient script does it: they are simply inlined. Therefore his code is also affected by the bug this PR fixes: when loading his paint worklet, you'll get back a "Uncaught ReferenceError: ConicalGradient is not defined" — a message similar to the one seen in css-houdini-voronoi
.
You can test this yourself by including this worklet JSON definition:
{
"workletName": "conic-gradient",
"packageName": "conic-gradient",
"cdnUrl": "https://codepen.io/bramus/pen/3545348be3100ddc57bb4716cfaa8d52.js",
"tags": ["paint"],
"usage": {
"background": "paint(conic-gradient)"
},
"customProps": {
},
"author": {
"name": "Vincent De Oliveira",
"url": "https://twitter.com/iamvdo",
"image": "/assets/images/iamvdo.jpg"
}
}
(Note: I'm using a slightly altered version of his worklet here hosted on CodePen. The changed version includes a check for window being undefined or not + a fallback to default colors to use)
The problem is that only the worklet class from his paint.js
gets loaded. All the rest of his code — e.g. the dependencies — gets stripped due to the loading mechanism currently in use. You can see this in this screenshot from DevTools: only the registerPaint call is there, all the rest is gone.
👉 This PR fixes this behavior, making sure the whole code from the worklet is added as a module, by using a simple CSS.paintWorklet.addModule(url)
.
When including the JSON above with the branch from this PR, iamvdo's script (and my css-houdini-voronoi
along with that) work as expected 🎉
Hi all!
One suggestion I have: it would be good to retain the old behavior under a property (like cdnUrlType:'script'
) on each Worklet's configuration. This would allow worklets available only as main-thread JS with addModule(blob)
to still be used. The default can definitely be to load these URLs via addModule()
- the script loading code I had in here was very much a hack.
I would suggest something like:
[
{
"workletName": "conic-gradient",
"packageName": "conic-gradient",
# // This URL is assumed to be a Paint Worklet module. It gets loaded via CSS.paintWorklet.addModule():
! "cdnUrl": "https://codepen.io/bramus/pen/3545348be3100ddc57bb4716cfaa8d52.js",
"tags": ["paint"] // etc
},
{
"workletName": "other",
"packageName": "other",
+ // If this is set to "script", the URL will be loaded via <script src> on the main thread:
+ "cdnUrlType": "script",
! "cdnUrl": "https://unpkg.com/foo-worklet/index.js",
# // ^ this file is one that would be calling CSS.registerProperty()/CSS.paintWorklet.addModule()
"tags": ["paint"] // etc
}
]
Also: with the above in place, this stuff should be safe to remove.
@developit That would allow one to fix it indeed. If I interpret correct, the default would then be "worklet"
as a value for cdnUrlType
?
@bramus yup, exactly!
@developit I've adjusted this PR to reflect your proposed changes:
cdnUrlType
, defaulting to "worklet"CSS.paintWorklet.addModule
cdnUrlType
to "script"Awesome, thanks all :) I like this solution!
I'm currently trying to add
css-houdin-voronoi
to the list of demo worklets (see this separate branch). While the addition of the JSON is straightforward, I am however greeted with an"Uncaught ReferenceError: Voronoi is not defined"
error.I took me some time to figure out but found that this is caused by the way how worklets are loaded, in combination with how
css-houdini-voronoi
is structured.registerPaint
(normally fromoCSS.paintWorklet
), this method is being manually implemented in thewindow
scope: https://github.com/GoogleChromeLabs/houdini.how/blob/main/public/index.js#L19css-houdini-voronoi
uses an extra library which the painter uses. This extra function/class is placed adjacent to theregisterPaint
call found inside theworklet.js
file.As here on houdini.how the
window.registerPaint
is being called from within the script loadedworklet.js
, and thatregisterPaint
callingCSS.paintWorklet.addModule()
with only the painter, the painter no longer has access to the extra library whichcss-houdini-voronoi
requires.This PR fixes that behavior by simply loading the paint worklets using
CSS.paintWorklet.addModule
. As that's also a promise, nothing else in the logic of theDemo
component needs to change.⚠️ However, if merging this PR would be considered: I've noticed the leaf demo breaks on this change. It spits out aFixed with an extra commit."Uncaught ReferenceError: CSS is not defined"
. That's because that worklet checks forregisterPaint
being available inCSS
before calling it. I don't think this is customary for a worklet to do so? Furthermore that demo callswindow.CSS.paintWorklet.addModule(workletBlob);
itself, which also doesn't seem customary. All other paint worklet demos — including thecss-houdin-voronoi
one which I want to add — work fine.