Skip to content

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

@NWYLZW

Description

@NWYLZW

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions