Remixing How We Give

Rate this content
Bookmark

A review of how we're using Remix at Daffy.org to change the way people give to charities.


We'll talk about why we decided to use Remix, how we've used it and migrated from our previous frontend application and some patterns and libraries we have developed internally.

32 min
18 Nov, 2022

Comments

Sign in or register to post your comment.

AI Generated Video Summary

Daphne uses Remix for their web application, benefiting from its resilience, error boundaries, cache boundaries, and progressive enhancement. Remix simplifies form submission, authorization, and validation, and allows for easier refactoring and code duplication avoidance. Next and Remix are used together, with Remix serving as the backend for the frontend and handling data aggregation. Remix provides query functions for fetching data, mutations for form data validation and API calls, and custom conventions using the handle export. Migrating to Remix resulted in smaller JavaScript files, faster navigation, and the ability to preload data and assets. The migration process took around nine months and involved mixing Next.js and Remix using Express. Hiring someone to work on Remix is easier than hiring for other frameworks.

1. Introduction to Daphne and Remix

Short description:

Hello, welcome to my presentation. I'm Sergio Salambri, web developer at Daphne, and I'm going to talk how we use Daphne, how we use Remix at Daphne. Daphne is a platform to help people donate to the charities they care about in an automated way. We use Remix for our web application because it provides resilience, error boundaries, cache boundaries, and progressive enhancement. With Remix, we can catch unexpected errors, show known errors, and ensure the application remains usable even if JavaScript fails to load. Additionally, we chose RemixBoot for its form mutation capabilities.

Hello, welcome to my presentation. I'm Sergio Salambri, web developer at Daphne, and I'm going to talk how we use Daphne, how we use Remix at Daphne.

So what is Daphne? Daphne is a platform to help people donate to the charities they care about in an automated way. To do that we provide both an iOS application and a web application and we use Remix for that web application. We also use Remix for other apps. We are going to focus on how we use it for main web. That's what users use.

So first of all we started using and building the front end. Daphne or MVP was a router application being served from a Rails route and compiled by Rails webpacker. It worked great for the MVP proof of concepts but then we changed it to Next.js for the landings and the web because we wanted to have a server and other features. We had some problems with the setup. We had slow pages on a slow connection to the website. If there was an error on one of our API calls to get data to render on the page, they would crash and show a suspected error. Also, forms were way too complex to validate and run to errors. We have some unnecessary duplication of code. Also sharding code in get server-side props function is too complex, because you need to grab it on high-order functions.

So we decided we needed to use something else, and we chose to use RemixBoot. And the reason for that is the first one, the resilience. So the resilience is how well an app can support, can keep working in case of an error. Remix doesn't make your app work all the time if there is an error, but it helps you a lot to get there or near there. With error boundaries, we can catch any unexpected error and show something to the user, like, hey, something went wrong. We are going to – we know about this now, but you can contact support if you need more help. With Cache Boundaries, we can show any known errors. The user goes to a charity and that charity doesn't exist, that's not fun. Or a user provider doesn't exist, it's not fun. They want to do something that needs more money on their account, we can return a missing payment cell or UI with Cache Boundaries. We also can use Progressive Enhancement. If a JS fails to load for any reason, the application is mostly usable. At least they can access the content. Another reason was form ammutation.

2. Simplifying Form Submission and Migration to Remix

Short description:

With Remix, the process of form submission, authorization, and validation becomes much simpler. The action call is in the same file as the form, making it easier to understand the flow of the application. Remix also offers conventions and separation of concerns, allowing for easier refactoring and avoiding code duplication. Additionally, the migration to Remix was done by running Remix and Next together, utilizing the express server to run both apps in a single process.

With the previous stack, we had to do a lot of things to do ammutation like create a form, a state for input, serialize that, send it in a fetch to an API, create the API in another file, send authorize, validate data and send it to our Rails API. With Remix, this becomes way simpler. We just render the form, export in action on the same file the form lives in. We can do the service and launch authorization and validation of the data before sending it to Rails and it works. It's way simpler.

Action call is also on the same file of the form. That's a great benefit for being able to know what's happening in a route. We go to a route, so there is a form. We go to the action. We know what's that form doing. We can also add validation with solve. Multi-step forms can work with JavaScript way simpler and with the back button, something we had used before. And we can use the user transition to enhance the experience of the users. And so from loading states to optimistic UIs.

