Skip to content

Support resolve import.meta.hot.accept dep #16375

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

Closed
4 tasks done
NWYLZW opened this issue Apr 7, 2024 · 4 comments · Fixed by #18840
Closed
4 tasks done

Support resolve import.meta.hot.accept dep #16375

NWYLZW opened this issue Apr 7, 2024 · 4 comments · Fixed by #18840

Comments

@NWYLZW
Copy link

NWYLZW commented Apr 7, 2024

Description

Vite is a great project, and it does an excellent job with code hot reloading. However, I feel that it could be more friendly towards monorepos. When I tried to depend on other packages within a monorepo, I encountered some issues. The 'accept' feature tracks dependencies based on file paths, but when my module is an external module (relative to the current module within the workspace), I found it inconvenient to register the paths. I believe this project could potentially provide some useful APIs to address such needs.

import.meta.hot.accept('@foo/bar', newModule => {
  // never trigger
})
import.meta.hot.accept('@foo/bar/a', newModule => {
  // never trigger
})
import.meta.hot.accept('foo', newModule => {
  // never trigger
})
// I have to write it this way, but it lacks any scalability.
import.meta.hot.accept('/@fs/Users/username/to-the-project/packages/core/src/index.ts', ()=> { ... })

Alternatively, I could redefine a file and then reexport the module.

// src/reexport.core.ts
export * from '@foo/core'
// src/index.ts
import.meta.hot.accept('./reexport.core.ts', async newModule => { ... })

This method is incredibly inconvenient and becomes a pure burden when it comes to writing code.

Suggested solution

  • import string deifne
// vite.config.ts
export default {
  importDefine: { workspace: getWorkspace() }
}
// src/index.ts
import.meta.hot.accept('<workspace>/packages/core', () => { ... })
// or
import.meta.hot.accept('workspace:/packages/core', () => { ... })
// or
import.meta.hot.accept('/@workspace/packages/core', () => { ... })
  • auto detect string path
// external pacakge
import.meta.hot.accept('xx', () => { ... })
import.meta.hot.accept('xx/yy', () => { ... })
import.meta.hot.accept('@xx/yy', () => { ... })
import.meta.hot.accept('@xx/yy/zz', () => { ... })
// relative path
import.meta.hot.accept('./a', () => { ... })
import.meta.hot.accept('../a', () => { ... })
// absolute path
import.meta.hot.accept('/@fs/a', () => { ... })

accept(deps?: any, callback?: any): void {
if (typeof deps === 'function' || !deps) {
// self-accept: hot.accept(() => {})
this.acceptDeps([this.ownerPath], ([mod]) => deps?.(mod))
} else if (typeof deps === 'string') {
// explicit deps
this.acceptDeps([deps], ([mod]) => callback?.(mod))
} else if (Array.isArray(deps)) {
this.acceptDeps(deps, callback)
} else {
throw new Error(`invalid hot.accept() usage.`)
}
}

With this approach, it seems that I only need to check and resolve the 'deps' parameter at this point. I have tried it, but I'm not sure why there is a '/src' added before the relative path. I couldn't figure out when it was added, so I paused the experimental changes using this method.

Alternative

No response

Additional context

No response

Validations

@justid
Copy link

justid commented May 30, 2024

Can't agree more.
i thought import.met.hot.accept should resolve path just like import('@/somefile.js'), but it never trigged

@justid
Copy link

justid commented May 30, 2024

I found a better way to do this if you are using react.

import React from 'react'
import {lib} from '@/lib.js'

export function SomeComponent(props) {
    React.useEffect((){
       // you can get the new lib here
       // if you are using import.meta.hot.accept callback , you will get the old file instead of the newest one.
       console.log(lib)
    },[lib]);
}

@NWYLZW
Copy link
Author

NWYLZW commented May 30, 2024

I found a better way to do this if you are using react.

import React from 'react'
import {lib} from '@/lib.js'

export function SomeComponent(props) {
    React.useEffect((){
       // you can get the new lib here
       // if you are using import.meta.hot.accept callback , you will get the old file instead of the newest one.
       console.log(lib)
    },[lib]);
}

Seems a bit magical. I'll try it out later to see if it can work under vite.

@jods4
Copy link
Contributor

jods4 commented Sep 6, 2024

Virtual modules are confusing, too.
Let's look at unplugin-vue-router for example.
In regular code you use import routes from "vue-router/auto-routes".
Yet in front-end the module name is different. If you want to accept it you need hot.accept("__vue-router/auto-routes"). Note the __ prefix, seemingly out of nowhere.

@github-actions github-actions bot locked and limited conversation to collaborators Feb 7, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants