This content originally appeared on Bits and Pieces - Medium and was authored by Fernando Doglio
3 Things to Avoid When Coding with Remix
This is JavaScript town where all libraries and frameworks live. Everyone knows each other, and the minute someone new comes along, all eyes are turned on the stranger, at least until they can prove they have what it takes to live here.
Remix has provided that proof already, and people are starting to visit its home to ask for some sugar, get to know them more, understand what they do for a living and most importantly: whether they’re single or not.
However, part of the magic that makes Remix so special can also be a problem if you don’t really know how to wield it. This is why in this little article, I want to show you how you can break Remix, simply so you don’t do it on your own by accident.
What’s this magic I keep talking about?
So one of the main incredible points about Remix, is that it lets you write code without having to worry about what’s backend code, and what’s frontend code (to a point, we’ll talk about that in a minute). All you have to worry about is writing your routes, exporting your components, defining your loaders and that’s it.
The reason why you get to work like that, is because Remix takes your code, and creates proxy modules, only using what they need for each environment.
For a route like this:
Remix would only want to use the component exported on the front-end, and it would ignore the loader. So the framework would create a proxy module like this one:
Effectively ignoring the loader, which gets the data from a data source (in my case, that’s a location on the hard drive). So yeah, this new proxy module is safe to be used on the frontend without problems.
However, what would happen if suddenly, inside your module, or inside the frontend-specific functions, you add backend only code?
Let’s answer that with another example.
Keeping side effects on check
If you happen to include backend-specific code inside the code that gets exported into the frontend section, you’ll run into some trouble.
No, the universe wouldn’t collapse on itself, but Remix would just go bat s*it crazy and your build would not work.
The key here is that you have to avoid what some folks know as a “module side effect”. Essentially, you need to make sure that at the time of importing the module, no code auto executes. If you write your modules following common sense, that wouldn’t happen unless you have some debug code or strange ad-hoc logic.
That said, if you do need to add side effects, make sure those aren’t backend related. For example:
Notice line 14, I’ve added a simple console.log which in practice should not cause a problem, however, since the line is also calling a function that reads a local file using the fs module (which is 100% backend related) the framework will end up bundling the app but failing the moment this code executes. Mind you, since the code is bundled in both, the backend version and the frontend one, it’ll only fail on the latter and succeed on the former.
If you do something like this, you’ll see a similar error to this:
Now, the simple way to solve this problem, is to encapsulate all that backend-specific behavior inside the loader function, which doesn’t get exported on the frontend proxy module, like so:
The only thing I did was move the call to our readFileLocal function into the data loader. That’s all I needed, now this function will only be called from the backend logic.
Higher-order side effects
In a similar fashion to the very direct side effect we covered above, you might be tempted to use higher-order functions to change the behavior of your loader logic. It’s a clever trick to try and provide pre-checks on the request and make sure that if requirements aren’t meant, you can send act accordingly.
For example, imagine you wanted to add validation for a custom header, let’s call it x-custom-header and log an error message if it’s not present. Let’s add that code into the component I’ve been using:
Look at line 24, that’s where our problem begins. While you might consider that this is valid code, the function is being called right when the module is imported. That also causes the loader to be called both, on the backend (as it should) and on the front-end as well, because it is a module side effect.
It’s exactly the same problem as before, the framework can’t prune the checkRequireHeaders functions from the frontend code, because it gets called during the import process.
And since the loader is not meant to be executed on the frontend, you might get very unpredictable results. In my case, this is the error I see:
Instead, if you need to add this type of logic, you can still do it around the loader, just not as a side effect.
The new code has a similar effect, it now logs the error message when the header is missing, however, since it’s executed from within the loader, this will only happen on the backend. Which is what we wanted.
Careful where you put your browser-only code
Now, Remix does everything in its power to prune backend code from the frontend bundle, but it doesn’t do the same thing when it comes to removing frontend code for the backend bundle.
That’s a big problem if you’re using frontend-specific code. Remember, since it’s all JavaScript, the frontend code will try to run on the backend if you’re not careful.
And it’s not that hard to mess it up either, something as simple as:
Clearly, this is a module side effect, we have the function callMagicFunction being called as soon as the module is imported, not only that, but this code depends on the window object existing in this context. However, since Remix will try to render the component on the backend as well, and there is no window object there, you’ll see an error similar to this one:
Sadly, there is no way (yet) to make Remix remove the frontend code from the backend bundle, instead, you should write your code to make sure you’re checking if the API is available, like so:
That’s all that was needed to make it work, now that new IF statement will return false on the backend, so the side effect will not execute.
But what happens if you’re not calling that function from a module side effect, but rather from within the component? Look at the following example:
Even though I’m checking if the window object exists, the same page will have a different version rendered on the backend than on the frontend and while that will still work fine, you’ll see an error on the browser’s console:
So the key is to make sure you execute this code only on the backend through the use of React’s useEffect hook:
Through the use of this hook, which you’ll have to import from the ‘react’ module, you’ll ensure that this code is only executed on the frontend. Mind you, the code is still part of the bundle, and it’ll be there for the backend, but at least it will not be executed.
While Remix tries to hide the complexity around the development of a full stack application, as you’ve seen here, there are some gotchas you have to consider when writing and structuring your code.
Keep an eye open and remember these details and you’ll be fine!
Have you tried Remix already? What are your thoughts on it?
Build applications differently
OSS Tools like Bit offer a new paradigm for building modern apps.
Instead of developing monolithic projects, you first build independent components. Then, you compose your components together to build as many applications as you like. This isn’t just a faster way to build, it’s also much more scalable and helps to standardize development.
It’s fun, give it a try →
Learn more
- Building a React Component Library — The Right Way
- 7 Tools for Faster Frontend Development in 2022
- Microservices are Dead — Long Live Miniservices
Breaking Remix JS: A ‘How Not To’ Guide was originally published in Bits and Pieces on Medium, where people are continuing the conversation by highlighting and responding to this story.
This content originally appeared on Bits and Pieces - Medium and was authored by Fernando Doglio
Fernando Doglio | Sciencx (2022-03-02T09:23:10+00:00) Breaking Remix JS: A ‘How Not To’ Guide. Retrieved from https://www.scien.cx/2022/03/02/breaking-remix-js-a-how-not-to-guide/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.