Conventions and separation of concerns is also another reason we choose Remix. Roots files help a lot with refactoring. We can just remove a root file and remove with that the action, the loader, the component, links, everything. We need nested roots also help avoid duplication. We don't need to move code to another file and import it into many files like headers, across roots. We just create a pattern, layout root, and put inside everything that needs that header and that's it. And the component then lives in the root. Loaders and actions also use standards. And we spend less time on Remix docs and more time on Mozilla Developer Network docs. Also means hiring and teaching the stack is simpler. We hired someone who didn't know Remix and she learned Remix for the interview and passed the interview and other developers focusing on backend were able to learn Remix super fast, like a day or less than a day and started using it.

Now, how we migrated to Remix. We know we wanted to use Remix, but we still had this big Next application. What we did, the first thing was, we can migrate everything at once, so we decided to run Remix and Next together. To do this, we take advantage that Remix can be plugged in an express server and Next can also be plugged in an express server. We use express to run both processes, both apps in a single process.

3. Using Next and Remix Together

Short description:

We send requests to Next for APIs and assets, but everything else goes to Remix. We handle errors from Next initially, but eventually switched to sending all requests to Remix. We shared the authentication state across apps using a shared sessionStore. During the migration, we used full page navigation for links and forms. Now, Remix serves as the backend for our frontend, aggregating data from multiple API endpoints. Loaders handle data fetching, filtering, and transformation, simplifying our React components.

We send everything from a slash underscore Next slash whatever, to Next, so it can handle APIs and sending assets. We use express static for the public build, the public folder and the public build folder for Remix. We send a specific request to Remix and the rest of the requests to Next initially. This means we had to handle errors from Next at the beginning but eventually we switched and we started to send all requests to Remix by default and only specific requests to NextJS. We did this when we moved all our cache, all routes, that is the user profile slash whatever is a user profile. So, we moved that to Remix and that allowed us to do the switch and say, okay, from now on everything goes to Remix except this path, like API route from Next or some routes that we were still serving with HTML for Next.

We also had to share the authentication state because moving from one app to another for the user should have been the same. The user didn't know if the route was using Remix or Next except probably because it was faster. So we created a mixout. We changed the Out0 Next.js SDK to RemixOut with the Out0 strategy and then we realized that the session storage object from Remix is actually not tied in any way to Remix. We can use it in Next. You can install that part in the next app and have it working. So there you can see how you can pass the res.headers.cookie value to sessionStore.getSession and get the session, and then commit the session and get the string to send to res.setHeader. And in the same way we can do with Remix. So we shared this sessionStore to be able to share the authentication state across apps.

Finally, another issue we had was Remix links pointing to next apps while we're trying to do a client-side navigation, and that failed because the root didn't exist on Remix yet. And the same happening in the other way. Next links pointing to Remix tried to do the same, trying to load the following route the user was navigating to using next, but that didn't exist anymore. So the solution was, for the time the migration was still happening, we added reload document in Remix components and avoided using next link component. So every link was a full page navigation. Same with forms. Every form was causing a full page navigation even if the link or the form was pointing to a route we already know was using Remix. So we set the baseline, basically everything used full page navigation, and after the migration was ready, and we know there was not any more Next.js code running in production, we removed all reload documents and they all become a single page application packet.

Now how we use Remix at Daffin. First, Remix is a backend for frontend for us. The user interacts only with Remix, there is no way the user see a request to Rails API, just send it to Remix and from there to Rails, and we use this to aggregate data from multiple endpoints of our API. Server side, on the loaders, we can just fetch multiple endpoints. We get the data and filter it also on the server side, and we can transform data. For example, we convert date objects to localizing messages, or numbers to localize the string amount. And because of this, because most of these things we used to do on the UI are now in the loaders, our React components are simpler because they just focus on the UI, they focus on get the data from use loader data and show it to the user, and a few specific states or efforts for integration mostly with third party services.

4. Root File Structure and Component Coupling

Short description:

We have the idea of a root file containing everything needed, avoiding coupling components with data. Shared components receive data from props and find exactly what they need. Complex components are tied to the root and reside in the root itself.

