And now, I wanted to wrap up dependencies. As I promised, I wanted to show you how you could load dependencies dynamically. Do we have any questions so far? With what we just covered? Opportunity. Lars. So you said your dependencies are in DevDependencies, but you spread the dependencies. Actually, I spread these dependencies that are Azure dependencies. In DevDependencies, you see, I have them on the workspace level, which is a Webpack, DevServer, and so on. You don't want to share these because these are being executed on this computer, on server, in CI. In the pack, this is not being... You look at the top level of packages. That's what I thought, too. Okay. Again, the reason why I'm using Lerna is, and I hate to confuse you, but I'm using Lerna so that it's easier, so you have everything in one repository, so you don't have to think about multiple repositories. In real life, I would not use Lerna for your project. And the reason is fairly straightforward. As your application grows, your.git repository is gonna be huge, and then you're gonna create PRs, and there are gonna be merge conflicts. And then Lerna is good about sharing. And as a microfinance, yeah, you wanna share a little, but you also wanna own a little. And then if everything is in one repository, all the possible flavors of testing libraries, and runners, and CI scripts, and all that stuff, it gets confusing, right? Because you wanna give that freedom, and if freedom is exercised in a common space, it's confusing. Just like if you had 10 people speaking 10 different languages trying to communicate, but they can't, right? It's not very useful. But the cool thing here is for features, I would use, and I prefer, I always suggest using dedicated Git repositories per feature. And Learn.NET is really good when you decide to create a custom set of libraries for your application. Shared code. The code that you really wanna make available to everyone else, the shared part. So, where you have a special logic for communicating between apps, or where you have special logic for loading translations, or things like that. In some cases even authentication, although that can be dynamic as well. So those are or tracking and tagging, right? Those can be feature apps, but can also be libraries, if they are non-functional, so users still really interact with them. It really depends on how projects and teams use those. I've seen, for example, tracking to be a feature app, so that means I'm a feature app, I'm totally agnostic and I do my thing. I can expose libraries, others can use them, or I can do my own thing, that's a feature app. Or a library is, I'm meant for others to use me and I'm not doing anything automatically. My purpose is for other projects to use me, but they don't have to use me. So that's the difference, so that's why I said, technically this is easy to understand, I think, I hope. Architects and solution architects can have a little bit of a hard time getting things in order, especially for the first time as that experience is being built, but the major improvement and change, and we know how change can be difficult, can be on the organizational level. Okay, I'll stop preaching about that because there is always a story about everything we preach, and this can really get messy. Okay, so we saw that, and as I said, the next step is for us to create a dynamic loader. Now, I'm gonna do that in the core, so we have remotes, I'm just going to comment this out. I'm doing this, so we have some kind of history, so I commented this out, and we probably need to restart the server for this one. Okay, and obviously, it would fail if you're trying, so this is public, private, good, public. All right, it's probably going to fail. No, it is going to fail, because it doesn't know how to load to Hero. So let's work from here, let's fix this. So app is using these two libraries. Yeah, I can no longer use this level of import if I use dynamic loaders, so I'm going to resort to something else. I'm going to create a new component, I'm going to call it loader. I have it ready, guys. I'm not going to be typing it. And trust me when I say it has probably a couple of hundred lines of code. No, almost 100, but this is a simple version. And I'm going to walk you through this so you know what's happening. First of all, let's skip this, let's skip this step. I'm going to talk about that later. So what do we need to do? We need to create a script, right. We need to create a script. It should be a synchronous. And we attach a listener on load. So when it's loaded, we say, we are ready. If there is an error, we say, oh, there was an error. And eventually when we unmount, we can remove the script tag, right? That's just working with script tags. We're gonna be using this loader function. So the loader function does this, uses this hook to import the source. And if we are using development, now in the build step, this block in production, this block would be deleted because Webpack is going to statically know the environment is production, so I can delete this code, tree shaking. But we are working development and we're gonna see loading feature and a fail to load feature if it fails, right? As a helper. We use suspense and that means when we are loaded, we're gonna kick in this function that communicates with module iteration. So that's what I said I was gonna mention later. So this is really not. I don't think you find this in documentation but you can find traces of these, you can find traces of these commands or maybe even very similar functions in various examples online, right? I even think module federation, a GitHub organization that's owned by Zack Jackson I think he may have created something that is too. Anyway, the whole thing is we call these special functions that are only available because webpack registered that our code needs it. You can not call this for console, this is not in global scope. A webpack parses your code and it says, Oh, you need webpack in its sharing, this is a special method. So we say, okay, I'm going to, again, in a sharing there is something called scope. We always use the full scope but you can create additional scopes. I haven't shown you that because I feel that that's mostly not needed. The full scope is just gonna cut it. But if you need to load a shared modules in different namespaces, then you can do that too. Then the default namespaces, obvious default. So we are initializing that feature through this line. And then we say Windows code. So if you remember when I said, we go to a package, sorry. Not package, I meant webpack-config. And we named hero, right? So that means there is going to be an object called window.hero. And that's how it works. That's how we bundle the JavaScript modules. And that is also configurable, if we change that how that library works through config, there is documentation for that. This is definitely out of scope for this intro. But you could totally change how features are bundled. Again, I'm not gonna touch that, but so far just so you know we get that container, now which is the runtime. And then we initialize, right? Webpack share scopes in the default share scope, we initialize that container, that script tag that we received, we say, hey Webpack, so we call the init method of that script and we merge it with that default namespace. So, that's when I said, every remote feature that you load is going to merge runtimes, it merges registries of dependencies, merges in the information that they share as they get introduced. And this is that merging, initializing, right? Finally, we get the module and we return it, it's a factory method.
Comments