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

when use <script lang="tsx" setup> with template. HMR can not resolve import component using in template #22

Open
7 tasks done
we125182 opened this issue Jun 26, 2022 · 7 comments
Labels
feat: hmr p3-minor-bug 🔨 An edge case that only affects very specific usage (priority)

Comments

@we125182
Copy link

Describe the bug

after project run. replace App.vue<script>code with follows

<script setup lang="tsx">
import { Search } from '@element-plus/icons-vue'
// import { Apple } from '@element-plus/icons-vue'

import RenderComp from './components/RenderComp'

const label = () => (<div>test</div>)
</script>

<template>
  <RenderComp :label="label" />
  <Search />
  <!-- <Apple /> -->
</template>

warning
only after the project running, import new component using in template. the problem appears.

Reproduction

https://stackblitz.com/edit/vitejs-vite-qrc4zw?file=src/App.vue

System Info

System:
    OS: macOS 11.6.5
    CPU: (8) x64 Apple M1
    Memory: 31.31 MB / 16.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 14.17.6 - /usr/local/bin/node
    Yarn: 1.22.11 - /usr/local/bin/yarn
    npm: 6.14.15 - /usr/local/bin/npm
  Browsers:
    Chrome: 103.0.5060.53
    Firefox: 95.0
    Safari: 15.4
  npmPackages:
    @vitejs/plugin-vue: ^2.3.3 => 2.3.3 
    @vitejs/plugin-vue-jsx: ^1.3.10 => 1.3.10 
    vite: ^2.9.12 => 2.9.12

Used Package Manager

pnpm

Logs

No response

Validations

@we125182
Copy link
Author

video can see in issue vuejs/core#6171 (comment)

@sapphi-red sapphi-red added feat: hmr p3-minor-bug 🔨 An edge case that only affects very specific usage (priority) and removed pending triage labels Jun 27, 2022
@glitchboyl
Copy link

I found that the bug was caused by the Vite cache. I've tried if remove them and that can fixes the issue.
So i think that when it using <script setup> and the templates and scripts both has changed, it needs to re-cache.

If that solution is okay, I can try to pr it. 😄

@we125182
Copy link
Author

@glitchboyl the issue is only show while using<script setup lang="tsx">. <script setup>is ok. maybe it was vue-jsx

@glitchboyl
Copy link

@we125182 Yeah, thank you for your complement. While using <script setup>, it didn't generate the cache but generate resolved everytime, I need to dig in and figure it out why.

@Preyou
Copy link

Preyou commented Sep 7, 2022

这个问题目前有解决方案吗?

@we125182
Copy link
Author

we125182 commented Sep 17, 2022

@sapphi-red @patak-dev
it is similar with issue vitejs/vite#6568 and PR vitejs/vite#4563. the bug was caused by this line.
using <script setup lang="tsx"> in sfc file, while template code changed and affectedModules.has(mainModule) === false it will use prevDescriptor. because of this, script code changing was ignored.

// packages/plugin-vue/src/handleHotUpdate.ts
export async function handleHotUpdate(
  { file, modules, read, server }: HmrContext,
  options: ResolvedOptions
): Promise<ModuleNode[] | void> {
  ...
  const affectedModules = new Set<ModuleNode | undefined>()
  const mainModule = modules.find(
    (m) => !/type=/.test(m.url) || /type=script/.test(m.url)
  )
  const templateModule = modules.find((m) => /type=template/.test(m.url))

  if (hasScriptChanged(prevDescriptor, descriptor)) {
    let scriptModule: ModuleNode | undefined // TODO: this line should move out of block
    if (
      (descriptor.scriptSetup?.lang && !descriptor.scriptSetup.src) ||
      (descriptor.script?.lang && !descriptor.script.src)
    ) {
      const scriptModuleRE = new RegExp(
        `type=script.*&lang\.${
          descriptor.scriptSetup?.lang || descriptor.script?.lang
        }$`
      )
      scriptModule = modules.find((m) => scriptModuleRE.test(m.url))
    }
    affectedModules.add(scriptModule || mainModule)
  }

  if (!isEqualBlock(descriptor.template, prevDescriptor.template)) {
    // when a <script setup> component's template changes, it will need correct
    // binding metadata. However, when reloading the template alone the binding
    // metadata will not be available since the script part isn't loaded.
    // in this case, reuse the compiled script from previous descriptor.
    if (mainModule && !affectedModules.has(mainModule)) { // TODO: here should add condition: !affectedModules.has(scriptModule)
      setResolvedScript(
        descriptor,
        getResolvedScript(prevDescriptor, false)!,
        false
      )
    }
    affectedModules.add(templateModule)
    needRerender = true
  }

@patak-dev patak-dev transferred this issue from vitejs/vite Dec 3, 2022
@shendiid
Copy link

@sapphi-red @patak-dev it is similar with issue vitejs/vite#6568 and PR vitejs/vite#4563. the bug was caused by this line. using <script setup lang="tsx"> in sfc file, while template code changed and affectedModules.has(mainModule) === false it will use prevDescriptor. because of this, script code changing was ignored.

// packages/plugin-vue/src/handleHotUpdate.ts
export async function handleHotUpdate(
  { file, modules, read, server }: HmrContext,
  options: ResolvedOptions
): Promise<ModuleNode[] | void> {
  ...
  const affectedModules = new Set<ModuleNode | undefined>()
  const mainModule = modules.find(
    (m) => !/type=/.test(m.url) || /type=script/.test(m.url)
  )
  const templateModule = modules.find((m) => /type=template/.test(m.url))

  if (hasScriptChanged(prevDescriptor, descriptor)) {
    let scriptModule: ModuleNode | undefined // TODO: this line should move out of block
    if (
      (descriptor.scriptSetup?.lang && !descriptor.scriptSetup.src) ||
      (descriptor.script?.lang && !descriptor.script.src)
    ) {
      const scriptModuleRE = new RegExp(
        `type=script.*&lang\.${
          descriptor.scriptSetup?.lang || descriptor.script?.lang
        }$`
      )
      scriptModule = modules.find((m) => scriptModuleRE.test(m.url))
    }
    affectedModules.add(scriptModule || mainModule)
  }

  if (!isEqualBlock(descriptor.template, prevDescriptor.template)) {
    // when a <script setup> component's template changes, it will need correct
    // binding metadata. However, when reloading the template alone the binding
    // metadata will not be available since the script part isn't loaded.
    // in this case, reuse the compiled script from previous descriptor.
    if (mainModule && !affectedModules.has(mainModule)) { // TODO: here should add condition: !affectedModules.has(scriptModule)
      setResolvedScript(
        descriptor,
        getResolvedScript(prevDescriptor, false)!,
        false
      )
    }
    affectedModules.add(templateModule)
    needRerender = true
  }

Has it been resolved? Currently, there is still this problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat: hmr p3-minor-bug 🔨 An edge case that only affects very specific usage (priority)
Projects
None yet
Development

No branches or pull requests

5 participants