Also, we have this idea of a root file has to contain everything they need, at least as much as possible. We only move components to the apps slash components folder if they are truly shared, like if we use it on almost every root or at least more than three. So, we know before moving a component to this folder that the component is actually going to be used in a lot of parts is not tied to the data. This allows simple refactoring of roots because if everything is in the root, we can just remove the root and remove all the related code. There is no way in where we remove a root and we left the component in the component because we are not sure if something else is using it. We also avoid coupling components with data. Because all of our shared components just receive data from props and not from the data. And they will find exactly what they need. And a lot of simple components because they are not, if they are complex components, they are usually tied to what the root is specifically doing and do sleep in the root itself.

5. Query Functions, Mutations, and Error Handling

Short description:

We have the concept of query functions in Remix, which are async functions that fetch data from the API and handle filtering, parsing, and transformation. These functions are placed at the end of the loader code. Errors in important queries cause the main catch to fail inside the loader, while others fail silently. We handle mutations in a similar way, validating form data with a SOD schema and sending it to the API. We return JSON responses with success or error statuses accordingly. We also handle UI errors by moving parts of the UI to separate components and rendering them based on the data availability. Additionally, we define custom conventions using the handle export and have a type-safe API client to ensure type safety when fetching from our own API.

We also have this idea of a query function. So this is how a loader looks like in Remix, the initial code where we authenticate the user, create API clients, instances, and things like that are expected to not fail. So they fail, we want the error boundary to render. We then try to catch everything that is expected that may fail. If there is an error, we capture the exception and send it to Sentry. And we also return or true a response to let the user know something went wrong. We true when the word root is bad, and we return when we can still render part of it.

And the query functions are these get something functions, async functions we have inside the loader at the end of the loader code where we fetch data from the API. We also filter it or parse or transform it there so the word code is in a single function. And inside this function, we can try catch the request. So this means if you get donation fails, in this case, we want the root to fail because if you are seeing a specific donation, nothing makes sense without that data. But if you get charities fail, we can return null and catch the exception to center. So we know something failed, but for the user what's going to happen is the list of charities disappears from the UI. So important queries cause the main catch to fail inside the loader but the others fail silently.

We do something similar with mutation. So mutation is again a function we put at the bottom of the action where we created the SOD schema, we validate the form data with the SOD schema and send it to the API. And if it's a success, we can return it JSON with the status success or a red or whatever we need. And if there is a random error, we check if it's a SOD error, we return in JSON with a status error and the list of error messages. If it's not a SOD error, it means something else failed, we got your reception and show a message usually telling the user to contact support that we already know of the error.

We also handle errors on the UI this way, so we have the cache bound that in case the wall loader failed, the wall root failed. But we move a part of the UI from the root to different components, and inside those components that live in the same file as the root, we call user.data, get the data we need, and render it, and if the data is null, we just return null to hide that part of the interface. We also define custom conventions using the handle export. Most of this custom conventions are no part of Remick Utils, things like Hydrate scripts, and Dynamic Links and Structured Data are part of Remick Utils, and we have this global type, Daffy.handle, that we can attach to our handle export and define what the root can set there. So our roots define if they need or not javascript, if they need external scripts, it can load it that way. We also extend this convention for different layouts, so the boarding handle have different conventions attached to the global ones. Same with layout on the app handle and you can see for example in the app handle we have this aside component that receives the loader data props and this allows the app layout root to render the sidebar with a side, but render it in a larger layout with the root specific children routes inside it in another place. So we can use this as a way to define slots or then selling it in some way for different parts of the layout. We also have a type safe API client so we don't use something like Prisma because we fetch an API. So in order to have type safety when we fetch from our own API we define a schema with sort, export, infer the type from there, and when we fetch the API we just parse the data as it comes to from sort with sort, and let it fail if there is an error. So if there is an error there we know something changed on the API that wasn't expected to change and we can review we review the error and check what happened and if not and if something worked correctly the return value from the API method is going to be correctly typed with the schema donation type.

6. Resource Routes and Remix Libraries

Short description:

We use resource routes to generate PDFs and open graph images. The React PDF library is used to render PDFs with localization support from Y18-next. For open graph images, we render SVGs and transform them as needed. RemixAdafi has contributed to the Remix community, leading to the creation of RemixUtils, RemixOut, and RemixY18next. These libraries provide various features and integrations. Thank you for joining me!

