This post will describe the development process/history (it's just me rambling really) used for creating IP Visualizer. You can try live demo here.
Want to see the code? It's here
At the time I'm writing this the live version is still running on janky code as i have not updated it yet, but that's OK, code might be janky but it does not mean it's broken or non working.
It all began with the idea that I wanted to use the GEORADIUS feature in Redis to fetch all IP-addresses in a given radius and visualize them on a map.
First thing to deal with is getting the data (using the GeoLite2 free geolocation data from MaxMind) into Redis so can actually query it.
This was easier said than done. I used the node-redis lib and well, all the geo stuff in this lib are broken af (mildly speaking).
I eventually found the sendCommand() function that can be used to send raw commands to Redis and yeah, finally able to load some data and get things going.
Created a super simple server in node that used web-sockets for communication with front-end. Created a new Svelte app and imported Mapbox GL.
My first test was using regular mapbox pin markers, yeah, dont try that, putting thousands or more html-based markers will kill the browser rather fast, haha.. i kind of expected that to happen.
I clearly needed a different way of to visualize things, enter deck.gl. I have used deck.gl once before some year ago, but only for a super simple project. That project was using React and not the using the full Mapbox GL library. Had already taken the decision to not use React for this project simply cuz I don't like writing React, my React skills sux and have not used for so long I do not remember much of it.
So did a lot of reading and checking examples of how can use Deck.gl with Mapbox GL and managed to get some prototype code going.
Next I needed some way of drawing a circle with the mouse and get it transferred to the map canvas. Started with some code i used in a different project, but that on was made for drawing boxes. Took some head scratching and math to get all the junk right and correct for drawing circle instead.
At this point I have a working prototype. All code is just dumped in one Svelte file. It's a mess, loads of code, lots of scrolling and hard to keep track of all the stuff.
Now I start refactor things. All the drawing of circle logic gets extracted into a class. I do get into one problem, how should i signal the main app that the drawing of circle is complete and send over the needed data. I end up just emitting a custom event.
Was curios about the performance difference between just using a regular api endpoint for sending the data versus web-sockets. As I had suspected using web-sockets where a bit slower (and there is also some really janky behavior when using Vite with Svelte and hot module reloading, it reconnects the old socket and also create a new connection leading to sending and receiving the data same amount of times that the HMT has run so when developing need to remember to do a full page refresh).
So yeah, I scrapped all the sockets junk and just used a regular endpoint on the server instead.
Did some more refactoring and broke out all the Deck.gl layer logic into it's own Javascript file. Same problem as before arose, how to do the signaling, the solution was the same as before, just emit some custom events and listen for them in the main app file.
I did also replaced Mapbox GL with MapLibre because even if not using the Mapbox tiles Mapbox now requires you to have an API-key. This I don't like and is the sole reason I made the switch.
At this point I have a working app, with logic being a bit more separated. It's rather janky and I spend some time ironing out all the bugs but I am not really pleased with it.
Do you remember the Vite issue with HMT and web-sockets I told you about before, yeah, had the same issue when it comes to emitted events. When HMT kicks in on any change in the code it will resend the old events. Not optimal and only an issue in development.
At this point I have two options! Embrace the jankiness and call the project done or do a massive rewrite of the code into how i wished it would be.
If this would have been just another of my hobby projects I would just embraced the jankiness because the code works and I would probably never touch it again after it has been deployed.
I thought about it for a while before deciding I should try to make it into what I wanted.
First I dealt with the mouse handling of drawing the circle. Scrap the whole class junk and make an object approach and just make a function, much cleaner and less code.
The signaling problem still exist so I got rid off event-emitting and use promises instead. That way can just await the promise in the top-level of the app.
Next thing to deal with is the logic for deck.gl and the layers and control stuff.
Created a new Svelte component with the box for controlling the layers. All logic for layers now goes in here and are cleaned up and simplified and at the same time making it easy to add additional deck.gl properties that can be controlled, no separate Javascript file for handling layer stuff, just let the layer controller be responsible of it all. This means I now also do not need to care about signaling, no more emitting of custom events.
Well folks, that was the story about how I coded some really janky stuff and then transformed it into something a bit less janky.
This post has just been me, from memory rambling about the process I went through. Don't mind the langue mistakes, I'm not a native speaker or writer of it. ;)
The main takeaway I guess is you should really take some time to do some proper planning before diving in and starting to code.
Some times this is not easy though, especially if not sure how to do things cuz have no previous experience with it.
Like me, the Svelte stuff could probably be a lot better but I am a noob when it comes to Svelte.
The server code on the other hand did not give me much problems, have done API's with Node and Express before and yeah, it did not need any major refactoring.
The only thing that was new for me to implement was rate limiting (using Redis store) that works when running the server in clustered mode but it was rather straight forward to get it working.
Do you embrace the jankiness?
Top comments (0)