Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
While porting the CKEditor Widget to Drupal core in #2994696: Render embedded media items in CKEditor, I encountered this remaining @todo
:
* @todo Since previews use the downcasted representation, and `downcast()` relies 100% on `this.data`, and
* `_hashData()` knows which changes are immaterial, we should be able to cache preview responses.
We could:
- implement our own URL-based cache! Cool! But more code to maintain and test. 👎
- What if we'd instead rely on this pre-existing URL-based cache called the browser and allow it do its thing by switching to
GET
requests and ensuring the response has aCache-Control
header that allows for caching? That sounds lovely!But Drupal AJAX requests currently always use
POST
, notGET
. Which means the browser won't cache it. There's a Drupal core issue to make this happen: #956186: Allow AJAX to use GET requests. - We could force this today, but that seems risky (wrt security, maintainability) — the code to do so is simple:
+ previewLoaderAjax.options.type = 'GET'; + previewLoaderAjax.beforeSerialize = function () {};
- We could also just switch to plain (non-Drupal) AJAX GET requests, but then we effectively break BC for sites relying on Entity Embed's CKEditor Widget loading CSS + JS — see #2844822: The preview in CKEditor does not use the same Twig template as the one on the front end (default theme).
Comment | File | Size | Author |
---|---|---|---|
#7 | 3064340-7.patch | 7.89 KB | Wim Leers |
| |||
#7 | interdiff.txt | 2.17 KB | Wim Leers |
#6 | 3064340-4.patch | 7.45 KB | Wim Leers |
| |||
#6 | interdiff.txt | 4.85 KB | Wim Leers |
#6 | 3064340 after.mov | 3.46 MB | Wim Leers |
Comments
Comment #2
Wim LeersA few hours later, this happened: #2844822-25: The preview in CKEditor does not use the same Twig template as the one on the front end (default theme). In part spawned by this issue causing me to take another look at it 🤓 🥳
If that lands, then this can simply delete the
@todo
.Comment #3
Wim Leers#2844822: The preview in CKEditor does not use the same Twig template as the one on the front end (default theme) landed.
I've got an exciting new patch for y'all … thanks to #2844822-25: The preview in CKEditor does not use the same Twig template as the one on the front end (default theme) we know we don't need to use the AJAX system anymore (and we don't anymore as of #2844822 landing), we also have solid test coverage even before #2844822 but with #2844822-40: The preview in CKEditor does not use the same Twig template as the one on the front end (default theme) even more so, and in #2844822-41: The preview in CKEditor does not use the same Twig template as the one on the front end (default theme) I pointed out that we're now using nothing of the Drupal AJAX system anymore which opens the door to making the response cacheable…
So without further ado, here we go: a test asserting using the Resource Timing API (https://developer.mozilla.org/en-US/docs/Web/API/Resource_Timing_API) to verify that the browser is indeed caching the response and is hence resulting in a much improved UX. Of course, this will fail right now.
Comment #4
oknateNice test! Very exciting stuff.
Comment #6
Wim LeersSince #2844822: The preview in CKEditor does not use the same Twig template as the one on the front end (default theme), the Drupal AJAX response was merely a means of transportation; we were picking out the data for a single AJAX command, and were ignoring the
add_css
AJAX command for example if that existed. (Of course, prior to #2844822, that command was executed, but didn't have any effect on<iframe>
CKEditor instances: theadd_css
command operated in the main frame!So, since there's no point in sending that data, there's also no point in using a controller that returns AJAX responses that we then have to parse manually anyway. If we simplify that, we simultaneously gain the opportunity to cache the response on the client side, which we know is fine for Entity Embed responses, but we can't say that for sure about
\Drupal\embed\Controller\EmbedController::preview()
, which anything in contrib/custom code could be using for non publicly known things.Did all that, and in doing so, this yielded the UX improvement we all were hoping for:
(Those screencasts are with
usleep(500000);
in the controller, to simulate real-world less-than-ideal circumstances: response times of a little over half a second.)Comment #7
Wim LeersCleanup.
Comment #8
Wim LeersGiven this is 99% identical to
embed.preview
/\Drupal\embed\Controller\EmbedController::preview()
, I feel confident moving ahead with this. Even more so thanks to our test coverage :)Comment #9
Wim LeersTo thinking about users on high-latency connections! To better user experiences!
Comment #10
Wim Leers🚢
Comment #12
Wim Leers🤷♂️
Comment #13
oknateThat second video is really impressive. Nice work!
Comment #14
Wim Leers😊
Comment #16
Dave ReidThis seems to have a regression that no attached libraries or CSS/JS are included when the preview embedded entity is rendered?
Comment #17
maximpodorov CreditAttribution: maximpodorov commentedYes, and this is the major issue for embedded content which is just a wrapper filled by the data stored in drupalSettings. We have to be able to turn off this optimization.
Comment #18
maximpodorov CreditAttribution: maximpodorov commentedHere is the patch that reverts the commit.
Comment #19
maximpodorov CreditAttribution: maximpodorov commentedReverting the commit is not enough.
I have solved the problem of inability to preview JS-based media entities by invoking an additional AJAX request to /embed/preview/rich_text - the response is processed in the usual Drupal way.