We also use a lot of resource routes for different things. We for example generate PDF because we have to give users report about the donation for tax purposes. So we use a React PDF library to render a React inside a resource route and generate a PDF. We localize the PDF using Y18-next library and then after we render the PDF, we send a response using the PDF helper from RemixUtils and that way we can generate a dynamic PDF with React.

We also use resource routes for open graph images. In the same way we just get params from the URL search params, we use React to render an SVG as a string. If the user expects an SVG response, we just return it. If not, we can transform the SVG to something else like a PNG, JPG, WebP, etc, and save the file with a content type header. This way we can just optimize images for OpenGraph as we need it.

RemixAdafi has contributed to the Remix community because a lot of things were extracted from there. RemixUtils exists. Thanks to RemixAdafi, we use client-only useHydrated, useGlobalPendingState, and more things come from internal functions and components. We use it in Adafi and then we extract it to RemixUtils. RemixOut was born because the need to implement Auth0 authentication. At Dafi, I published the first draft with my initial intent and then from the proof of concept we have from Remix. We created RemixOut version 1 with Auth0 strategy that was later extracted to another package and the library grow with the community. RemixY18next also exists thanks to Dafi using Remix because we need to localize the app. The app is actually English only but we support localization already. We choose Y18next translated from them. My initial implementation was published as an article. Then we extracted the library with the output code. We used it as Y18next from Dafi proof of concept. That was how the library was created and the community started to contribute. That's it.

Thanks for joining me. Sergio, how are you today? I'm fine. Oh, good. Well, that was an amazing talk. Thank you so much. We want to jump over to Slido and see what the results were of the poll.

QnA

Migrating Existing Projects to Remix

Short description:

We asked the audience if they have migrated an existing project to Remix. 53% said no, but they would like to, while 38% said yes. Only 6% have no plans to migrate. It's great to see that many people are planning to migrate. The favorite feature of Remix mentioned by the audience is mutations, which is considered the hardest part of any application. The migration process took around nine months, starting in January and completing in September. The migration was done incrementally, taking advantage of redesign opportunities and empty workspaces.

Let me get my screen over to that. We asked, have you migrated an existing project to REmix? And 53% of people said no, they haven't migrated yet, but they would like to. And then some people said yes, about 38%. And then nobody, no, I don't have plans to about 6%. So very little don't want to migrate at all. But that's pretty cool that a lot of people are planning to, right?

Yeah, yeah. You should, you should keep it up. So hopefully this talk helped them get the motivation to go ahead and start migrating their apps over. And don't forget that you can always join us slido.com and 1-818 is the code if you want to answer on any of these polls that we're doing.

All right, let's jump back into the Q&A. So we have a question that we asked the audience in the beginning and we're asking every speaker now, we would like to know what is your favorite feature of Remix? I think it's the same. The majority is mutations. Yeah. It's the hardest part in any application. It's easy to read data. It's hard to mutate it correctly and revalidate. And all the things Remix does around that, it's super easy with actions and forms. Yeah, I think we might get back into that in a question later. But that is a very popular answer to that question is mutations. We hear loaders and actions a lot. And so I think that is a very popular and requested feature also.

So how long did it actually take you to do the migration that you talked about? We started in January of this year. And if I'm not wrong with my memory, we completed it by September. So it was around nine months to do the word migration while we keep adding more features. Okay. So how did that process look like for you then with taking that time? Were you able to incrementally switch over and migrate your application? Yeah. Well, we do that. Because we are a small startup, we are still figuring out a lot of things on our product. So when we redesigned things to improve how they work, we used that opportunity to move them to Remix and build a new version, the Rendering Remix. And then when we had some empty spaces of work, we didn't have anything else to do for a few days, use that time to migrate other things that were not so important that we are not touching so much, but we have in Nexon, so we migrate them to Remix.

Mixing Next.js and Remix

Short description:

To mix Next.js and Remix together, we used Express to run both applications on the same server. We shared the authentication state and leveraged Remix's UI patterns. Instead of heavy client-side data fetching, we used GetServerSideProps and easily transitioned to Remix's Loader. The code logic remained the same, with only minor adjustments to reading requests and sending responses.

What are some of the processes you used to do those incremental changes? Because you move from Next.js to Remix, which have two very different APIs. So how are you able to kind of mix those together? Well, what we did was to use Express to run both applications on the same server using one process, and then we had to share the authentication state after we figured that moving things was basically reveal everything from the ground in Remix, maybe reusing part of the UI. Luckily for us, because I really like a lot of the Remix patterns, we didn't do too much things client side, like data fetching, so we used GetServerSideProps. Moving from GetServerSideProps to Loader is not that hard as if you used another library for querying data client side. Actually, that's kind of an interesting point, that you could just almost like find and replace your GetServerSideProps with Loader and get your data that you need for your route. I like that. Yeah, a lot of code is the same. You just need to change how to read things from the request and how to send things in the response. But the rest of the code, the actual logic you use there is the same. Awesome. Well, I guess that would make it a little bit easier.

Benefits of Migrating to Remix

Short description:

Migrating to Remix has resulted in smaller JavaScript files, faster navigation, and the ability to preload data and assets. Remix's router allows for incremental loading of necessary components. Progressive enhancement in Remix ensures that the app works without JavaScript and enhances it for users with JavaScript. This is particularly important for our financial application. We use links and forms in Remix to maintain functionality even without JavaScript. Convincing our team to migrate to Remix was a process that started when we realized the need for a better solution than React routers set up by Rails.

So what are some of the benefits of migrating from React that you've seen or from Remix that you've seen in your application? We have way smaller JavaScript files in the client. So our application feels faster when you are navigating with this link preload feature. Remix can preload not only the code as it does, it also preloads the data and other assets. So if we have images that we preloaded, it can fetch them, and if we have a loader on the next route, we can also start prefetching it before the user actually clicks a link and navigate faster to the other page, even if we are doing service rendering all the time.

Yeah. So maybe it has to do with just the way that the router in Remix is set up and is able to incrementally load some of those things that you need. Yeah. Yeah, awesome.

All right, when making the switch from Next.js to Remix, you mentioned that progressive enhancement is also one of the reasons. Can you explain more about that and how Remix handles the progressive enhancement? Yeah. For those who don't know, the progressive enhancement is this idea that your app works without JavaScript and then you enhance it so that it works better for people with JavaScript that can be most of the users, usually. In our case, we work with money and if the app doesn't work, it's worrying for the users, right? You have my money there. Even if you already donated, when you give the money to us, it's really your money. And using progressive enhancement means if the app, if there is an error on our client-side JavaScript, you can still see and use it. A lot of things, not everything, but a lot of things still work with the JavaScript, like forms and things like that. So most of the app can be used even without JavaScript. And that's how Progressive Enhancement is helping us. And this can be done in Remix because, you know, Remix use link to navigate and link is an anchor and use the form component, which is an app. And everything keeps working that way.

That actually makes a lot of sense too, because you're working with that money. You want to give that user feedback on what they're doing in your application. So you need to have that Progressive Enhancement. It's like this is working behind the scenes, but you can't see it until it's actually finished. But we're going to progressively show you an optimistic update in hopes that that data is going to come back, right? Yeah. Awesome.

So we have a couple of audience questions now. Chris said, did you have any issues with convincing your team to migrate to Remix? I think you said from Next.js, and how do you go about that at the start? I started thinking of convincing the team to use Remix. We were just starting the front-end. We built an original proof of concept with React routers being set up by Rails in your route, and then we needed to move to something that was better.

Migrating to Remix and Monorepo Structure

Short description:

We initially built a proof of concept with React routers, but eventually decided to migrate to Remix due to performance issues. The CTO was initially hesitant to use Remix because it was a paid framework and might make hiring more difficult. However, after trying Remix during the holiday season, the CTO was convinced of its benefits. Our application is not a monorepo, but rather a single folder containing all the frontend code.

We built an original proof of concept with React routers being set up by Rails in your route, and then we needed to move to something that was better. At that moment, Remix was still paid. My CTO was not convinced to use it because it's paid, it means not everyone is going to know. It is going to be harder to hire someone who knows the framework. We started using Next because of that. I contributed, one of my co-workers is one of the original authors of NextJS. We started with Next, then we decided to migrate to Remix because we started to have issues with the performance of the application. The frontend landing pages were great, but what you are on the application part is not that great, especially if you don't use most things client-side, and that was what combined the CTO to try Remix. He tried it on the week between Christmas and New Year. After that, he came back from New Year and basically told me, yeah Remix is great. This is my list of things. While I like it, we are going to migrate to our code, to do it. It's like if they don't want to switch over to Remix, just show them, just like make them try it, right? Yeah, I think that's the best way to combine someone to use it. Just try it, show it. Awesome, so is your app a monorepo? It's not a monorepo, well, we have a monorepo, but my application it has the front end is one folder that has everything from the front end. There's no share with other parts of the monorepo, because it's other languages.

Monorepo Importing and Team Size

Short description:

In regards to monorepo, we haven't experienced difficulties importing local component packages into Remix. We have all the code in the same application. We have a fairly small team of 8 people working on the migrated codebase. It's easy to convince people to migrate by using their terms and phrasing it differently. Remix is easy to learn as it uses the web platform and JavaScript. Hiring someone to work on Remix is easier than hiring someone for other frameworks.

Okay, we have a question that's in regards to a monorepo, so if you don't know it, no worries, but I just wanted to ask it in case. Have you experienced difficulties importing local component packages into Remix in a monorepo environment? Yeah, we didn't try it, we just have all the code in the same application. Yeah, awesome. So I don't have experience with that either.

Okay, let's do one last question from Adrian. How many people are working on the code base that you migrated? Let me count it. We have 1, 2, 3, 4, 5, 6, 7, 8 people. Nice. It's a fairly small team, right? It's pretty easy to convince people. And I think that's something that I've always said is, like, if you're talking to a stakeholder or somebody who's not a developer about migrating, something like that, you want to make sure that you're using their terms and phrasing it in different ways than you would if you're talking to a developer. So I think that's another thing to think about if you're trying to convince your company to migrate over.

Yeah, also, when we started, we have four people. We hired the rest after we started immigration. And then Remix, super fast. One of them learned it for the interview in a week, like, a week in two days, something like that. That's another great point is that Remix doesn't have a lot of, like, specific Remix stuff, and it uses the web platform. So you're really just learning JavaScript for the most part. And React. I think that makes hiring someone to work on Remix easier than hiring someone to work on anything. It goes, you don't need to learn too much from, you only learn about the web itself. Yeah, awesome. Well, I think that is about all the time we have for questions. Thank you so much for answering these, Sergio, and thank you for joining us today. Thank you. All right.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

React Summit Remote Edition 2021React Summit Remote Edition 2021
33 min
Building Better Websites with Remix
Remix is a new web framework from the creators of React Router that helps you build better, faster websites through a solid understanding of web fundamentals. Remix takes care of the heavy lifting like server rendering, code splitting, prefetching, and navigation and leaves you with the fun part: building something awesome!
React Advanced Conference 2021React Advanced Conference 2021
39 min
Don't Solve Problems, Eliminate Them
Humans are natural problem solvers and we're good enough at it that we've survived over the centuries and become the dominant species of the planet. Because we're so good at it, we sometimes become problem seekers too–looking for problems we can solve. Those who most successfully accomplish their goals are the problem eliminators. Let's talk about the distinction between solving and eliminating problems with examples from inside and outside the coding world.
Remix Conf Europe 2022Remix Conf Europe 2022
23 min
Scaling Up with Remix and Micro Frontends
Do you have a large product built by many teams? Are you struggling to release often? Did your frontend turn into a massive unmaintainable monolith? If, like me, you’ve answered yes to any of those questions, this talk is for you! I’ll show you exactly how you can build a micro frontend architecture with Remix to solve those challenges.
Remix Conf Europe 2022Remix Conf Europe 2022
37 min
Full Stack Components
Remix is a web framework that gives you the simple mental model of a Multi-Page App (MPA) but the power and capabilities of a Single-Page App (SPA). One of the big challenges of SPAs is network management resulting in a great deal of indirection and buggy code. This is especially noticeable in application state which Remix completely eliminates, but it's also an issue in individual components that communicate with a single-purpose backend endpoint (like a combobox search for example).
In this talk, Kent will demonstrate how Remix enables you to build complex UI components that are connected to a backend in the simplest and most powerful way you've ever seen. Leaving you time to chill with your family or whatever else you do for fun.
JSNation Live 2021JSNation Live 2021
29 min
Making JavaScript on WebAssembly Fast
JavaScript in the browser runs many times faster than it did two decades ago. And that happened because the browser vendors spent that time working on intensive performance optimizations in their JavaScript engines.Because of this optimization work, JavaScript is now running in many places besides the browser. But there are still some environments where the JS engines can’t apply those optimizations in the right way to make things fast.We’re working to solve this, beginning a whole new wave of JavaScript optimization work. We’re improving JavaScript performance for entirely different environments, where different rules apply. And this is possible because of WebAssembly. In this talk, I'll explain how this all works and what's coming next.

Workshops on related topic

React Summit 2022React Summit 2022
136 min
Remix Fundamentals
Featured WorkshopFree
Building modern web applications is riddled with complexity And that's only if you bother to deal with the problems
Tired of wiring up onSubmit to backend APIs and making sure your client-side cache stays up-to-date? Wouldn't it be cool to be able to use the global nature of CSS to your benefit, rather than find tools or conventions to avoid or work around it? And how would you like nested layouts with intelligent and performance optimized data management that just works™?
Remix solves some of these problems, and completely eliminates the rest. You don't even have to think about server cache management or global CSS namespace clashes. It's not that Remix has APIs to avoid these problems, they simply don't exist when you're using Remix. Oh, and you don't need that huge complex graphql client when you're using Remix. They've got you covered. Ready to build faster apps faster?
At the end of this workshop, you'll know how to:- Create Remix Routes- Style Remix applications- Load data in Remix loaders- Mutate data with forms and actions
DevOps.js Conf 2024DevOps.js Conf 2024
163 min
AI on Demand: Serverless AI
Featured WorkshopFree
In this workshop, we discuss the merits of serverless architecture and how it can be applied to the AI space. We'll explore options around building serverless RAG applications for a more lambda-esque approach to AI. Next, we'll get hands on and build a sample CRUD app that allows you to store information and query it using an LLM with Workers AI, Vectorize, D1, and Cloudflare Workers.
React Summit 2023React Summit 2023
106 min
Back to the Roots With Remix
Featured Workshop
The modern web would be different without rich client-side applications supported by powerful frameworks: React, Angular, Vue, Lit, and many others. These frameworks rely on client-side JavaScript, which is their core. However, there are other approaches to rendering. One of them (quite old, by the way) is server-side rendering entirely without JavaScript. Let's find out if this is a good idea and how Remix can help us with it?
Prerequisites- Good understanding of JavaScript or TypeScript- It would help to have experience with React, Redux, Node.js and writing FrontEnd and BackEnd applications- Preinstall Node.js, npm- We prefer to use VSCode, but also cloud IDEs such as codesandbox (other IDEs are also ok)
Remix Conf Europe 2022Remix Conf Europe 2022
195 min
How to Solve Real-World Problems with Remix
Featured Workshop
- Errors? How to render and log your server and client errorsa - When to return errors vs throwb - Setup logging service like Sentry, LogRocket, and Bugsnag- Forms? How to validate and handle multi-page formsa - Use zod to validate form data in your actionb - Step through multi-page forms without losing data- Stuck? How to patch bugs or missing features in Remix so you can move ona - Use patch-package to quickly fix your Remix installb - Show tool for managing multiple patches and cherry-pick open PRs- Users? How to handle multi-tenant apps with Prismaa - Determine tenant by host or by userb - Multiple database or single database/multiple schemasc - Ensures tenant data always separate from others
Remix Conf Europe 2022Remix Conf Europe 2022
156 min
Build and Launch a personal blog using Remix and Vercel
Featured Workshop
In this workshop we will learn how to build a personal blog from scratch using Remix, TailwindCSS. The blog will be hosted on Vercel and all the content will be dynamically served from a separate GitHub repository. We will be using HTTP Caching for the blog posts.
What we want to achieve at the end of the workshop is to have a list of our blog posts displayed on the deployed version of the website, the ability to filter them and to read them individually.
Table of contents: - Setup a Remix Project with a predefined stack- Install additional dependencies- Read content from GiHub- Display Content from GitHub- Parse the content and load it within our app using mdx-bundler- Create separate blog post page to have them displayed standalone- Add filters on the initial list of blog posts
React Day Berlin 2022React Day Berlin 2022
86 min
Using CodeMirror to Build a JavaScript Editor with Linting and AutoComplete
WorkshopFree
Using a library might seem easy at first glance, but how do you choose the right library? How do you upgrade an existing one? And how do you wade through the documentation to find what you want?
In this workshop, we’ll discuss all these finer points while going through a general example of building a code editor using CodeMirror in React. All while sharing some of the nuances our team learned about using this library and some problems we encountered.