Skip to content
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

CSS files are not loading in the site editor #42

Closed
adamziel opened this issue Oct 14, 2022 · 9 comments
Closed

CSS files are not loading in the site editor #42

adamziel opened this issue Oct 14, 2022 · 9 comments

Comments

@adamziel
Copy link
Collaborator

adamziel commented Oct 14, 2022

As in the title. Keep reading the thread below for more details.

@dd32
Copy link
Member

dd32 commented Oct 14, 2022

These files appear to be bypassing the ServiceWorker's fetch listener. The thing they all have in common is being triggered for fetch via react-dom

@adamziel
Copy link
Collaborator Author

The site editor is rendered in an iframe and all the requests bypassing the ServiceWorker originate in that iframe:

CleanShot 2022-10-14 at 11 11 36@2x

@adamziel
Copy link
Collaborator Author

adamziel commented Oct 14, 2022

That nested document seems to be rendered through a React portal:

https://github.com/WordPress/gutenberg/blob/a84db76d51617ed3e3a518ce8ffeb0ad038b13b1/packages/block-editor/src/components/iframe/index.js#L319-L370

Its source is:

> $0.contentWindow.location.href
'about:srcdoc'

It doesn't show up in ServiceWorker's clients.matchAll() and therefore isn't a controlled frame:

CleanShot 2022-10-14 at 11 24 59@2x

@adamziel
Copy link
Collaborator Author

It's a known bug in Chrome.

The intended behavior is an about:srcdoc iframe should inherit the ServiceWorker from the parent document – see the discussion in the ServiceWorker repo. That's what Firefox does – see the related issue. I don't know about other browsers.

We can't re-route the static asset requests in the ServiceWorker, but we can do it on the server. We only need to remove the WordPress instance scope from the URL like this:

Before:

/scope:0.8798659149475636/wp-includes/css/dist/block-editor/style.min.css?ver=6.0.1

After:

/wp-includes/css/dist/block-editor/style.min.css?ver=6.0.1

This repo could ship a .htaccess file in dist-web for the Apache users out there, and then provide some documentation to explain the problem.

The iframe also sends a request to load-styles.php and this can't be resolved by simple URL rewriting. Fingers crossed #43 will make that request go away entirely.

adamziel added a commit that referenced this issue Oct 14, 2022
Related to #42

This commit implements the URL rewrite with:

* A liveServer middleware for local dev
* A .htaccess file for apache production setups

Documenting this behavior in a visible place will be critical for mass
adoption of this project.

Nested iframes with src="about:srcdoc" are not controlled by the
parent's frame ServiceWorker. This is a bug in Chrome and potentially
other Chromium-based browser.

This is problematic because WordPress site editor is rendered in one
such iframe and it loads a bunch of stylesheets using a link tag like:

    <link rel="stylesheet" href="/scope:<scope>/<URL>" />

The /scope:<scope>/ part of the URL does not actually exist on the
server – it's a WordPress instance scope introduced to make WASM
WordPress usable in multiple browser tabs. Learn more at #31

The point is – these stylesheet requests bypass the ServiceWorker and
are actually sent to the server where they get a 404 response. This
effectively breaks the site editor.

We cannot re-route these requests in a ServiceWorker, but we can do it
on the server. That's what this commit is.

Unfortunately this commit won't solve the problem in setups based on nginx
and other server software – let's follow it up with a documentation
update.
@adamziel adamziel changed the title Some CSS files are not loading in the site editor CSS files are not loading in the site editor Oct 14, 2022
@adamziel
Copy link
Collaborator Author

adamziel commented Oct 14, 2022

Workaround introduced in 5f03281. This behavior still need to be documented.

adamziel added a commit that referenced this issue Oct 14, 2022
Related to #42

This commit implements the URL rewrite with:

* A liveServer middleware for local dev
* A .htaccess file for apache production setups

Documenting this behavior in a visible place will be critical for mass
adoption of this project.

