ยปTitle
-Text
diff --git a/404.html b/404.html index 2a9260e..9a2fb13 100644 --- a/404.html +++ b/404.html @@ -1,4 +1,4 @@ -
Page not found
Page not found
Text
This content is a work in progress.
I will also write a blog post about the JSConf that happened in the following two days where Iโll also talk about Berlin and the venue to give you a real insider perspective on the conference so that you can properly decide whether or not you will attend it next year.
I will also write a blog post about the JSConf that happened in the following two days where Iโll also talk about Berlin and the venue to give you a real insider perspective on the conference so that you can properly decide whether or not you will attend it next year.
See you soon.
See you soon.
Now you can go ahead and remove all those 100 characters long relative imports at the beginning of your JavaScript files.
Now you can go ahead and remove all those 100 characters long relative imports at the beginning of your JavaScript files.
I might have spent one or two days trying to figure out how to bring all these pieces together, but having done it, believe that it increased my productivity in ways that by far compensate the invested time. I hope you find this article useful especially if it saves you one day of trouble trying to figure out the right configs.
I might have spent one or two days trying to figure out how to bring all these pieces together, but having done it, believe that it increased my productivity in ways that by far compensate the invested time. I hope you find this article useful especially if it saves you one day of trouble trying to figure out the right configs.
Generally speaking, I would say everybody loves the destructuring assignment, and for good reasons. Next, I list some of the amazing things one can achieve with destructuring in JavaScript.
+Set
)The most significant dilemma of destructuring itโs related with the fact that relies on properties of nested structures that can only be evaluated at runtime, let me give you an example.
+ +On the other hand, if you write this without destructuring, you wonโt make assumptions on the user, you can double check whether the given user is valid.
+ +Just a note, for you to be conscious that as in default assignment default parameters the null
value itโs not considered false, thus you canโt fall back to some default value in destructuring a property whose value is null
.
Every feature above mentioned exists for you to use, but we should find a balance (as in everything else in life). Below I list a few guidelines/rules that will help you find the balance when using destructuring.
+ +source: https://imgflip.com/tag/fat+cat+balance
+You might have noticed some previous warning sings (โ ๏ธ) in some of the listed usages of destructuring. I left those signs there because I consider those use cases potentially harmful.
+snake_case
it uses now camelCase
just because it made more sense from an aesthetic point of view. Now your marvelous single page application is burning and falling into pieces because you were unsafely accessing this property when you could have protected yourself against it.Manual testing of any software itโs a vital activity to ensure its quality and long-term stability. Together with their coding activities, developers test their code changes to understand if they produce the desired outcome without breaking any existing software functionality. So far, so good.
+Manual testing of any software itโs a vital activity to ensure its quality and long-term stability. Together with their coding activities, developers test their code changes to understand if they produce the desired outcome without breaking any existing software functionality. So far, so good.
Today Iโm writing a few points on why developers are bad at manual testing their own code changes, especially at detecting unwanted side-effects in areas of the software often unrelated to the modified parts.
Iโm writing because, at this point in time, I have experienced two very different setups towards software testing:
See ya ๐
This article was originally published by LogRocket. You can checkout the original post here.
+With the introduction of React Hooks, the amount of shareable code within React codebases has exploded. Because Hooks are thin APIs on top of React, developers can collaborate by attaching reusable behavior to components and segregating these behaviors into smaller modules.
+While this is similar to how JavaScript developers abstract business logic away in vanilla JavaScript modules, Hooks provide more than pure JavaScript functions. Instead of taking data in and out, developers can stretch the spectrum of possibilities of what can happen inside a Hook.
+For instance, developers can:
+In this post weโll explore the latter possibility. As a case study, weโll abstract the MutationObserver
API in a custom React Hook, demonstrating how we can build robust, shareable pieces of logic in a React codebase.
Weโll create a dynamic label that updates itself to indicate how many items we have in a list. Instead of using the provided React state array of elements, weโll use the MutationObserver API to detect added elements and update the label accordingly.
+ +source: https://blog.logrocket.com/guide-to-custom-react-hooks-with-mutationobserver/
+The following code is a simple component that renders our list. It also updates a counter value that represents the number of fruits currently in the list:
+ +We want to trigger a callback function whenever our list
element is mutated. Within the callback we refer to, the elementโs children give us the number of elements in the list.
useMutationObservable
custom HookLetโs look at the integration point:
+ +The above useMutationObservable
custom Hook abstracts the necessary operations to observe changes on the element passed as the first parameter. It then runs the callback passed as the second parameter whenever the target element changes.
Now, letโs implement our useMutationObservable
custom Hook.
In the Hook, there are a number of boilerplate operations to understand. First, we must provide a set of options that comply with the MutationObserver
API.
Once a MutationObserver
instance is created, we must call observe
to listen for changes in the targeted DOM element.
When we no longer need to listen to the changes, we must call disconnect
on the observer to clean up our subscription. This must happen when the App
component unmounts:
All the above work, including initializing the MutationObserver
with the right parameters, observing changes with the call to observer.observe
, and cleaning up with observer.disconnect
, are abstracted away from the client.
Not only do we export functionality, but we also clean up by hooking into the React componentsโ lifecycle and by leveraging cleanup callbacks on effect Hooks to tear down the MutationObserver
instance.
Now that we have a functional and basic version of our Hook, we can think about improving its quality by iterating on its API and enhancing the developer experience around this shareable piece of code.
+One important aspect when designing custom React Hooks is input validation. We must be able to communicate to developers when things are not running smoothly or a certain use case is hitting an edge case.
+Usually, development logs help developers understand unfamiliar code to adjust their implementation. Likewise, we can enhance the above implementation by adding runtime checks and comprehensive warning logs to validate and communicate issues to other developers:
+ +In this example, weโre checking that a callback is passed as a second argument. This API check at runtime can easily alert the developer that something is wrong on the caller side.
+We can also see whether the provided DOM element is invalid with an erroneous value provided to the Hook at runtime or not. These are logged together to inform us to quickly resolve the issue.
+And, if observe
throws an error, we can catch and report it. We must avoid breaking the JavaScript runtime flow as much as possible, so by catching the error, we can choose to either log it or report it depending on the environment.
If we want to add more capabilities to our Hook, we should do this in a retro-compatible fashion, such as an opt-in capability that has little or no friction towards its adoption.
+Letโs look at how we can optionally debounce the provided callback function so callers can specify an interval of time when no other changes in the target element trigger. This runs the callback once rather than running the same amount of times the element or its children mutated:
+ +This is handy if we must run a heavy operation, such as triggering a web request, ensuring it runs the minimum number of times possible.
+Our debounceTime
option can now pass into our custom Hook. If a value bigger than 0
passes to MutationObservable
, the callback delays accordingly.
With a simple configuration exposed in our Hook API, we allow other developers to debounce their callbacks which can result in a more performant implementation given that we might drastically reduce the number of times the callback code gets executed.
+Of course, we can always debounce the callback on the client side, but this way we enrich our API and make the caller-side implementation smaller and declarative.
+Testing is an essential part of developing any kind of shared capability. It helps us ensure a certain level of quality for generic APIs when they are heavily contributed to and shared.
+The guide to testing React Hooks has expansive detail around testing that can be implemented into this tutorial.
+Documentation can level up the quality of custom Hooks and make it developer-friendly.
+But even when writing plain JavaScript, JSDoc documentation can be written for custom hook APIs to ensure the Hook passes the right message to developers.
+Letโs focus on the useMutationObservable
function declaration and how to add formatted JSDoc documentation to it:
Writing this is not only useful for documentation, but it also leverages IntelliSense capabilities that autocomplete Hook usage and provide spot information for the Hookโs parameters. This saves developers a few seconds per usage, potentially adding up to hours wasted on reading through the code and trying to understand it.
+With different kinds of custom Hooks we can implement, we see how they integrate extrinsic APIs into the React world. Itโs easy to integrate state management within Hooks and run effects based on inputs from components using the Hook.
+Remember that to build quality Hooks, itโs important to:
+debounceTime
exampleYou can check the full implementation of the custom React hook here.
This part of the series itโs all about getting your hands dirty! Part 3 is a tutorial on core techniques to build an application with reactive streams using RxJS.
+Weโre going to start with a small refresher from the previous article, implementing a click event handler with RxJS. Next, weโll have a brief overview of RxJS, followed by the main challenge of building a small animated game the reactive way.
+Hereโs how a usual JavaScript event handler function looks like.
+ + +In the above code, weโre incrementing counter
that is global and logging its value each time we update it.
Usually, we donโt increment globals or console.log
directly in real-life apps, but we do have other side-effects in place (like updating something else in the UI, triggering a web request, firing an animation, etc.). You can always organize your code to split concerns, but it seems the event handler is already doing two very distinct things, and weโre barely getting started.
Letโs take a look at how this looks like in the reactive world, with RxJS. Hereโs how you should visualize and implement a stream of click events.
+ +Note: e stands for event and itโs the value pushed to the stream at each click in the button element, just like you would have an event argument in the typical onClick callback (event handler) at each click.
+ +A few things to notice here:
+subscribe
is a must! Without subscribing to our stream, nothing would ever happen.$
is just a common (non-standard) notation to identify streams in your code - totally optionally, no need to follow.Opposite to the click event handler, you can subscribe to the stream of clicks as many times as you want and split all kinds of different tasks into separate subscriptions that share the same event listener! Attaching event handlers to the DOM is costly especially due to the event attaching phase that happens at page load (onload
or DOMContentReady
events) a busy period for modern web applications - paraphrased from โHigh Performance JavaScriptโ, book by Nicholas C. Zakas.
In a way, things are opening up, you get a more flexible model to organize your code, compared to the classic event handler callback.
+++Anything can be a stream, remember that, let it be the cornerstone of your reactive thinking.
+
This should get you warmed up for the real challenge later in the article. Before that, thereโs something I want to mention about the RxJS library.
+I would highly recommend you later to go through the RxJS official docs overview; it complements a few concepts Iโve covered in the previous article giving you a more mature view into the fundamentals. But for now, I want to focus on two things only: creating streams and manipulating them. Looking at RxJS, youโll see that you can identify two big groups of โthingsโ:
+fromEvent
to transform DOM click events into an Observable, a stream that you can subscribe to.Now weโve had our refresher, we can jump into building a small animated game with RxJS, something more complex.
+The game weโre building is called โTake the cat to the partyโ, hereโs how it goes down.
+ +Weโre going to split this into 4 levels. Per each level, Iโll explain the goal weโre trying to achieve, show you how the implementation looks like, and what it does with plenty of detail. Feel free to try and code the levels yourself before checking the suggested solution. You can check out this repo if youโre willing to give it a try. The file cat-party-empty.html contains the necessary boilerplate in a single HTML file. You can just open it in the browser and start coding.
+Before we start, letโs take a look at some boilerplate code already in place.
+There are a bunch of RxJS taken from the global window
at the top (Iโm just injecting RxJS via <script>
at the top of the HTML file). Then we have our markup appended to the elementโs app
innerHTML
. Just some boilerplate, donโt bother with the detail.
The next block contains a few of the DOM elements weโll often be referring to.
+ +Finally, we introduce three streams that weโll use quite often while going through the challenge. These are the most basic building blocks of our solutions.
+ +Letโs follow a bottom-up approach. Weโll start by building some specific streams that will allow us to assemble more complex behaviors as we move along.
+Letโs start by answering the following: how do we know that an HTML element has been dropped at the party
? Weโll need to detect any drop
event that occurs in the party
element.
+ e stands for event and it's the value pushed to the stream at each drop event in the whole document!{" "} + e1, e2 and e3 have different event.target (target DOM elements). +
+ )} +/> +Cool, we now have a stream that emits a drop
event every time something is dropped in the party
, we ensure that using the filter operator.
I would like to pause and add further detail on this marble diagram. Notice that we read from top to bottom, meaning the last timeline is the only one that really matters, itโs the fine grained stream that gives us more useful values. In this case since we wonโt subscribe to drop$
directly, think of it as an auxiliary conceptual timeline which is a step towards shaping the ideal stream to tackle our task: partyDrop$
.
Another relevant detail on the marbles diagram: e1
and e2
marbles donโt make it to partyDrop$
(bottom stream). For those events,
+event.target
itโs not party
, this means the user did not drop the HTML element in the party
.
At this point we can already notice the exceptional compositional capabilities of streams and how easy it is to plug & play the smaller blocks (such as drop$
) to build higher level streams.
Next, letโs see how we can detect that the cat
is dropped at the party
.
Alright, a few things are going on here. Weโre familiar with withLatestFrom, but this time, itโs a bit more complex to perceive. Weโre looking into a stream of dragstart
events dragstart$
and asking it for the last value emitted in that stream; this is the same as saying that we want the last draggable element in the page that emitted a dragstart
event! Next, we have filter
again. Weโre going to use filter
to narrow down our stream to allow dragstart
events to pass through only if their target element is cat
! And thatโs it! We have a stream that will emit an event every time we drop the cat at the party.
In the above diagram, e1
, e2
and e3
are dragstart
events (dragstart$
stream) that might come from anywhere in the page. de
represents a drop
event at the party
. Notice how withLatestFrom
operates by bringing together the last element on dragstart$
which is e3
and with the party
element which is published to the dragend$
stream. Now because e3
event target is actually the cat
youโll get e3
pushed to our final stream catAtParty$
!
But weโre not finished just yet; we need to leverage the work weโve constructed so far to actually render the cat
in the party
. For that, we just need to subscribe to our catAtParty$
stream and do some DOM manipulations.
+ The console.log reveals the drop and dragstart events as payload for our subscription. We + also log the event.type of each individual event. +
+ )} +/> +If youโre following this point, youโll notice that although we can drag the cat perfectly, we still see the original cat
element while carrying it. We see the original cat element while dragging it.
Setting the catโs element opacity to 0 yields a more natural user experience.
+ +To achieve the same behavior we have in the above GIF, we want to toggle the cat
elementโs opacity while dragging. Yes, another side effect, we can actually simply create another subscription to take care of this.
And done with Level 1!
+I want to leave a challenge for the reader. Looking at how weโre setting the opacity value of the cat
element, could we somehow handle everything in one single subscription instead of two? I would suggest you to read the whole article and come back to this one later, you should be then able to nail it then.
window.alert
message.
+window.alert
weโll want to make sure the cat
is actually rendered at the party
.So we already have a stream that emits an event each time we drag the cat to the party, itโs called catAtParty$
. Our work here is mostly done. We just need to subscribe to it.
window.alert is triggered when we drop the cat at the party, but the cat is not rendered!
+ +Hmm.. strange, we did everything right but the window.alert
triggers before we get to actually render the cat
at the party
, what a bummer.
It seems that the DOM changes donโt kick in before we trigger the alert; thatโs because the rendering is asynchronous, and the page only gets updated later on after weโre done with executing this function and dismissing the alert. I donโt want to spend much time fixing this since I donโt have any mechanism to tell me whether the DOM node has been rendered successfully, Iโm going to code a hack and trigger the alert inside a setTimeout
that should buy us some time to correctly render the cat
element.
Great! The window.alert
is triggered after the cat element is rendered at the party!
It works. We can achieve a similar hack with RxJS without having a solution based on callbacks keeping our subscription handler clean (but still a hack!).
+ +See that delay there? Thatโs another operator. It allows you to hold the value in the stream for a determined amount of time before pushing it to the subscribers. So whatโs happening here is that instead of the Observer (subscription) being aware that we have to code a hack to trigger the alert after the cat enters the party, we shift that responsibility to the Observable, the stream is now the hacky code that is delaying the whole thing. This is super powerful, the way you can shift responsibilities and broadcast your changes to all the subscribers. Yes, all the subscribers will receive a delayed update! This can be simultaneously a gift and a wrecking footgun!
+In our markup, thereโs a GIF positioned at the top right corner. We want to show it while dragging the cat and hide it again once we drop the cat.
+We already have two streams: catDragStart$
and catDragEnd$
. We need to combine them to form a new stream. Letโs try and draw a small diagram of what that stream should look like.
+ In the image, ds symbolizes a dragstart event, and de represents a dragend event. +
+ )} +/> +Our GIF is wrapped in an HTML element whose display
attribute is set to "none"
by default. Weโll want to set it to ""
(empty string) to make it visible and back to "none"
once itโs time to hide it again. Our side effect should look something like this:
Letโs try to build a stream to feed to this function a value for display
that reflects whether the cat is being dragged or not. Our stream should remove the necessity of the imperative logic dictated by the ternary operator, weโll create values that react to changes to replace the imperative code.
First, letโs look back at our streams catDragStart$
and catDragEnd$
. When catDragStart$
emits a value, we want to set the display
to ""
. So this means we need to somehow transform our stream of events into a stream of empty strings. Each time a string is emitted, we shall pass that value onto the function that will set the display
property on the loading
element.
After you apply an operator, you transform your stream into a more refined one, ideally better suited to the task youโre trying to tackle! Youโre making every pushed value to the topmost timeline flow through a function provided in the map
operator. That function will map each value into the bottom timeline, your โfinalโ stream. If you subscribe to it now, you will receive empty strings instead of DOM events!
The same thing should happen to catDragEnd$
.
Now we have two streams, and we could just subscribe to each one of them and set the value of the "display"
property for the loading
element!
Although this works, we could further refine our streams and merge them into a single one.
+ + ( ++ A single stream becomes the source of truth for the display property value of the loading{" "} + element throughout time. +
+ )} +/> +Awesome! The merge operator gives us the power to take to streams and merge them into one so that the values of the "display"
flow through a single stream (a single source of truth). Hereโs how the code looks like.
One subscription to handle the toggling of showing/hiding the GIF.
+I feel overwhelmed by the tremendous amount of operators offered by RxJS, its API is considerably large. We could further simplify the above implementation with the operator mapTo.
+ +You get the same result as applying map
but without needing to provide a function, because weโre really not doing anything else rather than returning a hardcoded value on that inline function.
Youโve might have noticed that Iโm creating a new variable per each stream, this allows me to better explain the building blocks of each solution and map them to the diagrams. Although this helps keeping the code readable, this is not mandatory, it can be overkill per times!. Streams can be inlined. Letโs look again to a small refactor of the above solution to understand what Iโm referring to.
+ +We could drop catDragStartDisplay$
and catDragEndDisplay$
by inlining them in the merge
operator.
We need to code a new path in our game, the one where the user loses the cat isnโt dragged to the party within 5 seconds. This looks like a countdown, with a few actions tied to it:
+As in the previous levels, letโs build this incrementally. First, letโs build a countdown. To emphasize how RxJS shines here, letโs first see how we would make a countdown with native JavaScript APIs.
+ +Thatโs a rough implementation of a countdown. We need to keep track of the timer identifier in a variable to ensure we clean up after running the setInterval
provided callback the expected amount of times.
Now hereโs how you can do the same with RxJS.
+ +Letโs examine the above code ๐คฏ. This time weโre not creating a stream from an event or anything like that. Instead, we use timer from RxJS to generate a timer stream that emits a new numeric value every second.
+Now a timer emits values in ascending order (0, 1, 3, etc.). Weโll want to reverse that to display an actual countdown. To reverse the numerical value on the stream, we simply use map
. We should only give the user 5 seconds to drag the cat
to the party
. This translates to stop emitting values when we hit the mark of the 0
seconds, this is controlled by the takeWhile operator. A few evident advantages compared with the classic implementation:
secondsLeft
and intervalId
.takeWhile
and other built-in operators to be the rail guards of our business logic.setInterval
we need to worry about cleaning the interval with clearInterval
so that it does not run indefinitely!In the above image, the bottom timeline represents the stream; notice the pipe (|) at the end of the timeline indicates that the stream completes after emitting the value 1.
+A crucial aspect to notice is that youโll trigger a new timer as soon as you subscribe. This is a Cold Observable. Our countdown$
will start emitting values right away upon subscription, so we canโt just .subscribe()
Weโll have to subscribe to the countdown when the user starts dragging the cat
element.
Now remember we had a stream catDragStart$
; weโll use that to trigger our countdown. But how can we trigger a subscription to a stream from within another stream? In my opinion, this is a hard concept to comprehend.
Presenting the switchMap operator. switchMap
allows you to trigger a subscription from within a stream to a second stream. Not clear yet? Think of it this way switchMap
allows you to switch to a new observable. Ok, letโs look at our countdown implementation, now that we have this information.
Note: You might have noticed that Iโm using t => t >= 0
โgreater or equal toโ in our predicate. This is just for convenience, so that we get 0
pushed onto the stream to easily rendered it, finishing the countdown at 0
.
We're switching from one stream to another and subscribing to it immediately.
} /> +Notice the return value of switchMap
is countdown$
, this means that when a dragstart
event is emitted in catDragStart$
the following things will happen:
switchMap
operator.countdown$
and start emitting its values leaving the dragstart
event behind (because we donโt really need it for this task).Once more, as soon as a ds
(dragstart
event in the diagram) is pushed to our catDragStart$
stream, switchMap
will kick in and subscribe to our countdown$
stream, โpassing the ballโ (moving the flow of control) to the countdown$
. Weโll start to push to our subscribers the seconds left in the countdown like if we had subscribed to the countdown$
in the first place, but in this case we programmatically triggered the subscription.
Although weโre going more deep into flattening Observables in this level, weโve already seen this before in this article. If youโre thinking about withLatestFrom
from Level 1, youโre right! That operator also triggers a inner subscription.
We can now leverage countdownRunning$
to display an alert.
We have a filter to check for the second 0
; this way, weโre basically ensuring that we just emit a value when the countdown runs out. Similarly to Level 2, we have a delay
with random time to safeguard our countdown value gets rendered with 0
on the screen before we trigger the alert.
Only one thing left! If youโre following up until this point, youโre probably wondering why the counter is not reset once you stop dragging the cat. See the following GIF to understand what Iโm referring to.
+ +Hmm.. Strange the counter does not reset once we drop the cat! It should, since the 5 seconds didnโt ran out while we were dragging the cat. Letโs look at our countdown$
implementation once more.
Now, itโs pretty clear that weโre not doing anything to โstopโ the counter. Once we subscribe to countdown$
with the switchMap
operator, thereโs no stopping it, it will go on until it reaches the end, and when this happens, weโll display the alert to the user. Ideally, we would stop the counter upon any of the two following events:
catAtParty$
, once a value is pushed into this stream, you know the cat
was dropped at the party
.catDragEnd$
, each emitted value means we just dropped the cat
element. You might be thinking the first point would be enough, but remember the cat can be dropped literally anywhere on the screen. We have no guarantees that it will get dropped at the party.Meet takeUntil, this operator allows you to listen to a stream until something happens! Letโs look at the implementation of the countdown$
.
Now, what is the argument of the takeUntil
operator? takeUntil
receives a stream, once that stream emits a value, our countdown$
will stop emitting, thus canceling the timer and giving our users another chance to dragging the cat
to the party
.
But we have two streams, catDragEnd$
and catAtParty$
, can we make it one? Yes, we can! Weโve already met merge
! This operator can take multiple streams and combine into a single one, think of it as a funnel.
Letโs call this last stream cancelCountdown$
. After we declare it, we can feed it as an input to our takeUntil
operator. Hereโs the final implementation of Level 4 with cancellation.
+ In this diagram, our stream gets cancelled after the value 3 is published. The first dragend event + causes the countdownRunning$ to stop emitting values. +
+ )} +/> +You can check out the complete implementation of this challenge here.
+Here are the concepts youโve learned by building this game:
+map
, filter
.withLatestFrom
, switchMap
, and merge
.takeUntil
to achieve this.Now go out there and try to apply these concepts to build your own applications. I would be pleased to hear from you if youโve learned something here today.
+In the upcoming articles, Iโll share with you the good and bad parts of adopting reactive programming and start using RxJS in your codebase, and at last, Iโll share with you a bunch of fantastic resources to learn RxjS and reactive programming.
+The odds are high that youโre using webpack to bundle your assets. If youโre looking into an excellent way to feed environment variables to your applications, DefinePlugin might well be the answer.
+If you want to pass environment variables and use it within your JavaScript, you need to:
+webpack.DefinePlugin
.One of these days, I had this exciting challenge, I was integrating some third party that required from me to provide the current commit hash of the code to a JavaScript SDK that performs some magic in bug tracking and versioning.
+Well seemed pretty simple for me at the time. I need to take the commit hash at build time and somehow feed it to our JavaScript, whatever that means.
+In this blog post, Iโll explain step by step how to implement the following:
+++We want to log in the console the link to the GitHub history of the application +that points to the commit of the current version of the application.
+
Hereโs a step by step implementation of the previously announced challenge. I will use one of my open source pet projects on GitHub, el-conversor.
+Iโm going to do this within a npm script in the package.json. In the dev
npm script you can find the following:
So in COMMIT_HASH=\"$(git rev-parse HEAD)\"
we are basically assigning the output of the command git rev-parse HEAD
to an env variable COMMIT_HASH
.
Now, letโs dive into the webpack.config.js. Well itโs not that complicated, the only nasty detail is that even if you want to pass in a simple string, you need to wrap it with a JSON.stringify
otherwise, webpack dumps whatever text comes out of your environment variable and dump it in your JavaScript, and you get a very nasty syntax error. So letโs use the DefinePlugin:
Pro Tip: You might be wondering why the strange naming __commitHash__,
well the prefix and suffix underscores are just a way to prevent naming collisions. I hope that you donโt often use __var__
as a style to name variables in JavaScript, well I donโt, thatโs why I found this extremely unlikely to collide.
In the end, we use the environment variable. In this case to console.log
a helpful GitHub link:
You can see the final result in the image below, it logs:
+ +tl;dr SSH into your android and download the files with scp. This one works for me.
+So this afternoon, I had decided to take some time to clear my smartphone, archive some old pictures and stuff. I usually park them on an external drive. Anyways, it happens that my OnePlus 6 does not connect to my new shiny MacBook Pro.
+I tried, but Apple doesnโt make it easy to recognize other devices.
+I start browsing the Google Play store for some apps that allow me to run an SSH server on my smartphone. Quickly Iโve stumbled into this.
+Straightforward setup, as you can see in the screenshot below.
+ +Since my laptop and my smartphone are on the same network, they can communicate.
+ +Hope this tip helps you out in case you get stuck due to the usual apple mumbo jumbo.
Hope this workaround helps you as it helped me!
-โAs usual, React and Vue lead the pack, but Svelte is quickly establishing itself as a very serious contender for the front-end crown.โ, State of JS 2020: Front-end Frameworks
RxJS is known to be the go to library when it comes to programming with streams. Reactive programming is famous for making complex things easier by offering an extensive API of operators that give developers extreme power and flexibility when writing complex event-driven user interfaces.
RxJS is known to be the go to library when it comes to programming with streams. Reactive programming is famous for making complex things easier by offering an extensive API of operators that give developers extreme power and flexibility when writing complex event-driven user interfaces.
Again much of the written above is just my opinion. I hope you find useful some of the sections of this post even if you donโt work on the tech industry.
Again much of the written above is just my opinion. I hope you find useful some of the sections of this post even if you donโt work on the tech industry.
+#opinion
@@ -121,4 +121,4 @@Update Oct 12th 2024
I didnโt modify this article. I donโt fully agree with my views here anymore. The problem is not on FOSS, but rather on peoplesโ expectations and approach to FOSS. Iโm still of the opinion that FOSS is not at a fully sustainable stage. Major projects today are typically funded and itโs no longer rare to see full-time employed developers work on maintaining FOSS these days.
This is quite a dilemma for me. Iโm interested to see how all this is going pan out. My bet is on the money. Money wins, most of the time.
I have this poor habit you knowโฆ Whenever I accumulate a lot of git stashes in some repository I just get a little maniac and start cleaning everything.
+ + +I found it sometimes even funny to open the terminal and play around with some bash to delete the stashes, look:
+ +Well, it happens that today (a few hours ago actually) I just did this and regretted the moment I did because there was this huge feature that for some reason I had locally stashed and not committed
ยฏ\_(ใ)_/ยฏ.
Good news!, the commits are not actually gone until git runs garbage collection, so to check the list of commits that might still be rescued just go ahead and type:
+ +or maybe
+ +because you actually need to check whether your hash is somewhere referenced as a unreachable commit.
+Then all you need to do once you find your stash (if you donโt know the hash Iโm afraid you will have to apply stashes until you find it) is just:
+ +Here, some cool references on git stash:
+ +Notice that the references above are from Atlassian, which I highly recommend when it comes to quick search into a specific Git topic.
+And thatโs it, hope this saves you just like it saved me.
+Have a nice day.
During the past two months, Iโve been developing a side project at work, this started with me doing a simple refactor task. At the time I looked at the solution we had in place, and it was dirty, but it was necessary to skip some considerable performance penalty. Maybe it was something that we just had to learn to live withโฆ
+ +source: https://imgur.com/gallery/J3WYR
+Hell no! At the time the alternatives werenโt that promising, but soon I realized the untapped potential of doing work at build time with babeljs. Iโm very proud to present babel-plugin-cloudinary. In this trivago tech blog article, you can find all the details and motivation behind the plugin. +And by the way, if you want to know what the heck am I talking about, just take a look at the official repository of babel-plugin-cloudinary.
Letโs continue our journey on Reactive Programming. This part will highlight some of this paradigmโs key concepts for quick learning.
+You might have encountered several diagrams and explanations of the Observer pattern. For those of you that might not yet be familiar +with it, allow me to explain it with an example-based approach, a very different one than what I had at school.
+++โDefine a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.โ by sourcemaking.com
+
I didnโt get it for the first time with this definition and set me away instead of fascinating me. I thought this would be +a super tricky thing to get. But not if youโve had explained it to me with something we all know like youtube.
+Letโs look at youtube.com for a second. Iโll use it as an example to explain this patternโs two core participants: Observer and Observable.
+Your browsing on youtube and you find a new channel. You want to receive notifications anytime some new +content is published into that youtube channel, but for that, youโll need to hit the subscribe button first. You are the Observer, consuming the content posted (published) by that youtube channel. This makes the youtube channel the Observable. Another vital aspect to see is the multiplicity of this relationship. Thereโs one youtube channel to many youtube users (subscribers).
+Keeping this analogy in mind, letโs clarify a couple more concepts that complement the relationship between an Observable and its Observables.
+These concepts are more comfortable to follow when backing them up with some real-life example, but most importantly, it is good that you possess a grasp of the jargon. Itโs crucial to clearly express yourself with your peers. Last but not least, this becomes super relevant when youโre trying to Google your away around some issue.
+Now letโs get our hands on and implement the Observer pattern for our youtube case study. The idea is to use the Observer pattern to notify many youtube users when a new video is published into the channel. Weโll keep the example slim and straightforward. The main idea is to have an end-to-end perception of how the data flows in our application when using Observables. We wonโt have a UI here. We will just use console.log
to signal some events in our small program.
Letโs map the entities of the above example:
+User
is our Observer
.Channel
is our Observable
.Video
is just really the contract for the payload we sent out to subscribers, it can really be anything.I hope this example clarifies that you can leverage the Observer pattern with no additional libraries in any programming language. I found this knowledge of paramount importance to understand more complex use cases in reactive programming, specially when using libraries, we sit as a client, we go one layer of abstraction above what youโve seen in the previous example. With reactive programming libraries, you can juggle with Observables in fantastic ways effortlessly.
+As a side note, if youโre keen on learning more about the Observer pattern (or any other design pattern), I highly recommend the following resources:
+++โObservables never had a chance to shine on their own. The real win, IMO, to RxJS is the Observable type itself. Not the operators.โ from โObservables, Reactive Programming and Regretโ
+
Observables are everywhere these days. Libraries such as RxJS has an internal implementation of an Observable type, an refers to it as a first-class citizen.
+I would like to highlight the tc39 Observable proposal. Observables are a very natural fit to handle many programming challenges. I think this has become more noticeable given that people are even considering bringing it into the language (in this case JavaScript)! I believe we are blurring the line between language specification and library, but Iโm happy to see the proliferation of Observablesโ discussions.
+Reactive Programming is programming with streams of data. Streams are vessels of values pushed over time. Streams can be transformed into and combined with other streams.
+To make the above clearer, letโs go over a few essential concepts, those youโll hear all the time.
+There are 3 very important aspects about Observables in reactive programming. Maybe some of them donโt make sense now, but they will, once you have some hands-on experience with some reactive library.
+Observables areโฆ
+An overused term these days, but Iโll try to make it simple. +First of all, a stream is an Observable; youโll find that these two concepts are often interchangeable. Simply put, a stream is a collection of values pushed over time. Letโs think of โlive streamingโ in the video industry for a moment; on one end, thereโs your laptop observing the stream; on the other end, something is pushing several bits of data over the wire. Simple right? But how to think about streams in the conceptual world? Thatโs where diagrams (more precisely marble diagrams) come in handy. At the most basic level, a stream is simply represented by a horizontal line, representative of time, with geometric figures. Each figure represents an emitted value on the stream. Whatโs an emitted value? If a stream emits a value, it means that everyone looking into the stream will get notified of that value. Hopefully, the following figure makes it crystal clear.
+The following represents a stream that emits 4 values (1 value emitted per second).
+ +source: https://rxviz.com/
+From now on, whenever you hear โstreamโ, try to visualize the above in your head.
+Streams alone are useful as they allow multiple Observers to subscribe to it for updates. Things start to get more enjoyable when you want to manipulate a stream. As mentioned, streams can be transformed and even combined. The power itโs all yours. Letโs look at two essential operations, mapping, and filtering. Take a look at the following animation.
+source: https://reactive.how/filter
+As you can see on the left, map
applied over the left-most stream generates a new stream of values where each value in the original stream goes through the function isEven
provided to the mapping operation. Subscribing to this stream, you would get a boolean (true vs. false) or number (0 vs. 1) that tells you whether a given value is even or odd. Now letโs look at filter. With filter
, instead of transforming each value, youโre actually creating a new stream that only emits the original value when the same itโs even. So from an Observer perspective, you would be notified half of the times, while with map your Observer will be notified for every single value.
This is a concept that Iโve experienced before understanding it, and it can be daunting.
+A Hot Observable emits values before the subscription happens. Think of it as a live music concert in a stadium. You will only get to see the full performance if you enter the stadium (subscribe) before the show starts (stream emits values). Of course, you can arrive at the venue to see the concert at any future time. Everyone at the stadium shares the same experience (meaning the values are shared among subscribers). +In a real use case, a Hot Observable can be a stream of click events on the page (there might be clicks happening before you subscribe to it) in a user interface.
+A Cold Observable only starts emitting values upon subscription. Think of it as a movie on Netflix. The film only starts playing once you press play on your laptop. You wonโt miss pieces of the movie since you can start playing from the very start. If someone else watches the same movie on Netflix, they wonโt share your timeline; each user has its own individual timeline (values are not shared among subscribers). +In a real use case, a cold Observable can be a countdown clock where each subscriber has its own clock.
+According to my research in the paper Functional Reactive Animation (1997), we see some first mentions to things such as: reactivity. Some kind of temporal representation animations resembles the concept of a stream.
+Haskell mentions in its WiKi page :
+++โFunctional Reactive Programming (FRP) integrates time flow and compositional events into functional programming.โ
+
The phrasing here is bit complicated. Thereโs this concept of a primitive type called Behavior
, which is defined as a time-varying value. This resembles a stream, right? A stream is somehow a time-varying value since you can get different values pushed to the stream over time, not that the reference to the stream changes, but its contents instead.
Today reactive is not only used to manage animated user interfaces. Itโs on every platform, from the web to mobile, from UIs to servers. Hereโs a couple of the most famous reactive programming libraries today:
+I hope this section offers some other views (and their sources) on reactive programming, expressed in a different way that might complement or even wholly build your understanding of things so far.
+++ + + "The introduction to Reactive Programming you've been missing" + + +โReactive Programming raises the level of abstraction of your code so you can focus on the interdependence of events that define the business logic, rather than having to constantly fiddle with a large amount of implementation details"
+
++ + + "Streams for reactive programming" + + +"When you fully embrace RP, the core of your app ends up being a declaration of a graph through which your data flows."
+
++ + + "What is reactive programming and why should I use it?" + + +"Never store a mutable state on your types. Instead, when you generate a new value in response to a change, send it in to a channel.โ
+
Itโs good that you discovered these concepts before you jump into practice. In my opinion, these canโt be absorbed only by reading. Go over to the next blog post, where weโll build a small game together so that you can materialize the things Iโve covered in this blog post.
+After seeing reactive streams in action with RxJS, I would now like to expand โPart 1 - Why you should consider Reactive Programmingโ by debating some of the gains & pains of reactive streams and RxJS. +As of now, weโve covered some fundamental aspects of reactive programming, and weโve seen some code as well! +In this part of the series, Iโll be compacting some of the benefits I felt while using reactive programming and some of the major pain points of adopting it. Since weโve used RxJS, Iโll make occasional mentions of this reactive libraryโs ups and downs.
+Letโs explore some beneficial aspects of adopting reactive programming and RxJS now that we have looked at how to approach a problem and model it with streams.
+Working with streams means nothing happens until you subscribe to them, which is terrific! Because any code path now has a โfree of chargeโ stop & play capability! Without any effort, your computations become lazy by default executing when needed - Promises are eager. They start running as soon as you construct them. Itโs common to wrap a Promise with a function to make it lazy.
+As weโve seen in the hands-on part of this series, youโll likely have to model events and think about what parties are interested in consuming such events. Youโll spend less time focusing on the implementation details. Youโll rather spend your time drawing a mental map of the eventsโ interdependency that define your business logic. In my experience, this often results in more compact implementations, making it more accessible to capture the big picture of the internal flows in your application.
+It only makes sense that if you have an ecosystem, such as RxJS, in your arsenal, youโll spend less time implementing behaviors that are already built-in in some operator (e.g., debouncing, throttling, etc.). Just like youโll spend less time mutating the DOM directly when you use a UI framework such as React or Vue, youโll think more about how your UI looks like and what data binds to what parts of your UI.
+In my opinion, an overlooked easy win of coding with streams and RxJS is how easy it becomes to implement cancellation. What kind of behavior does cancellation concern, you ask? Letโs see an example.
+ +In the above GIF, we have a list of items. Hovering on each item in the list triggers an ajax request to fetch some data from the server. The problem of eagerly (compared with clicking the item, for instance) triggering the requests upon mouse hovering is that you can potentially fetch the data for all the items but ending up not displaying any of the data to the end-user. To avoid that, we cancel an itemโs request when the userโs mouse leaves it.
+(Note: oh, btw on the above GIF, Iโm not calling a real API, Iโm just using the tweak browser extension to mock the HTTP requests seamlessly)
+Hereโs the snippet of the above pattern, implemented with switchMap and takeUntil.
+ +++โBackpressure is when the progress of turning that input to output is resisted in some way. In most cases that resistance is computational speedโ, from โBackpressure explained โ the resisted flow of data through softwareโ
+
Did it ever happen that your addEventListener
handle is just executing too many times? For instance, while running an event handler for the scroll event? Itโs common to use a debounce strategy to run your event handler only after X time has passed since the last scroll event. Again, with built-in operators such as debounce in RxJS, you can quickly relieve the load in your consumer functions (event handlers). The operator single-handedly takes care of debouncing emissions for you!
Iโve covered this in greater detail during โPart 1 - Why you should consider Reactive Programmingโ the gist is that working with streams when done right, might make callbacks, Promises, and async/await nearly obsolete. I say nearly because youโ might still use Promises under the hood, but your code now can look the same whether youโre tackling synchronous or asynchronous tasks.
+I want to reinforce that you can leverage reactive libraries such as RxJS to solve complex problems with little effort. If you havenโt watched the talk โComplex features made easy with RxJSโ by Ben Lesh, I would highly recommend it. In the first 10 minutes, youโll see how easy it becomes to tackle some of the following problems with the help of RxJS:
+If you aim to solve one of the problems mentioned in the above list, you can avoid reinventing the wheel by following the reactive patterns demonstrated in the video.
+There are two aspects of maintainability that I would point out. First, youโll write less code; thereโs a lot of heavy lifting that RxJS can do for you; if you leverage that, youโll undoubtedly ending writing less code. The second is that a combination of streams with powerful operators solve complex problems in a very declarative manner. Code will look concise and straightforward; instead of verbose branching and imperative logic, youโll have a few combinations of operators that will do all the magic for you. +However, with RxJS and streams, maintainability is a double-edged sword. Weโre going to cover that in the next part of this article.
+Letโs look at the not so bright side.
+Any modern JavaScript codebase uses a cocktail of libraries. RxJS (or whatever library you would adopt) would be just one more thing youโll have to teach newcomers. But donโt take this as a light decision. Youโre not only introducing a new library in the codebase, but youโre also introducing a new paradigm. I feel thereโs quite a learning curve towards mastering reactive programming and RxJS. Not only youโre exposed to an entirely new ecosystem with new APIs, but you also need the time to process this different paradigm of programming with streams. As weโve experienced in previous articles, it can be quite different from a traditional writing code style (compared with imperative programming, for example).
+Depending on how broadly youโll embrace this paradigm, you might need to ship new tooling for unit testing and master additional concepts such as marble diagrams - which helps you properly model and assert data streams. However, it might require you and your team to learn another tricky DSL (domain-specific language) to deal with these diagrams.
+Some might argue that the โlearning curveโ is a โone-time costโ. As it turns out, in the software industry, software engineers tend to move a lot (due to the high demand for the skill these days), and they might be sticking around in the same company for an average of 2 to 3 years before embracing a new challenge. The bustling job market makes me believe that it is not wise to think of the โlearning curveโ as a one time cost because soon, your freshly trained engineer with RxJS skills might say goodbye.
+Just the same way, you can split your code into several functions, and those functions call other functions which, without some structure, might end up in spaghetti code. Likewise, you can end up entangled in a spaghetti of streams and not know which way to turn. I think simple functions are usually more straightforward to debug, given that they are composed sequentially. Youโre reading a function; that function might call other N functions and so forth. Well, with streams, it might not be that candid because thereโs no such thing as a stream invoking another stream. Instead, youโll have a stream plugging with other streams in mixed ways depending on the operators that join them. It might feel overweighing at some point to find your way around some particular flow (hopefully, you wonโtโ reach that point because your code is clear and concise).
+Another aspect that you might run into while debugging streams is that such an amount of abstractions and compact implementation will let no space for you to plug into a stream and debug it or inspect it the same way you debug a function. Things tend to be on a higher level of abstraction - which is beneficial because it will free up your mind on some implementation details. Hence when it comes to the point you need to dig further down, understanding whatโs going on at the very core of your flow, you might need to tap into streams here and there to figure out whatโs the issue. Although old this article, it might be one of the best walkthroughs of the problem Iโm trying to surface here. It will give you a solid strategy to debug streams (even if youโre looking at that particular code for the first time) - tip for reading it: mentally replace do
per tap
.
Kiss: Keep it Simple, Stupid, not easy with reactive streams and RxJS tough. Iโll tell from personal experience that it will come the day youโll look at your code, and although itโs just fine, youโll feel this voice inside your head: โAre you sure thereโs nothing else much fancier in the RxJS API that would allow you to write less two lines of code?โ - fight that voice! Creative solutions with RxJS might often result in dreadful consequences for your product and team. But yet, RxJS has such a unique and evolving ecosystem that will feel tempting with time to start to chime in some new operators just for the sake of adding more operators. Fight that in code reviews - this is the place you can understand why your colleague is shipping that new exotic operator and challenge simpler alternatives already in use. I guess this is general advice. I wouldnโt apply it to reactive programming only. If you donโt have a code review process, ยฏ\_(ใ)_/ยฏ.
+As usual, with powerful tools, there is increased responsibility towards their use. If you pick RxJS as your weapon of choice, there are things youโll need to be extra careful. I want to highlight one: shareReplay. We didnโt look into this operator in particular during this series, but we did learn the difference between Hot and Cold observables, a quick refresher:
+<a +href=โhttps://www.learnrxjs.io/learn-rxjs/operators/multicasting/sharereplayโ +target=โ_blankโ +title=โshareReplay - Learn RxJSโ
+++shareReplay + allows you to take a cold observable and make it hot in the sense that you can now multicast the underlying computation +to multiple subscribers ๐คฏ - thatโs share. With this operator, new subscribers will be able to โcatch upโ with +previously emitted values at any point in time - thatโs replay.
+
Donโt want to get into extensive detail of what the operator pertains to; be mindful of your implementation gaps that might trigger massive memory leaks in your application by using this operator. The gist is that using shareReply without refCount may origin a memory leak because the operator doesnโt automatically close the stream after all its consumersโ have unsubscribed.
+Also, historically, there have been some issues around its implementation [1] [2].
+Finally, yet notably, error handling. Something I did not cover in the previous articles. Error handling is yet something else that changes considerably. Letโs look at a simple example comparing reactive vs. non-reactive.
+ + +For a more natural integration, youโll have to stick with the catchError operator. As a beginner, I would tend to wrap stuff around with try/catch, but things work slightly differently with streams. Observable is our primitive here, remember? +Something mentioned as a โgotchaโ of RxJS is the fact that an RxJS Observable does not โtrapโ errors; when an error bubbles to the end of the observer chain, when unhandled, the error, it will be re-thrown.
+Would I use reactive programming and RxJS in my next project? Dependsโฆ Thereโs a great deal of learning involved in using these technologies, so even though I might not always use them, Iโm confident that these skills will (and are!) playing an essential role in my evolution as a software engineer. Just know that I would do it again (all the learning and writing).
+I do think Reactive is powerful and useful, but itโs not a holy grail that will solve all your problems overnight.
+Please focus on the problem first, scrutinize the use cases, and Reactive shall reveal itself a solution.
+I hope youโve enjoyed this series is now approaching its end. This series is far from the perfect learning resource, but I hope that my perspective and way of explaining things fit some of you, complementing your learnings in a way. To close, Iโll leave you with a list of fantastic learning resources for reactive programming and RxJS.
+It might be useful to think of the SLA as your answer: โWhat happens if one fails to comply with the agreed SLOs?โ
puppeteer.launch
options API that Iโve covered in this section.
What are your favorite bits of Puppeteer? What would you recommend me to learn next?
What are your favorite bits of Puppeteer? What would you recommend me to learn next?
Cheers!
Another thing that comes in handy when setting up our testing workflow, is to have a way to update the fixtures by tweaking existing test case inputs or adding new ones and automatically re-running the run-fixtures.js
script and the unit tests with Jest. How would that go?
If you never tried nodemon, now itโs a good time to check it out. Itโs a mighty tool to restart some job based on specific changes in your project. Letโs use nodemon to set up a npm script that seamlessly re-runs our fixtures. The idea is that we achieve the same workflow that we would normally have with jest โwatchAll, on our fixtures folder. After installing nodemon, we just need to use the โwatch option to check for changes in our fixtures.
- + [package.json] @@ -246,4 +246,4 @@As already mentioned, all the code examples in this blog post are in a public GitHub repository.
I hope that if you went through the article, you have now one more testing software pattern on your toolbelt that will (for the right use cases) allow you scale the tests in your codebase effortlessly and a in self-documented/self-organized fashion.
What do you think about having a fixture based testing architecture? Do you have any project in mind where you see that this could be the right fit?
What do you think about having a fixture based testing architecture? Do you have any project in mind where you see that this could be the right fit?
I did so, with the attributeFilter issue on the MutationObserverInit.attributeFilter API. Hereโs the final result where caniuse is displaying the information for users about the compatibility issue on the attributeFilter
API.
source: https://caniuse.com/#search=attributeFilter
-I hope this short episode makes you aware that you can help to make the web compatible and help the community get relieved of all of these annoying nuances of the different JavaScript APIs in the various browsers, especially when working with Internet Explorer and Edge.
I hope this short episode makes you aware that you can help to make the web compatible and help the community get relieved of all of these annoying nuances of the different JavaScript APIs in the various browsers, especially when working with Internet Explorer and Edge.
-- -Part 2 - Fundamentals of Reactive Programming -
-
--Part 3 - Hands-on Reactive Programming with RxJS -
-
--Part 4 - Reactive Programming: The Good and the Bad -
-
--Part 5 - Awesome RxJS and Reactive Programming Resources -
-
No trackers, a few javascript, few stylesheets. and your words.
-Looks great on any device
-Tiny (~30kb), optimized, and awesome pages
-No trackers, ads, little scripts
-RSS feeds
-Publish something awesome with your panda hands
The content clipper that highlights and syncs content, with opt-in AI enhancements.
+Mock or modify your HTTP requests to test, develop and demo your web application. tweak allows you to mock and + modify HTTP requests without leaving the browser. +
github.com/danielcaldas/react-d3-graph
Interactive and configurable graphs with react and d3 effortlessly.