-
Notifications
You must be signed in to change notification settings - Fork 622
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
Dynamic import not working #52
Comments
@jeanlauliac can discuss more about the plans for this. |
We plan on adding the However, we have no plans to support non-static imports in general, whether it's a We could theoretically typecheck & support dynamic requires under the condition that the list of possible modules to be imported is known at bundling time, though it's not clear what syntax would express that. What I've seen in some projects to workaround this, for example for routing systems, is to have each
That is effectively equivalent to having 'dynamic' requires with a list of fixed possibilities, but more verbose. It would be possible, for one who wishes, to implement a Babel transform that'd make that less verbose. |
@jeanlauliac Thanks for explaining the background! I think what you describe toward the end is exactly what people (including me) expect to happen: 1) provide a way to inform the packager which modules are potentially imported 2) support dynamic (programmatic) import of those declared in point 1. As you point out, type checking would work, bundle size would not be an issue. Since dynamic (variable) imports will be part of the language, can RN afford not to provide some form of support? |
Yes, even though I said we have no plans internally to implement it, I'd love RN to provide some form of support for this ^_^ We have no plans ourselves because we don't have a use case requiring that right now, and are busy with other issues, but I'm happy to look at proposals/PRs. For example we could imagine some opt-in configuration setting that makes packager include all source files from a particular directory into a bundle, regressing build duration and bundle size but allowing for a form of dynamic require. It believes in need to be opt-in as it causes these regressions. Then we would have to figure out how numeric module IDs are handled in such a model. |
Ok fair enough. I will have a think about it (I am not familiar with RN packager etc. so it may be a bit of a learning curve for me but then again, it is something I would love to use, so ... :)) |
Is this being actively looked at/worked on by anyone at this point? This is still a feature I would very much like to see in RN, and was actually surprised not to have in the first place. |
I'd like to publish some simple module to allow people to do the second case easily. |
This bug limit to numbers of really popular libraries like e.g. moment/moment#3624 i saw similar other items with same issue |
This is a huge bummer for me. I'm trying to take a Domain Driven Design approach with my RN app where each screen components have a predictable file structure:
Then have a main This approach simplifies our development process and reduces the number of times we've had compile errors because someone forgot to include their actions/reducers/etc into the aggregated files. As a work around, I'm running a gulp watch on the components directory, then writing to my aggregated file on creation/delete. I hate doing it this way as there are often times when the gulp watch craps out or there's race conditions that spring up when editing that causes a need for a restart of both my gulp watch and RN. |
I'm curious: how do you get the list of files to require, do you use |
@jeanlauliac Yes, I use readdir via a custom CLI for the project that generates components/assets/libraries and adds the file names to the aggregated object. It ends up looking like this:
Then I use
|
I was asking because |
You can do this with It works for us in production. |
@serhiipalash I'll have to give this a look. Thanks! |
@camdagr8 I don't know how this plugin works, but we have folder with these files
I think it replaces our
on this
And it does this before React Native packager started. If you add more files in translations folder after React Native packager start (during development), it will not know about them until you restart it. |
Webpack does this by parsing the module expression and bundling everything it could require Typescript has been coming at typing modules for a while, but the current closest issue would be microsoft/TypeScript#14844 |
I think that not implementing this because it could blow out bundle sizes is like saying you're not going to support One place I'd like this is in importing translation files. They all sit in the same place, and if I could use a variable, I could do something like import(`translations/${locale}.json`) In this case, eagerly loading the whole folder is not just a side-effect, but the intention, given the alternative of const translations = {
en: import(`translations/en.json`),
de: import(`translations/de.json`),
'en-US': import(`translations/en-US.json`),
}; And so on for more languages as my service scales out. Not only that, but I also need to load locale data, both for the Additionally, it'd be nice to be able to const translations = await import(`https://some-s3-url.com/translations/${locale}.json`); and similarly with the locale data that also needs to be loaded. |
Importing unbundled code is a very interesting use-case that would in the general case need to implement https://whatwg.github.io/loader/ I've gotten surprisingly far by simply combining const externals = {
react: require('react'),
'react-native': require('react-native'),
};
async function fetchImport(url) {
const res = await fetch(url);
const source = await res.text();
let exports = {};
const module = { exports };
const require = id => {
if (!(id in externals)) throw new Error(`Module not found: ${id}`);
return externals[id];
};
eval(source);
return module.exports;
} The main problem with this is that error stacks in (at least android) JSC don't include frames from eval'd code at all, even with |
Is there any update status for this issue? |
Bump. It would be extremely nice to have the ability to do this. |
It's not totally related, but wanted to mention here that optional requires are now possible. Not sure how but this might enable a workaround for some people interested by this feature? react-native-community/discussions-and-proposals#120 (comment) |
Looks like this would be a solution for local loading of certain kinds of content, e.g. @benbucksch 's use-case for translation files. https://github.com/itinance/react-native-fs |
Bump. This feature is really important.... |
This is really important use case. |
Are there any updates or any solutions? We really need to require conditionally because of integrating Huawei packages. They will be available on devices with Huawei services, but unavailable on all the others. This is really a blocker 😢 |
you can already do conditional requires @biancadragomir IIRC.
this issue is specifically about not being able to use runtime-evaluated strings as import locations, for instance if you wanted to do:
edit: in fact #52 (comment) mentions it specifically - react-native-community/discussions-and-proposals#120 (comment) mentions it's released. |
@deecewan we are doing that already. But we are using a tool called handpick to exclude the huawei dependencies from normal builds. the problem is that for normal builds (non-huawei), that package isn't available and there's a crash when the build happens since the packager resolves all the "require(...)" from the project, regardless of the if branch they are on. |
You can try metro-code-split https://github.com/wuba/metro-code-split . |
Do not import/require the package at the top of the file. |
It does not work in dev mode since the resolved files are cached by metro. Any changes to them or adding removing will not be recognised. I wonder if there is a metro setting to exclude certain file patterns from being cached? |
I switched to re-pack which uses webpack 5 to bundle your app |
tell expo developers to switch to it too pls |
Since const translationsContext = require.context(
// Relative path to the directory containing the translations
'./translations',
// Include subdirectories?
false,
// Regular expression files filter (eg. only include JSON files)
/\.json$/,
);
translationsContext(`./translations/${locale}.json`) This implementation is based on the |
What if the one using dynamic requirements is an installed package? |
@feri-irawan I'm doing something similar at the company I work for. Our SDK when installed by a user needs to conditionally import another installed package. So you need to provide the relative path to the module you'd like to import based on the structure of Example: const firebaseMessagingContext = require.context(
'../../../../@react-native-firebase/messaging/lib',
false,
/index\.js$/
); Note: The number of |
There has been a conversation around this problem on different thread, please see:
facebook/react-native#6391 (comment)
The problem is essentially that as of now it is not possible to import or require modules dynamically or programatically (using a variable).
With import() in Stage 3 in TC39 this feature is fast becoming a standard language element and the lack of this facility in React Native is becoming all the more limiting.
Also, as per the above conversation there are very legitimate scenarios (dependency injection for example), where such lazy and conditional loading is a must.
Based on all this I would like to make a feature request for this (please let me know if this is not the right forum for doing so).
The text was updated successfully, but these errors were encountered: