chrome-extension-tools icon indicating copy to clipboard operation
chrome-extension-tools copied to clipboard

fix(hmr): fix `tailwindcss` hmr does not work (vite)

Open molvqingtai opened this issue 2 years ago • 8 comments

FIxed: Fix the problem that tailwindcss jit did not trigger the hmr update Todo: Fix the problem that the index.css?inline syntax does not work in hmr

Fix: #600 #671 #609 #512

Tests to be added...

import index.css?inline still cannot implement HMR in contentScripts, because it is static data, but manually refreshing the page can already work, Do you have any good ideas?

At present(After merged this PR), there is only one compromise way to fully realize HMR:

createShadowRoot.ts

import { type ReactNode } from 'react'
import { createRoot, type Root } from 'react-dom/client'

export const createElement = <T extends Element>(template: string) => {
  return new Range().createContextualFragment(template).firstElementChild as unknown as T
}

export interface RootOptions {
  mode?: ShadowRootMode
  style?: string
  script?: string
  element?: Element
}

const createShadowRoot = (
  name: string,
  options: RootOptions
): Root & { shadowHost: Element; shadowRoot: ShadowRoot; appRoot: Element } => {
  const { mode = 'open', style = '', script = '', element = '' } = options ?? {}
  const shadowHost = createElement(`<${name}></${name}>`)
  const shadowRoot = shadowHost.attachShadow({ mode })
  const appRoot = createElement(`<div id="app"></div>`)
  const appStyle = style && createElement(`<style type="text/css">${style}</style>`)
  const appScript = script && createElement(`<script type="application/javascript">${script}</script>`)
  const reactRoot = createRoot(appRoot)

  shadowRoot.append(appStyle, appRoot, appScript, element)

  return {
    shadowHost,
    shadowRoot,
    appRoot,
    render: (children: ReactNode) => {
      document.body.appendChild(shadowHost)
      return reactRoot.render(children)
    },
    unmount: () => {
      reactRoot.unmount()
      shadowHost.remove()
    }
  }
}

export default createShadowRoot

content.tsx

import React from 'react'
import App from './App'
import createShadowRoot from './createShadowRoot'
import style from './index.css?inline'

void (async () => {
  const root = createShadowRoot(__NAME__, {
    style: __DEV__ ? '' : style,
    mode: __DEV__ ? 'open' : 'closed'
  })
  root.render(
    <React.StrictMode>
      <RemeshRoot store={store}>
        <App />
      </RemeshRoot>
    </React.StrictMode>
  )

  // HMR Hack
  // https://github.com/crxjs/chrome-extension-tools/issues/600
  if (__DEV__) {
    await import('./index.css')
    const styleElement = document.querySelector('[data-vite-dev-id]')!
    root.shadowRoot.insertBefore(styleElement, root.shadowRoot.firstChild)
  }
})()

If it is a development environment, add the out style in head to shadow dom If it is a production environment, write css string to shadow dom

molvqingtai avatar Jul 18 '23 21:07 molvqingtai

🦋 Changeset detected

Latest commit: 221dcbc003ba5986d5125c91395c1c9608f84ecb

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@crxjs/vite-plugin Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

changeset-bot[bot] avatar Jul 18 '23 21:07 changeset-bot[bot]

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
vite-plugin-docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jan 14, 2024 7:23pm

vercel[bot] avatar Jul 18 '23 21:07 vercel[bot]

It'd be so amazing to have this work!

flexchar avatar Aug 15 '23 14:08 flexchar

+1

gary-lo avatar Aug 18 '23 23:08 gary-lo

any updates here? this has been my blocker with vue :/

Joabesv avatar Oct 18 '23 03:10 Joabesv

Is it possible to have this merged? It is a blocker for my project as well.

NathanMLu avatar Nov 28 '23 15:11 NathanMLu

This would be good! :-)

sgcullen avatar Mar 27 '24 17:03 sgcullen