<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by David Domonkos on Medium]]></title>
        <description><![CDATA[Stories by David Domonkos on Medium]]></description>
        <link>https://medium.com/@daviddomonkos?source=rss-8c793f91cb4------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*oQNulaTIJ3umJnmavTycGA.png</url>
            <title>Stories by David Domonkos on Medium</title>
            <link>https://medium.com/@daviddomonkos?source=rss-8c793f91cb4------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 03:51:01 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@daviddomonkos/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Chrome Extensions and Continuous Integration]]></title>
            <link>https://medium.com/slido-dev-blog/chrome-extensions-and-continuous-integration-392206f7e414?source=rss-8c793f91cb4------2</link>
            <guid isPermaLink="false">https://medium.com/p/392206f7e414</guid>
            <category><![CDATA[chrome-extension]]></category>
            <category><![CDATA[continuous-integration]]></category>
            <category><![CDATA[testing]]></category>
            <category><![CDATA[development]]></category>
            <dc:creator><![CDATA[David Domonkos]]></dc:creator>
            <pubDate>Wed, 02 Oct 2019 09:26:25 GMT</pubDate>
            <atom:updated>2019-10-02T09:26:25.817Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*x1uA7vwt0vFX0P_aIRkSvQ.jpeg" /><figcaption>“Dear QA, please find the newest version attached.” Photo by <a href="https://burst.shopify.com/@matthew_henry?utm_campaign=photo_credit&amp;utm_content=Free+Shipping+Boxes+In+Front+Of+Red+Brick+Photo+%E2%80%94+High+Res+Pictures&amp;utm_medium=referral&amp;utm_source=credit">Matthew Henry</a> from <a href="https://burst.shopify.com/business?utm_campaign=photo_credit&amp;utm_content=Free+Shipping+Boxes+In+Front+Of+Red+Brick+Photo+%E2%80%94+High+Res+Pictures&amp;utm_medium=referral&amp;utm_source=credit">Burst</a></figcaption></figure><p>Let’s set the scene. You are in charge of developing a Chrome extension for your company. You have a colleague (let’s call her a QA expert) who is responsible for testing the extension before it goes live.</p><p>In the beginning you would always build the extension on your machine, zip it and send it to her when you finished some unit of work. In time this gets annoying for both you and her. Time to automate.</p><p>Does this sound familiar in any way? Read on. :)</p><h4>The standard approach</h4><p>There’s this <a href="https://circleci.com/blog/continuously-deploy-a-chrome-extension">excellent blog post</a> about how to do continuous integration of Chrome extensions written by the guys at CircleCI.</p><p>So why bother with another blog post? I had a constraint which prevented me from using that solution. Thing is, if you use the said solution you end up giving the CI process full rights to publish any Chrome extension in the name of the Google account that you use.</p><p>I see <strong>two problems</strong> if I use my own account:</p><ul><li>I have the right to publish to both staging and production. I do not want a staging CI process to have the rights to publish to production.</li><li>What if my account is deleted for some reason? The dependency of CI on my account’s existence and access rights is absolutely hidden here.</li></ul><p>Okay, there’s an easy fix — create a new Google account that will be dedicated only to this purpose and will only have the rights which it needs. But each account costs something. Is there perhaps another way?</p><h4>The alternative</h4><p>You don’t need the Chrome Web Store to distribute extensions. You just pack the extension, send it to the other person (our QA expert) and they drag’n’drop it into Chrome.</p><p>The problematic part is, naturally, updating. Luckily for us, there’s a property update_url in the extension’s manifest.json which we can use. In the URL you specify where Chrome expects an XML file with some info about the newest version of the extension. The file looks like this (let’s call it update2.xml):</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f074865a1bc08cf13433c1039f4e3af7/href">https://medium.com/media/f074865a1bc08cf13433c1039f4e3af7/href</a></iframe><p>There are three things in this file:</p><ul><li>appid — ID of your extension. You can see it when you install it in Chrome. It will stay static.</li><li>codebase — The location of the newest CRX file.</li><li>version — The version of the extension in that location.</li></ul><h4>The CI configuration</h4><p>Here are the things your CI needs to do:</p><ol><li>Generate a new version number so that Chrome knows it needs to update. For the staging environment, I use the 4th version number and bump it by one on each deployment. E.g. 1.0.0.0 , 1.0.0.1 , 1.0.0.2 and so on. I always have a script download the current update2.xml , check the current version and bump it.</li><li>Set the correct version in the manifest.xml and pack your code into a CRX file. You can use <a href="https://github.com/oncletom/crx">this amazing crx utility</a> and the command crx pack . For this, you’ll need to generate an RSA private key first. You can use this snippet: openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem . Put the key in some secured environment variable of your CI service.</li><li>Upload a new update2.xml (where you updated the version number) and the generated CRX file onto the locations you specified (in manifest.xml and update2.xml respectively).</li></ol><p>And that’s all there is to it.</p><p>When all these steps are complete, Chrome should automatically update the extension. If you don’t want to wait for Chrome to realize there’s a new version out, you can open the details of the extension in the browser and click the “Update” button.</p><p><em>Was this article helpful? Or did you find it a bit too brief and would like me to go into more detail? Let me know in the comments.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=392206f7e414" width="1" height="1" alt=""><hr><p><a href="https://medium.com/slido-dev-blog/chrome-extensions-and-continuous-integration-392206f7e414">Chrome Extensions and Continuous Integration</a> was originally published in <a href="https://medium.com/slido-dev-blog">Slido developers blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why you need no Redux Saga]]></title>
            <link>https://medium.com/slido-dev-blog/why-you-need-no-redux-saga-4d4dc46e448?source=rss-8c793f91cb4------2</link>
            <guid isPermaLink="false">https://medium.com/p/4d4dc46e448</guid>
            <category><![CDATA[asynchronous]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[redux]]></category>
            <dc:creator><![CDATA[David Domonkos]]></dc:creator>
            <pubDate>Thu, 14 Mar 2019 20:47:32 GMT</pubDate>
            <atom:updated>2019-03-28T08:47:07.974Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JUE1Jk9SxhQwUm4hW91MrA.jpeg" /><figcaption>Credit: <a href="https://unsplash.com/photos/nKEARsgmrqc?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Chris Benson</a>/<a href="https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>A very common requirement when writing single page applications is making an asynchronous HTTP request to some kind of an API. You might want to fetch some data from the server. Or you might want to perform some action on the server (think RPC).</p><p>Either way, it is an asynchronous action. And if you are just starting with Redux and/or front-end development, you google how other developers across the internet do these async things. And you come across <em>redux-observable</em>, <em>redux-saga</em>, <em>redux-thunk</em>, or some other “side-effects” library for Redux.</p><p>Redux-observable uses reactive programming, redux-saga uses generators. Both are extremely fascinating and useful concepts. But do you need to learn either of these to do that API request?</p><p><strong>In a word, no.</strong></p><p>To make my point, let us briefly get to the very essence of what we use Redux for.</p><p>I love Redux, because it allows me to abstract from the visual UI and lets me represent the state of my application in a simple (JavaScript) object. The UI is then for the most part just a visual projection of this object. It is as simple as that.</p><p>So, need to perform an asynchronous request? Ask yourself this question first: <strong>Does the request even affect the global state of the application at all?</strong></p><ol><li>No it doesn’t. This is a perfectly valid use case. Forget about Redux and just call that axios (or the HTTP client of your choosing).</li><li>Yes it does. Then why not just update the state yourself? One dispatch before the request and one dispatch after the request.</li></ol><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/352a6c4b1604f9134e3b975c0617966d/href">https://medium.com/media/352a6c4b1604f9134e3b975c0617966d/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/97e23cbd2a33a5c18623f72847f4481c/href">https://medium.com/media/97e23cbd2a33a5c18623f72847f4481c/href</a></iframe><p>Anyone with even basic knowledge of Javascript and Redux will understand how the code above works. <strong>Don’t put a middleman in there until you see that it will bring you more than it costs you.</strong></p><p>Another beauty of this “JavaScript 101” approach is that you get a Promise back (or an Observable if you wish)! Ever wanted to show a spinning wheel after clicking a button without a neck-breaking loop through dispatcher, reducer, selector, connect and props? Well now you can! :)</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c4342d7bf022d5771f329a694ca429d2/href">https://medium.com/media/c4342d7bf022d5771f329a694ca429d2/href</a></iframe><p>By the way, if you are a more seasoned Redux user, you might notice that this is not very different from <em>redux-thunk</em> at all. The main difference is dependency injection. Redux-thunk injects <em>dispatch</em> and <em>getState</em> for you — but since you have to pass the action to a <em>dispatch</em> first anyway, it saves you almost no keystrokes. On the other hand, it makes things a little less transparent and even changes the signature of the <em>dispatch </em>method to return a Promise (try explaining this to TypeScript).</p><h4>Wrap up</h4><p>My personal struggle with these side effects libraries was that they were adding a lot of complexity to something that, by itself, does not need to be complex at all.</p><p>I didn’t realize that what makes Redux really valuable for me, are not conventions or “using modern web technologies”. It is the fact that I can reason about the application without the burden of UI. And that I can easily write tests which do not have to rely on some crazy framework mocks.</p><p>So at the end of the day, <strong>my end goal is that I want to be able to update the state whenever I need to, to whatever state I need to. </strong>If a 3rd party library can help me with this, great! If not, why bother with it?</p><p>Whether this model works for you is entirely up to you to decide. But it has for me so far.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4d4dc46e448" width="1" height="1" alt=""><hr><p><a href="https://medium.com/slido-dev-blog/why-you-need-no-redux-saga-4d4dc46e448">Why you need no Redux Saga</a> was originally published in <a href="https://medium.com/slido-dev-blog">Slido developers blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>