-
-
Notifications
You must be signed in to change notification settings - Fork 6.2k
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
Can't dynamically import a node module with a variable #14102
Comments
Start a new pull request in StackBlitz Codeflow. |
It will get some warnings.
Try import dynamicImportVars from '';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
dynamicImportVars({
// options
}),
react(),
],
}); But the plugin has some limitations on importing path. See more: https://github.com/rollup/plugins/tree/master/packages/dynamic-import-vars#limitations |
Hi! Thanks for the quick reply. The limitations of this plugin specifically says that node_module imports wont work, which adds more problems than I originally started with. |
According to the page listed in the warning, you are not complying with Vite's limitations as far as I can see:
|
I am aware. Both of the cases that you provided from the reproduction still worked though, and is a smaller part of the issue at hand. |
Making this work will be tricky but not impossible. When you do |
I'm using Basically this works: defineAsyncComponent(() => import('ovosSkillPersonalOpenvoiceos/MainComponent')); But this doesn't: const componentName = 'ovosSkillPersonalOpenvoiceos/MainComponent';
defineAsyncComponent(() => import(componentName)); I tried this as well but without success: const componentName = 'SkillPersonalOpenvoiceos/MainComponent';
defineAsyncComponent(() => import('ovos' + componentName)); Not sure if there is a solution/workaround. Thanks 👍 |
You need strings inside |
Thanks |
@bluwy I have a webpack project that can correctly split chunks as intention when both variables and packages appear in the path, but I encountered this feature unsupported during the migration to a Vite project. const lang = await getLanguage()
const jsonFile = (await import(`@company/i18n-json/${lang}/index.json`)).default May I ask if this feature is hard to implement due to differences in dynamic import parsing algorithms between webpack and Vite/Rollup under the hood? Or is there any other design consideration or trade off for Vite/Rollup chose not to support it, like hoping follow to the ESM specification strictly etc.? I understand the complexity of the module search algorithm currently with the introduction of Node submodules, and I appreciate the work of the community team. Please forgive me if I said anything incorrect or offended. |
I am totally supporting your comment. When you start with Javascript and frameworks, most of the documentations recommend to use Vite because its the "new" way to start new project but Vite still lack some of the features supported by the "old ways" such as Webpack. I got really frustrated when I had to quit Vite to start fresh with Webpack. Its not a complaint but a feedback and I'm grateful for what the Vite community did (thanks 👍 ). |
We're not intentionally not supporting it, it's that this usecase wasn't considered in the initial design/support for glob imports. It started out as a way to glob relative files so it worked for relative paths, but then it slowly extended out, e.g. supporting globbing with
We're definitely open to a PR if someone submits one. For accepted enhancements we have the "enhancement" label. If you'd like to see this feature implemented, you can also leave a 👍 to the issue. If you'd like to workaround at the meantime, it's doable to also write a plugin that generates the list of dynamic imports and inject it into your code. Essentially doing the globbing manually if you know what the langs are. |
Would love to help out, time is a bit of an issue though, so whenever I get the time I can try to whip something up. Any pointers to how/what can be done would be greatly appreciated if its not much of an ask @bluwy ❤️ |
The main starting point would be the vite/packages/vite/src/node/plugins/importMetaGlob.ts Lines 544 to 548 in a43167c
(search for Also note that dynamic imports with variables are also transpiled as vite/packages/vite/src/node/plugins/dynamicImportVars.ts Lines 241 to 248 in a43167c
|
Thk for your detailed explanation! I will keep an eye on it. For those who may face the same problem as me can try this temporarily as long as your project lists the dependencies correctly: const lang = await getLanguage();
let json = undefined;
if (compatRelativePath) {
/**
* We manually use relative path import to make the rollup plugin happy.
*/
json = (await import(`./node_modules/@company/i18n-json/${lang}/index.json`)).default;
} else {
json = (await import(`@company/i18n-json/${lang}/index.json`)).default;
} I know this may feel a bit dirty and definitely not science, but engineering :) |
Okay, spent the entire day trying to figure it out and I thought I got pretty close? But ultimately ended up no where. Here's my digging for the record: I started at the files that you reference, I found out that vite/packages/vite/src/node/plugins/dynamicImportVars.ts Lines 105 to 109 in 598d423
Which got me into a huge rabbithole to see what and where I landed here
I landed here because other dynamic imports were resolving from vite/packages/vite/src/node/server/pluginContainer.ts Lines 675 to 688 in 598d423
So following
But non dynamic node_module imports (Like import( vite/packages/vite/src/node/plugins/resolve.ts Lines 347 to 363 in 598d423
The reason this condition is failing is because of the I wish I could say I know where to go from here but I really don't. I'll try again tomorrow but I can only really commit my weekends to this. any thoughts @bluwy ? Details that don't really effect the end result (i dont think)the import analyzer warns you most likely because of this guybedford/es-module-lexer#137 (correct me if im wrong) Which is used here
and is undefined here (because
|
Sorry for the late reply. I've been focusing on getting Vite 5 out and missed this. You'd first have to extract the library name vite/packages/vite/src/node/optimizer/resolve.ts Lines 42 to 45 in a0c5123
Though we can't really use it completely to fix this cleanly. We might need to carve out a part in the Thanks for taking a look at it. Understandably it's quite a big task to finish up. I'll also remove the "contribution welcome" label for now since it's a bigger task than expected, and we usually reserve it for simpler stuff. But we'll still accept contributions if you like to look deeper into it! |
No worries! I haven't had much time over the weekend anyways. I'll take a last look over this weekend to see if I can hack something together with the new info. I really appreciate your guidance ❤️ |
Hi, how far are you on this matter? I would also need the feature to "dynamically globally import node_modules" for localization purposes. I am working on an app with 9 languages/locales and have two dependencies, which have to be set correctly, with a proper locale. I do not want to load all the localization settings, for all the languages. This worked with Webpack perfectly and now switching to Vite, this is the only "open" thing, for me to fix. Thanks and kind regards! |
Hello! |
NOTE: I didn't manage to make it work the same way webpack worked. The problem is that vite runs after tsc, so the env variables get replaced after the transpilation. Thanks to import-meta-env I make it work but I lose the code splitting since the build now can dynamically change the env variables... Look for this discussion: vitejs/vite#14102
I am not quite sure if this is exact the same issue, but letting the comment anyway because I could not find it explicitly this way. I was trying to make this work: translations = !lang.startsWith('en')
? (await import(`./${lang}.js`)).default
: (await import(`./en-us.js`)).default It would work on dev, but build would create just translation file to So after digging a bit on what @bluwy said on
I've came to this solution below. Worked pretty well for me, loading just the correct file at the correct time, for both dev and build. Let me know if this is an anti-pattern or something like that. const modules = import.meta.glob('./*-*.js', { import: 'default' })
translations = !lang.startsWith('en')
? await modules[`./${lang}.js`]()
: await modules[`./en-us.js`]() |
I recently filed a similar bug (maybe the same): I'm trying to use the Vite Repo: https://github.com/karlhorky/vite-dynamic-import-build-missing-files
await import(`./x/${__NAME__}.ts`);
import { defineConfig } from 'vite';
export default defineConfig(({ mode }) => {
return {
build: { target: 'esnext' },
define: {
__NAME__: JSON.stringify('dynamic'),
},
};
}); This works in development but breaks after build:
Is this is the same issue described above? |
Fixed my problem, thx. |
@Brandon-Ln maybe not related but he type of the import is |
In my understanding, dynamic import in this use case is a runtime behavior, so it may not be able to be inferred by static analysis. In my use case, I mark the returned result as an |
but how @Brandon-Ln ? i am not getting it, in your example, you import a dynamic json, i could also have "index.json", "about-us.json" with different structures. const lang = await getLanguage()
const jsonFile = (await import(`@company/i18n-json/${lang}/${json}.json`)).default as unknown
|
What I mean is like: type JsonFile = Record<string, string> // You can replace the types you are interested in here
function jsonFileValidator(target: unknown): target is JsonFile {
// Your custom runtime check logic, It is just an example here
return typeof target === "object" && !!target
}
const lang = await getLanguage()
const jsonFile: unknown = (await import(`@company/i18n-json/${lang}/${json}.json`)).default
if (!jsonFileValidator(jsonFile)) {
// Error handling
throw new Error("Unsupported json files.")
}
/**
* 'JsonFile' is infererd
*/
jsonFile But if you require to infer all possible fields of the JSON file that may be obtained completely, I think it may be impossible in this scenario👀 |
Use dynamic imports, even though Vite does not quite yet support this for node_modules. See vitejs/vite#14102 Tried different approaches, including `import.meta.glob` to get all the locale names first. But the static analysis still can't figure out all the possible imports, so I get the dreaded warning.
CRA is no longer actively developed: https://github.com/facebook/create-react-app The dependencies are old and causing numerous security warnings, conflicts with other packages, etc. Let's switch to Vite - looks promising, more lightweight and modern. Without the bells and whistles of Next.JS that is not needed for my needs here. Rough steps needed to make this work: - Fix i18n - Fixes needed to make the worker work with vite - Make the Worker be type: module. - Ensure no dnd, etc. dependencies get loaded - for that, I had to split out the constants and utils from components to separate files. - Switch to ~ for root src path - Like it more than @ - @ feels like root for DNS - ~ feels more natural, being home path on *nix - Use dynamic imports, even though Vite does not quite yet support this for node_modules. See vitejs/vite#14102
CRA is no longer actively developed: https://github.com/facebook/create-react-app The dependencies are old and causing numerous security warnings, conflicts with other packages, etc. Let's switch to Vite - looks promising, more lightweight and modern. Without the bells and whistles of Next.JS that is not needed for my needs here. Rough steps needed to make this work: - Fix i18n - Fixes needed to make the worker work with vite - Make the Worker be type: module. - Ensure no dnd, etc. dependencies get loaded - for that, I had to split out the constants and utils from components to separate files. - Switch to ~ for root src path - Like it more than @ - @ feels like root for DNS - ~ feels more natural, being home path on *nix - Use dynamic imports, even though Vite does not quite yet support this for node_modules. See vitejs/vite#14102
Seems fixed in vite |
@minimit Ohh nice, can you show your demo code that is working? Do you know which change in the changelog entries for |
Also interested in your demo code. I just bumped my repro that was provided above and it doesn't seem fixed. updated repro: https://stackblitz.com/edit/vitejs-vite-cc4fvd?file=src%2FApp.tsx |
Well now i've a node package that does a dynamic import inside it's own package and it works, before it gave error, it's this line:
But from your demo, if you try to do a dynamic import inside node modules it still gives error. |
Still not working for my case, which means, I can not dynamically import node_modules dependencies when needed. I tried with Vite dynamic import and with rollup dynamic imports and no luck. |
Describe the bug
Hi! I've ran into an issue where I can't import a dependency from node modules with a variable. But without a variable, it works. I also tried using a variable for a "local" import and that also works.
I've attached a minimal reproduction, that uses dayjs as an example.
Reproduction
original: https://stackblitz.com/edit/vitejs-vite-rb9v1k?file=src%2FApp.tsx
vite 5.4.2 (same issue): https://stackblitz.com/edit/vitejs-vite-cc4fvd?file=src%2FApp.tsx
(check console)
Steps to reproduce
No response
System Info
Used Package Manager
yarn
Logs
TypeError: Failed to resolve module specifier 'dayjs/locale/en'
Validations
The text was updated successfully, but these errors were encountered: