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

fix: hmr doesn't work when modifying the code of jsx in sfc #4563

Merged
merged 2 commits into from Sep 1, 2021

Conversation

y1d7ng
Copy link
Contributor

@y1d7ng y1d7ng commented Aug 10, 2021

Description

fix #3008
When modifying the jsx code in the sfc file or modifying the code in the jsx file through script import, hmr does not work.

<script lang="jsx">
import { defineComponent } from "vue";

export default defineComponent({
  render() {
    return <div>change it</div>
  },
});
</script>

or change code in test.jsx.

<script src="./test.jsx"></script>

Additional context

The case of <script src="./test.jsx"></script>:

When the jsx file is imported through src in the .vue, the jsx file will be processed by plugin-vue-jsx to add hot related code.

code += `\nimport.meta.hot.accept(({${hotComponents

The importAnalysis plugin will make the isSelfAccepting of the jsx module true.

So when modifying the code in the jsx file, only a request will be sent to get the updated jsx file. Because the __hmrId of the instance corresponding to .vue is descriptor.id:
output.push(`_sfc_main.__hmrId = ${JSON.stringify(descriptor.id)}`)

and the __hmrId of jsx is newly generated and different, so the instance cannot be re-rendered only by loading jsx.
`\n${local}.__hmrId = "${id}"` +

The solution of this pr is to make the jsx file requested in the .vue have no hot related code, the isSelfAccepting of the module is false, so that when the jsx code is changed, the .vue file will be requested again.

The case of <script lang="jsx">:

But the jsx code used by <script lang='jsx'> will request a file of .vue?vue&type=script&lang.jsx, and the file's module will be excluded by the handleHotUpdate of plugin-vue.

affectedModules.add(mainModule)

In this way, the corresponding module will not be processed by invalidate and add lastHMRTimestamp .
invalidate(mod, timestamp, invalidatedModules)

Because there is no query parameter t in the jsx import in .vue file, after obtaining the .vue file, the jsx file will not be requested again
url = injectQuery(url, `t=${depModule.lastHMRTimestamp}`)

The solution of this pr is to filter out the module corresponding to jsx file in the handleHotUpdate method of plugin-vue.


What is the purpose of this pull request?

  • Bug fix
  • New Feature
  • Documentation update
  • Other

Before submitting the PR, please make sure you do the following

  • Read the Contributing Guidelines.
  • Read the Pull Request Guidelines and follow the Commit Convention.
  • Check that there isn't already a PR that solves the problem the same way to avoid creating a duplicate.
  • Provide a description in this PR that addresses what the PR is solving, or reference the issue that it solves (e.g. fixes #123).
  • Ideally, include relevant tests that fail without this PR but pass with it.

@patak-dev patak-dev added the p3-minor-bug An edge case that only affects very specific usage (priority) label Aug 25, 2021
@@ -46,7 +46,14 @@ export async function handleHotUpdate({
!isEqualBlock(descriptor.script, prevDescriptor.script) ||
!isEqualBlock(descriptor.scriptSetup, prevDescriptor.scriptSetup)
) {
affectedModules.add(mainModule)
let scriptModule
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

floating variables should be defined with a typedef

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your review, I will change it.

@@ -46,7 +46,14 @@ export async function handleHotUpdate({
!isEqualBlock(descriptor.script, prevDescriptor.script) ||
!isEqualBlock(descriptor.scriptSetup, prevDescriptor.scriptSetup)
) {
affectedModules.add(mainModule)
let scriptModule: ModuleNode | undefined
if (descriptor.script?.lang && !descriptor.script.src) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this is not necessary to fix the case once vue-plugin-jsx stops generating HMR code when detecting it's inside a SFC script block?

Is it correct that this is added only to handle the case where user or other plugins use HMR API inside <script>?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's to handle the case where <script lang='jsx'> is used, sfc request the file .vue?vue&type=script&lang.jsx.
When the jsx code is changed, the sfc file will be requested again.
Because the module of .vue?vue&type=script&lang.jsx is excluded by the handleHotUpdate of plugin-vue,
.vue?vue&type=script&lang.jsx will not be injected with t= lastHMRTimestamp, so it will not be reloaded.

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

Successfully merging this pull request may close these issues.

I need write tsx in sfc, so I installed both plugin-vue and plugin-vue-jsx. But the HMR seems not work.
4 participants