plasmo icon indicating copy to clipboard operation
plasmo copied to clipboard

[EXP] Content Script UI with SPA

Open wong2 opened this issue 3 years ago • 7 comments

What is the example you wish to see?

I'd like to learn how to use Content Script UI with SPA pages. (They use history APIs to do client side routing). The naive solution seems only mount on page load, no mount happens after client side navigating.

Is there any context that might help us understand?

No response

Code of Conduct

  • [X] I agree to follow this project's Code of Conduct
  • [X] I checked the current issues for duplicate problems.

wong2 avatar Jul 28 '22 08:07 wong2

Interesting. Can you elaborate on the problem of SPA page navigating that causes the mount to be lost?

Note that getMountPoint can be an async function and you can make it await.

Also CSUI should still be mounted on the page imo, but might be invisible. Check the DOM tree

louisgv avatar Jul 28 '22 13:07 louisgv

I think async getMountPoint doesn't help here.

The problem is like this: I'm using getRootContainer to mount the CSUI to a DOM element in the webpage, it works well on the page load. Then I click some link in the page, which makes a client side routing to another page, so the previous mounted element did not exist anymore. What I need is some way to trigger the mounting logic again, after client side routing happened.

wong2 avatar Jul 28 '22 13:07 wong2

That's the key reason why it's easier to mount the shadowDOM outside in the body (using that default root container) than mounting it into a temp DOM element rendered by the SPA. Try using getMountPoint instead, you will find that the csui will not be removed upon SPA transition /Re-render.

You can certainly try to find some kind of indicator from the underlying site (an event or some sort) to re-root your csui, but I doubt unless the website Collab with you, it's very unlikely for there to be an indicator.

Another way you can try to re-root, is simply watch out when your component is unmounted, have it call a function that redo the root container mounting logic.

louisgv avatar Jul 28 '22 14:07 louisgv

Hi, I've tried getMountPoint, but I don't know how to make it work. The shadow DOM is there, but CSUI is not(because the element it mounted to have been removed. I have to be remounted again.

have it call a function that redo the root container mounting logic.

I don't see such an API exposed by plasmo?

wong2 avatar Jul 28 '22 14:07 wong2

Note that when using getMountPoint, you need to comment out getRootContainer (to use the default one)

I don't see such an API exposed by plasmo?

It'd be specialized to your use-case - the idea is you would re-implement the createRoot logic.

louisgv avatar Jul 28 '22 20:07 louisgv

Yeah, of course I removed getRootContainer entirely.

I think Plasmo could add some API to simplify the remount logic here.

wong2 avatar Jul 29 '22 02:07 wong2

Got it - I think we will think of an API for that. This is likely related to #22

louisgv avatar Jul 29 '22 15:07 louisgv

My case

  1. mount app in '/home'
  2. when user go to '/user',i use this code to inject into some element
render(
        createPortal(<GoodsImporter />, div),
         document.createElement("div")
       )

but now i can't listen when location was changed.

  • observer.observe(document.body, { childList: true }) no working some times
  • listen on popstate no working at all

is there any way to acheive this ?

xmsz avatar Sep 09 '22 04:09 xmsz

My case

  1. mount app in '/home'
  2. when user go to '/user',i use this code to inject into some element
render(
        createPortal(<GoodsImporter />, div),
         document.createElement("div")
       )

but now i can't listen when location was changed.

  • observer.observe(document.body, { childList: true }) no working some times
  • listen on popstate no working at all

is there any way to acheive this ?

Can you make a

My case

  1. mount app in '/home'
  2. when user go to '/user',i use this code to inject into some element
render(
        createPortal(<GoodsImporter />, div),
         document.createElement("div")
       )

but now i can't listen when location was changed.

  • observer.observe(document.body, { childList: true }) no working some times
  • listen on popstate no working at all

is there any way to acheive this ?

Try to watch for subtree and attribute. We just shipped a feature for that too which might help with injection on new component? - To watch for location change, it's likely on window.location

BTW, feel free to make a Q/A in Discussion, someone might be able to further help :)

louisgv avatar Sep 13 '22 22:09 louisgv