Build Once, Use Anywhere: Microfrontends with Svelte

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
all right let's get started hello everyone um i'm giving a talk today on build once use anywhere using microfrontenzus felt so let's get started my name is evan payne i'm a senior front-end software engineer at netcentric european-based global business does a lot of interesting work good consultancy good values really enjoyable place to be the other day i put out a tweet i was like you know is it crazy for you at work well today i bounced between three projects that i lead uh one was angular inside of adobe experience manager another was uh i felt web component as a micro front end within two different places and the third one was moving our existing library or app into view three with tailwind in an nx monorepo all three very different technologies in some ways but my thing was can i kill my imposter syndrome now i think i can handle this but uh and imposter syndrome says no it never goes away and if this is starting off as a public service announcement no matter how good you get at this no matter how great you feel at the front end if you have imposter syndrome i don't think it goes away there's always something that you don't know or that you're not certain about and that's good it can be good don't let it get you down now to get to the point of this talk um we had some different requirements that were required by for the client to develop a sort of proof of concept so one of those was that we had one week to do it another was to build an app feature that can run in two different places so live within a pre-existing page or site and run on its own it should also have a standalone development and deployment cycle meaning it can be releasing new features all the time without the places where it's embedded needed needing to do anything and it also needs to meet the web component standard they were very clear on that they wanted this to be a web component so let's look at those one at a time so first one was one week and uh yeah that was uh that's accurate that was a a lot of pressure in the end we had a little more time and that allowed us to do stuff but we needed to work fast so next one is maybe the core of what we're working on build once use anywhere so the setup we had was this we had on the left-hand side our own manage site and server top left to server bottom left is our own site um we on the right-hand side we had salesforce um or this could be any third party uh to be more generic place uh with its own set of servers and apis and usually the scenario is that they talk amongst themselves and if you want them to talk to each other the front ends let's say you need a lot you need something that does the proxy and the back end and all that so our existing setup was as it is we wanted to build something that could live inside both of those front ends as a component essentially uh but but work on its own and have a standalone development or deployment cycle so what we came up with architecturally was something like this where our feature app at the bottom uh is on its own and it has a little proxy server so it has its own back end that it can have consistency with know what the apis are there and then in exchange the proxy server does the cores handling all the stuff that's required to talk between the first server and the salesforce server um allowing that the app only talks to that it doesn't have to worry about knowing authentication or if things have changed if things change its backend will handle it so trying to become a little flexible and the interesting thing here is that this is basically a micro front end you can embed this in both places they'll talk to the proxy server and get what they want so what's a micro front end this comes from a site micro frontends.org a good write-up on that the idea behind them is that the website or web app is a composition of features that make up things and each feature should be owned by independent teams so in some ways it's saying that this team should be the whole stack and the micro front end yes it's a part of that stack that is what the deliverable is but the back end parts the apis that it has the interfaces all that are also part of this team so that you can work in a sort of vertical silo and it makes it a little easier to develop new features when you want to um adapt them when you want to improve them because the rest of the site where this is used doesn't have to fix its updates change its script order any of that sort of stuff it can be quite pleasant and in our case that's exactly what this does we have our app that's embedded there if something changes this site doesn't need to upgrade because the way that it's embedded in there it just knows the javascript and the root html hook i'll show you that in a second and any updates that happen on this side this will have to update but that's okay too this is a little faster development process cycle so the last piece of the puzzle was that it should be a web component which is quite exciting there's a good site web components.dev which goes through all the details and this particular article goes all the ways to make a web component and there are quite a lot there's at least 20 of them including vue and react and even angular has angular elements but the part that look i looked into first was okay we're doing some stuff that has potentially complex elements to it we're building something that is as a feature even as a component isn't just a component it isn't just a slider or something it's it's something a lot more app-like in nature so i want to use a framework of some sort and smallest bundle was spelt and as soon as i saw that down there in the bundle size i was like i wanted to use felt forever so in the end we did some comparisons but chose to use spelt and the very interesting thing about svelt is that it's truly reactive meaning and you'll see once we get into the code a bit it just kind of works really elegantly and i liked seeing the discussions online as felt was coming up to its latest version three um with between rich harris who created felt and evan you who created vue i've seen them in github comments like going back and forth talking about the potential of proxies and reactivity within their systems it's nice to see the front-end community kind of grow together in that way this felt's very interesting i have had a good time and i'll show you why so once we decided on the architecture building a web component using svelt and putting it into a microfrontend kind of concept so that it can be embedded anywhere now it's just time to build it so let's dive in if you want to follow along afterwards the demo code is here but let's dive into the actual code so svelte likeview has a single file components so and anyone you will have a script tag uh your style tag and then your html at the bottom different than view which is html inside the template at the top doesn't matter it's the same kind of concept so all you need to do to make a regular svelt component a sort of top level one a a custom element so that you can bet it on a page is add this to the spelt options at the top the tag is item detail spa in our case this is what our custom element tag will be and in your rollup config or however you build it you need to pass through this felt option of custom element true with that in your this is our sort of demo page you can then add this item detail spa and when you load the page and render it whatever you've told svelte to create will be created there so already off the bat i was really happy to find that hey this is done i don't have to jump through a lot of hoops to set up this svelter's does it under the hood already comes along with the package no imports no nothing fancy it just works and if you were in to embed this now whatever you create in another place all you would need to do is make sure you load the script that is generated by your build here single javascript file um this one in particular and this is the development version but that needs to be loaded and then if it finds this element on the page or whenever this element is added to the page then it will bootstrap and run the app as expected and that's the perfect situation for what we need here we potentially will be navigating within a single page app to a section that uses this item detail that we're going to create here and we want it to be able to load asynchronously and just work without needing anything other than the script and the the tag that passes in okay so that's step one step two is passing in parameters so in our script tag in any felt component um you will declare props by exporting them so export let preview will give you an input prop of preview we need that so in case we don't want to use the real api we can use the dummy data and we will also take an issue id a base api url not always necessary if your api is on the same server as the page you're on so allow the apps where this is embedded to decide that and a theme just to show that we can do something like that here i'm using typescript because i love typescript i use it on like all of my frameworks now angular and view uh and it was nice to see it was supported in the latest releases of svelt so all i'm doing here is declaring a type um so saying that when we get this data back from the server it'll be i have an id and name description as strings then i'm declaring data so this is a property that'll change over time you'll see later that we use this and this is what we're actually going to use in our template to display the data these are some helper functions get data get dummy data we'll return after three seconds an id with this name description of this issue and if you needed to for extend to say what the api endpoint for this was so the base url is one thing but they don't always know what the api's call should be this you can specify this so in particular we'll use that we would use that let's say inside get data to properly specify the endpoint okay now we get to the core of what felt's reactivity system is like you have this dollar sign equals or dollar sign set to basically anything inside this wrapper will evaluate whenever one of the outside declared properties changes so if preview changes its value this statement will rerun same for if issue id or base api url change which you know this statement is setting data equal to the response so get data or get dummy data or promises so data is going to be a promise that resolves to an issue so it's an asynchronous property in particular and one caveat i noticed which i don't think happens in right inside regular components when you're inside a system is in the web component version the props fire one after the other meaning as the component loads it sets them in the same order that you do it so in our case we relied upon preview being undefined as long as it is not undefined we'll evaluate this so until it's actually set true or false which means it's a required property we won't do anything so here and here what we discovered is if we put preview first true or preview true in the first place it would happen too early issue id would still be undefined theme would still be undefined so we had to put it at the very end to make sure that it was the last one that was evaluated but besides that that just kind of works when preview is set it checks is it set to true or false if it's false and there's no issue id or and there is an issue id we will get the data from the actual server if it's anything else or somehow we forgot the issue id we'll get the dummy data so that is helpful it could be more in depth we'll figure it out but that's quite nice so then in the actual template itself down at the bottom we have our class with the background the wrapper class and inside here is where we use this uh svelte has something that is more or less like um suspense that react and now view have as well um where you will wait for this data so this is our promise while it is resolving uh you have this loading state that you can put in so during those first three seconds we can just kind of wait for it to happen then once it resolves once promised.then you declare a variable here i'm calling it issue and then if there is an issue i just make sure and i display it as a template issue name and and description so if something goes wrong you also have a catch block where you can display if something goes wrong and that's that's all that's needed so in our particular case now we're going to double check in our main ts we're using app a and i'm going to npm run dev and we should be able to open this loads very quickly because it's not a very complex app but you see we have our loading state and after three seconds it fills in the issue details that is quite fancy if we were to go over here to our index.html and change the theme to dark let's say that would update background is now dark and we have different theme so very little effort to get to a very first starting point for us to have this is now a web component that can be used anywhere and again to keep in mind this script and this custom element are all that you need on a particular page once it's there it just works and that is exactly what we wanted but we wanted to also go a little bit further and so one thing that we wanted to say okay well look we might need the user to click on something in this app and then we'll need to tell the parent application the parent page that something has happened so i need an event of some sort an output if you were thinking in terms of components so svelte makes this also really easy it was it took us a few seconds to find it but in the end what we're going to do is we're going to set a query selector on the item detail spa so this custom element and we'll add a listener for this custom event item detail spa success and when it happens we'll console.log success in the event itself to show what's possible so how do we actually get that to do something so we're going to go into app b here and up at the top what we found was that svelth has this internal thing which is exposed for now i hope that it will be in the future or moved up to a more top level because this is quite useful get current component and if we go down here uh to this bit this is all i added here so i define component as get current component and then i create a method a success called success which when it runs will create a new custom event item detail spa success like we wanted and in here the most important property i think is composed true which will make it jump out of the shadow dom boundary and bubbles and cancelable are those things you can set but detail as well you can pass through data which is also quite nice then when again when that runs it creates it and then component the git current component will dispatch that event and that just works so it's already built in it will it will do the work to set it up so that it emits the custom event um then down here in our template i created a button and say on click run a method which we'll call the success method so anytime they click we should be seeing that console log that's already set in place i will change our import in our main file to app b so we can use that one and when we come back to the page it's loading and we see this button i realized earlier i forgot to mention that the component that we see on the page and one of the things that's nice is it is a shadow dom so you have the component that's on the html and this is your kind of app shell if you want might have other elements and other apps on it and inside here is a self-contained shadow dom that has our styles and our container with our issue and everything we want to do in here so that satisfies the web component part of it okay but if we click on this then we see success custom event it works it does what we want to do and we have the data that comes through in the event as well again it didn't take very long for us to get that done it just kind of worked and came along for the ride out of the box was felt very exciting for me okay the last thing that i want to show you is here in app c um this there's a thing in front end that's been going and waiting for quite a long time which is called container queries and the idea is you want to at different break points be able to change stuff but not the media not the window or the browser size because especially when you're dealing with microfrontends and in these places you don't know that the browser size has anything to do with where you're being displayed right you could be in a sidebar you could be in a full width container you could have a parent width of 400 pixels or 1800 pixels you just don't know for sure so you have to actually focus in and think of this in terms of what is the size of my parent what's the container that i'm inside and write your media query so to speak as container queries instead so svelt made that quite easy i have this element width variable and if we look down in the template sveldt has this thing called bind client width and what that does is it says hey what size am i currently and anytime that changes it will set the variable equal to set element width equal to that value already right off the bat that is super handy so we have a constantly are able to track the width with again just kind of one line two lines of code um and then we also want to then set a class so this will be our kind of hacky version of media queries but let's see where we actually do that so again you're declaring current breakpoint it's going to be something that changes over time then what i added down here in our reactivity section was i defined our breakpoints so we want to do mobile first and then we have medium upwards if you're larger than 765 or large is 1280 then in a reactive statement so when breakpoints or element width which are defined outside when those change this whole statement will run again and it'll reset the current breakpoint and what i want to get out of that is a list of class names so i'm reducing over these values to check hey is the element width greater than or equal to 765 if so give me bp medium up otherwise don't give me anything and then joining them together with spaces so when you get up to 1290 pixels you should have both of these classes being added and then all you have to do is in the template set that class name and use it so in our particular case we have this button which has a width at a 100 percent now at mobile sizes but when we get to breakpoint medium up when it's a child of breakpoint medium up then with 100 pixels so the benefit of having this the top level of your web component is that you can just use it throughout your templates like this if i'm a child of this class keep it as flat as possible and i mean that just worked so here we are at a larger break point if i shrink it down i have 100 i will go show you the class changing as well so background dark position relative if i scroll uh open a little bit up to our breakpoint there we see bp medium up supplied and takes the css so this is something that you know yes the browsers have media queries but container queries are traditionally a little bit harder to implement because you need to do the javascript and it's not that the javascript isn't still there it's just that we didn't have to write it because sveld had this for us baked in out of the box what you'll see as you add in features like this is that your bundle size expands so when we were compiling uh when we compiled app c it's uh 1 000 lines of code unminified and everything if we were to change this back to our very simple app a and hit save and it'll re-render this and we'll check this and it's 884 so svelte only includes what you're actually using that said these are quite modern and they're written quite modern and if you as long as you can support you know browsers that can run es2015 uh or higher you'll get a lot of uh benefit out of this and once it's minified and gzipped and all of that it can be quite a small bundle okay so that's my general uh talk about all of this um and how we actually implemented it and again to reiterate it was simple it we got stuck for a few times but we ended up being a lot faster than we might have been with some other frameworks where you know we had to struggle to figure out how to do the custom elements or container queries or any of that stuff so in the end success um [Music] yeah we we implemented everything we needed to um we got it done really quickly and it allowed us time to do more than we had expected actually so that was quite a pleasant experience overall if you're thinking forward about this if one some pointers that you might want to keep in mind one is to keep the contract stable it is pretty important to have a fixed number of properties and and keep them as they are the reason being uh if you change one and an app cannot deploy for six months their newest version which has your updated script tag or your new properties their app will break so you do need to version your scripts and and also keep the contract as stable as you can so it doesn't get difficult to implement or or move stuff around something that could help with that is to create a manifest file where you can programmatically give the information so that if they did happen to a build they could find the newest version or fix themselves to a current version the other thing to keep in mind is it is totally possible and you probably will if you embrace this sort of micro front-end solution over time you will embed multiple single-page apps you might go always felt or you might do another one that's in react because that team prefers that or angular that's one of the nice things is you can kind of pick your own way of doing all of this vanilla javascript framework or a web component would work as well if so then you need an orchestration layer you need something that will be responsible for the actual loading of the dependencies so that if you have two apps that are running react on the same page and the same version of react then you only need to load that script once there's a few other considerations as well as how do they talk to each other if they need to shared state user ids things like that [Music] it can go it can get quite complex but there's a framework called single spa which seemed to tick all the boxes and cover all the cases so worth looking into if you're going that direction now the last topic is what do i actually think of micro frontends as an architectural choice so um they're a great fit for web components they were perfect for what we needed you do have this self-contained encapsulated methodology they fit into both places and you can update them in one place perfect fit they're nice for a diverse architecture where you don't have control over all of the elements in the full stack like we did in this case as well having another api or another server entirely that really wasn't under our development process at all that being said they're probably not the best case for all use cases if you control your stack in full if it's your back end your micro services your front end and such it's probably overkill you can probably find better ways to do that i'm not completely sold in the idea but again in this particular case it was a perfect fit so i'm i was really pleased with the end results and that's it for my talk if you have questions this being a pre-recorded talk please get in touch with me uh evanfuture on twitter and let me know what you think if you agree if you disagree any way conversation is always welcome thank you for your time and i will see you again next time ciao
Info
Channel: Evan Payne
Views: 14,449
Rating: undefined out of 5
Keywords: svelte, microfrontends, micro-frontends, frontend architecture, web components, frontend, javascript, reactivity, sveltejs, js frameworks
Id: -SvfwgHPh-A
Channel Id: undefined
Length: 24min 34sec (1474 seconds)
Published: Fri Sep 25 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.