Nested iframes with src="about:srcdoc" are not controlled by the
parent's frame ServiceWorker. This is a bug in Chrome and potentially
other Chromium-based browser.

This is problematic because WordPress site editor is rendered in one
such iframe and it loads a bunch of stylesheets using a link tag like:

    <link rel="stylesheet" href="/scope:<scope>/<URL>" />

The /scope:<scope>/ part of the URL does not actually exist on the
server – it's a WordPress instance scope introduced to make WASM
WordPress usable in multiple browser tabs. Learn more at #31

The point is – these stylesheet requests bypass the ServiceWorker and
are actually sent to the server where they get a 404 response. This
effectively breaks the site editor.

We cannot re-route these requests in a ServiceWorker, but we can do it
on the server. That's what this commit is.

Unfortunately this commit won't solve the problem in setups based on nginx
and other server software – let's follow it up with a documentation
update.
@adamziel adamziel changed the title CSS files are not loading in the site editor [Browser] CSS files are not loading in the site editor Oct 14, 2022
@dd32
Copy link
Member

dd32 commented Oct 17, 2022

There's another option here - Make WordPress not output scoped URLs for static resources in the first place.. bypassing the need for the serviceworker to handle it.

This can probably be done through the filters for site_url simply have any links to wp-(content|includes) or wp-admin/*.(css|js) return the scopeless URL..

Perhaps easier though, would be to use the script_loader_src filter which should be able to be used to return scope-less URLs. That probably won't handle the wp-content/* urls to theme assets though.

@adamziel adamziel changed the title [Browser] CSS files are not loading in the site editor CSS files are not loading in the site editor Oct 22, 2022
@adamziel
Copy link
Collaborator Author

Make WordPress not output scoped URLs for static resources in the first place.. bypassing the need for the serviceworker to handle it.

Great idea! It should help with most URLs. I don't think serviceworker can be bypassed completely, though, because all the uploads like media files or plugins needs to be served from Wasm's MEMFS. That being said, filtering as you proposed would at least reduce the number of requests routed through the serviceworker.

@adamziel
Copy link
Collaborator Author

adamziel commented Dec 2, 2022

It's a known bug in Chrome.

The intended behavior is an about:srcdoc iframe should inherit the ServiceWorker from the parent document – see the discussion in the ServiceWorker repo. That's what Firefox does – see the related issue. I don't know about other browsers.

@ellatrix explained me that srcDoc was used to force the iframe to use the standards mode and not the quirks mode. I patched the site editor with src: "/doctype.html" and a doctype.html file containing just <!doctype html> and it worked beautifully.

I committed the short-term for this repo in b7ca737. In the longer term, that fix should be merged directly to Gutenberg.

The original server-side fix can was reverted in 5f03281.

The only thing left to do here is to open a Gutenberg PR to remove the srcDoc usage in core.

adamziel added a commit that referenced this issue Dec 2, 2022
The site editor was initiating network requests that weren't routed
through the service worker. That's a known bug in Chrome, Firefox, and a
few other browsers based on these two. The issue is only with the
iframes using srcDoc and src="about:blank" as they fail to inherit the
root site's service worker.

Gutenberg loads the site editor using <iframe srcDoc="<!doctype html">
to force the standards mode and not the quirks mode:

WordPress/gutenberg#38855

This commit patches the site editor to achieve the same result via
<iframe src="/doctype.html"> and a doctype.html file containing just
`<!doctype html>`. This allows the iframe to inherit the service worker
and correctly load all the css, js, fonts, images, and other assets.

Ideally this issue would be fixed directly in Gutenberg and the patch
below would be removed.

See #42 for more details
@adamziel
Copy link
Collaborator Author

adamziel commented Jan 4, 2023

Let's track the Gutenberg PR in #91.

@adamziel adamziel closed this as completed Jan 4, 2023
Pookie717 added a commit to Pookie717/wordpress-playground that referenced this issue Oct 1, 2023
Related to WordPress/wordpress-playground#42

This commit implements the URL rewrite with:

* A liveServer middleware for local dev
* A .htaccess file for apache production setups

Documenting this behavior in a visible place will be critical for mass
adoption of this project.

Nested iframes with src="about:srcdoc" are not controlled by the
parent's frame ServiceWorker. This is a bug in Chrome and potentially
other Chromium-based browser.

This is problematic because WordPress site editor is rendered in one
such iframe and it loads a bunch of stylesheets using a link tag like:

    <link rel="stylesheet" href="/scope:<scope>/<URL>" />

The /scope:<scope>/ part of the URL does not actually exist on the
server – it's a WordPress instance scope introduced to make WASM
WordPress usable in multiple browser tabs. Learn more at WordPress/wordpress-playground#31

The point is – these stylesheet requests bypass the ServiceWorker and
are actually sent to the server where they get a 404 response. This
effectively breaks the site editor.

We cannot re-route these requests in a ServiceWorker, but we can do it
on the server. That's what this commit is.

Unfortunately this commit won't solve the problem in setups based on nginx
and other server software – let's follow it up with a documentation
update.
Pookie717 added a commit to Pookie717/wordpress-playground that referenced this issue Oct 1, 2023
The site editor was initiating network requests that weren't routed
through the service worker. That's a known bug in Chrome, Firefox, and a
few other browsers based on these two. The issue is only with the
iframes using srcDoc and src="about:blank" as they fail to inherit the
root site's service worker.

Gutenberg loads the site editor using <iframe srcDoc="<!doctype html">
to force the standards mode and not the quirks mode:

WordPress/gutenberg#38855

This commit patches the site editor to achieve the same result via
<iframe src="/doctype.html"> and a doctype.html file containing just
`<!doctype html>`. This allows the iframe to inherit the service worker
and correctly load all the css, js, fonts, images, and other assets.

Ideally this issue would be fixed directly in Gutenberg and the patch
below would be removed.

See WordPress/wordpress-playground#42 for more details
adamziel added a commit that referenced this issue Oct 9, 2023
…ce worker (#668)

## What is this PR doing?

Patches the block editor to use a special ControlledIframe component
instead of a regular HTML "iframe" element. The goal is to make the
iframe use a plain HTTP URL instead of srcDoc, blob URL and other
variations.

Normally, the patch applied here would be a huge maintenance burden over
time. However, @ellatrix explores fixing the issue upstream [in the
Gutenberg
repo](#646).
Once her PR is merged, the patch here will only be needed for a known
and limited set of WordPress and Gutenberg versions and will not require
ongoing reconciliation with new WP/GB releases.

Fixes #646

## What problem is it solving?

In Playground, the editor iframe needs to be controlled by Playground's
service worker so it can serve CSS and other static assets. Otherwise
all the requests originating in that iframe will yield 404s.

However, different WordPress versions use a variety of iframe techniques
that result in a non-controlled iframe:

* 6.3 uses a binary blob URL and the frame isn't controlled by a service
worker
* <= 6.2 uses srcdoc had a null origin and the frame isn't controlled by
a service worker
* Other dynamic techniques, such as using a data URL, also fail to
produce a controlled iframe

HTTP URL src like src="/doc.html" seems to be the only way to create a
controlled iframe.

And so, this commit ensures that the block editor iframe uses a plain
HTTP URL regardless of the WordPress version.

Once WordPress/gutenberg#55152 lands, this will
just work in WordPress 6.4 and new Gutenberg releases.

## Testing Instructions

Run `npm run dev`

Then, confirm the inserter is nicely styled and there are no CSS-related
404s in the network tools.

Test the following editors:

* Post editor
http://localhost:5400/website-server/?url=/wp-admin/post-new.php
* Site editor
http://localhost:5400/website-server/?url=/wp-admin/site-editor.php
* For all supported WordPress versions
* With and without the Gutenberg plugin (`&plugin=gutenberg`)


## Related

* https://bugs.chromium.org/p/chromium/issues/detail?id=880768
* https://bugzilla.mozilla.org/show_bug.cgi?id=1293277
* w3c/ServiceWorker#765
* #42
* b7ca737
adamziel added a commit that referenced this issue Oct 10, 2023
…ce worker (#668)

## What is this PR doing?

Patches the block editor to use a special ControlledIframe component
instead of a regular HTML "iframe" element. The goal is to make the
iframe use a plain HTTP URL instead of srcDoc, blob URL and other
variations.

Normally, the patch applied here would be a huge maintenance burden over
time. However, @ellatrix explores fixing the issue upstream [in the
Gutenberg
repo](#646).
Once her PR is merged, the patch here will only be needed for a known
and limited set of WordPress and Gutenberg versions and will not require
ongoing reconciliation with new WP/GB releases.

Fixes #646

## What problem is it solving?

In Playground, the editor iframe needs to be controlled by Playground's
service worker so it can serve CSS and other static assets. Otherwise
all the requests originating in that iframe will yield 404s.

However, different WordPress versions use a variety of iframe techniques
that result in a non-controlled iframe:

* 6.3 uses a binary blob URL and the frame isn't controlled by a service
worker
* <= 6.2 uses srcdoc had a null origin and the frame isn't controlled by
a service worker
* Other dynamic techniques, such as using a data URL, also fail to
produce a controlled iframe

HTTP URL src like src="/doc.html" seems to be the only way to create a
controlled iframe.

And so, this commit ensures that the block editor iframe uses a plain
HTTP URL regardless of the WordPress version.

Once WordPress/gutenberg#55152 lands, this will
just work in WordPress 6.4 and new Gutenberg releases.

## Testing Instructions

Run `npm run dev`

Then, confirm the inserter is nicely styled and there are no CSS-related
404s in the network tools.

Test the following editors:

* Post editor
http://localhost:5400/website-server/?url=/wp-admin/post-new.php
* Site editor
http://localhost:5400/website-server/?url=/wp-admin/site-editor.php
* For all supported WordPress versions
* With and without the Gutenberg plugin (`&plugin=gutenberg`)


## Related

* https://bugs.chromium.org/p/chromium/issues/detail?id=880768
* https://bugzilla.mozilla.org/show_bug.cgi?id=1293277
* w3c/ServiceWorker#765
* #42
* b7ca737
adamziel added a commit that referenced this issue Jan 13, 2024
As discussed in #42,
the Gutenberg plugin needs to be patched to ensure the editor iframe is
controlled by the service worker.

The previous patching approach was to patch the Gutenberg plugin in the
`install-plugin` step. This worked for the `install-plugin` step, but not for
the `import-site` step, because the Gutenberg plugin is already installed when
importing a site. That was fixed in another PR, but it's still not enough.

Turns out, there's a whole lot of ways to install the Gutenberg plugin:

* Install plugin step
* Import a site
* Install Gutenberg from the plugin directory
* Upload a Gutenberg zip

Since it's too difficult to patch Gutenberg in all these cases, this
commit blanket-patches all the scripts requested over the network whose
names seem to indicate they're related to the Gutenberg plugin.
adamziel added a commit that referenced this issue Jan 15, 2024
…940)

As discussed in
#42,
the Gutenberg plugin needs to be patched to ensure the editor iframe is
controlled by the service worker.

The previous patching approach was to patch the Gutenberg plugin in the
`install-plugin` step. This worked for the `install-plugin` step, but
not for
the `import-site` step, because the Gutenberg plugin is already
installed when
importing a site. That was fixed in another PR, but it's still not
enough.

Turns out, there's a whole lot of ways to install the Gutenberg plugin:

* Install plugin step
* Import a site
* Install Gutenberg from the plugin directory
* Upload a Gutenberg zip

Since it's too difficult to patch Gutenberg in all these cases, this
commit blanket-patches all the scripts requested over the network whose
names seem to indicate they're related to the Gutenberg plugin.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants