<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tal Bereznitskey</title>
    <description>The latest articles on DEV Community by Tal Bereznitskey (@ketacode).</description>
    <link>https://dev.to/ketacode</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F117175%2F34dec5ec-91e5-4679-a8e6-e72bd0312a18.jpg</url>
      <title>DEV Community: Tal Bereznitskey</title>
      <link>https://dev.to/ketacode</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ketacode"/>
    <language>en</language>
    <item>
      <title>Blueprints for [an awesome] web-app</title>
      <dc:creator>Tal Bereznitskey</dc:creator>
      <pubDate>Thu, 25 Jul 2019 19:02:07 +0000</pubDate>
      <link>https://dev.to/ketacode/blueprints-for-an-awesome-web-app-209f</link>
      <guid>https://dev.to/ketacode/blueprints-for-an-awesome-web-app-209f</guid>
      <description>&lt;p&gt;What makes web applications fun and easy to use? Following the best practices of a regular website can make Single-Page-Applications shine.&lt;/p&gt;

&lt;p&gt;Here are a few &lt;strong&gt;little-big details&lt;/strong&gt; we use at &lt;a href="https://toriihq.com"&gt;Torii&lt;/a&gt; to make our users a bit more happy 😀.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links everywhere
&lt;/h2&gt;

&lt;p&gt;Just like in a regular &lt;a href="https://en.wikipedia.org/wiki/Website"&gt;website&lt;/a&gt;, anything we can drill into should be a &lt;a href="https://en.wikipedia.org/wiki/Hyperlink"&gt;link&lt;/a&gt; to the page where more information is available. This makes the usage of the applications much more fluent, as you can pretty much &lt;strong&gt;get from anywhere to anywhere relevant with a single click&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is similar to &lt;a href="https://www.wikipedia.org/"&gt;Wikipedia&lt;/a&gt;, where every article has many links inside to other relevant articles. This is what keeps readers in Wikipedia for hours.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When the application says “Configure this from the Settings page”, make sure Settings page is a link, instead of sending the user in search of the “Settings” option somewhere in your app.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When showing a message such as “your email was sent to 20 users”, clicking the 20 users text should lead to a page (or popup) where the list of users is displayed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Every page is shareable
&lt;/h2&gt;

&lt;p&gt;No matter where you are in our app, if you copy (⌘+C) the link and send it to a friend who has the same permissions as you — you will both see the same screen. That was very important to us, as people can easily share pages without a complex sharing feature. They can just copy the page URL and send away in their favorite channel: email, Slack, etc….&lt;/p&gt;

&lt;p&gt;We also get the other benefits of regular links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Refresh the current page and stay in the same place (⌘+R)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bookmark the current page for later (⌘+D)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open each feature in a new tab (⌘+⇧+T)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy the link address (⌘+C)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Every page is completely searchable
&lt;/h2&gt;

&lt;p&gt;Searching (⌘+F) on a single page of a website is a very popular feature of any browser. I also use it in web applications — to find content on the page, find menu items, find where the settings page link is, and other things I expect to be on the page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sometimes web applications make optimizations that break the built-in search option.&lt;/strong&gt; One such optimization is called windowing (or virtualization) — displaying 1,000,000 table rows on a page can slow down your browser, so apps only show a small “window” of the table and move that window as you scroll the page.&lt;/p&gt;

&lt;p&gt;This breaks the built-in find option, as some results may not currently be displayed and therefore will not be found.&lt;/p&gt;

&lt;p&gt;Our  solution was to add a search box to every page that works by using… ⌘+F. This keyboard shortcut will now lead to a dedicated search box. Don’t like our search box? Another ⌘+F will bring up the browser’s search option. &lt;strong&gt;Best of both worlds.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Everything is copyable
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Any element you have should be selectable and copyable&lt;/strong&gt;. Lots of interfaces today will fire a click on a button if you try to select its text, but sometimes the interesting data is right there on that button.&lt;/p&gt;

&lt;p&gt;There’s nothing more frustrating when a web application prevents us from doing what we’re trying to achieve.&lt;/p&gt;

&lt;h2&gt;
  
  
  Every page is printable
&lt;/h2&gt;

&lt;p&gt;What’s a better way of taking a snapshot of your website other than simply printing the page (⌘+P) into a PDF? We make sure to &lt;strong&gt;include styling specific for printing&lt;/strong&gt; that gets rid of all the menus and give the content maximum space.&lt;/p&gt;

&lt;h2&gt;
  
  
  Less loaders, instant content
&lt;/h2&gt;

&lt;p&gt;Web applications require data to show their content. When users visit a page for the first time, a loader is usually unavoidable. However, the next visit can immediately display the cached information and run an update in the background. So &lt;strong&gt;switching between pages is instantaneously&lt;/strong&gt; and avoids showing loaders all the time.&lt;/p&gt;

&lt;p&gt;This is &lt;strong&gt;quite simple to achieve&lt;/strong&gt; with state management libraries like &lt;a href="https://redux.js.org/"&gt;Redux&lt;/a&gt;, where the data is stored when moving from one page to another.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Build great websites, build great apps.&lt;/p&gt;

</description>
      <category>webapps</category>
      <category>javascript</category>
      <category>bestpractices</category>
    </item>
    <item>
      <title>Adding the missing features to GitHub Pull Requests</title>
      <dc:creator>Tal Bereznitskey</dc:creator>
      <pubDate>Thu, 02 May 2019 18:50:02 +0000</pubDate>
      <link>https://dev.to/ketacode/adding-the-missing-features-to-github-pull-requests-8m1</link>
      <guid>https://dev.to/ketacode/adding-the-missing-features-to-github-pull-requests-8m1</guid>
      <description>&lt;p&gt;I love GitHub, but their interface for code reviews and pull requests needs some work. So instead of just complaining, here’s a Chrome Extension that adds a file tree view to pull requests as well as sticky file headers:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--weYF8DJY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/m1xf246gcw08441gfgmq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--weYF8DJY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/m1xf246gcw08441gfgmq.png" alt="Chrome extension"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;“Better Pull Request for GitHub” extension on the Chrome Web Store&lt;br&gt;
The code is open source and hosted on... GitHub: &lt;a href="https://github.com/berzniz/github_pr_tree"&gt;https://github.com/berzniz/github_pr_tree&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can also install it from the Chrome Store:&lt;br&gt;
&lt;a href="https://chrome.google.com/webstore/detail/better-pull-request-for-g/nfhdjopbhlggibjlimhdbogflgmbiahc"&gt;https://chrome.google.com/webstore/detail/better-pull-request-for-g/nfhdjopbhlggibjlimhdbogflgmbiahc&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So far 2,000 developers are using it daily and many have contributed their free time for fixing issues and adding additional features.&lt;/p&gt;

&lt;p&gt;Coding is fun.&lt;/p&gt;

</description>
      <category>github</category>
      <category>chrome</category>
    </item>
    <item>
      <title>Lessons Learned — A Year Of Going “Fully Serverless” In Production</title>
      <dc:creator>Tal Bereznitskey</dc:creator>
      <pubDate>Tue, 15 Jan 2019 13:35:53 +0000</pubDate>
      <link>https://dev.to/ketacode/lessons-learneda-year-of-going-fully-serverless-in-production-3mh8</link>
      <guid>https://dev.to/ketacode/lessons-learneda-year-of-going-fully-serverless-in-production-3mh8</guid>
      <description>&lt;h1&gt;
  
  
  Lessons Learned — A Year Of Going “Fully Serverless” In Production
&lt;/h1&gt;

&lt;p&gt;Photo by Aaron Burden&lt;/p&gt;

&lt;p&gt;At &lt;a href="https://toriihq.com"&gt;Torii&lt;/a&gt;, we decided to go the &lt;strong&gt;no-ops&lt;/strong&gt; path as much as possible meaning we’ll focus all our efforts on our product and not on &lt;strong&gt;operations&lt;/strong&gt;. While we enjoy doing devops, that’s not our main focus as a company.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Serverless, because we like to sleep at night.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can break our application into three parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Static websites&lt;/strong&gt;. These are frontend websites, written in React and statically generated at build time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Background jobs.&lt;/strong&gt; These are jobs that are scheduled or triggered by events such as file uploads, webhooks or any other asynchronous event.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;**API Server. **A REST API server interacting with our databases and serving all client requests.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;#1. Static websites&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Static website are fast, easy to scale and simple to distribute. We use React to build our frontend and the code is packaged as a simple HTML/JS/resources bundle ready for distribution.&lt;/p&gt;

&lt;p&gt;We use &lt;a href="https://www.netlify.com"&gt;Netlify&lt;/a&gt; to host these static assets on a CDN and get &lt;strong&gt;fast loading times from anywhere in the world&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;No Nginx/Apache servers to configure here 👍&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;#2. API Server on Serverless&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The basic idea is that an API Server is a function: the input is an HTTP request and the output is an HTTP response. It’s &lt;strong&gt;perfect for FaaS&lt;/strong&gt; (&lt;em&gt;Function as a Service&lt;/em&gt;) where each HTTP request gets its own server instance handling it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This setup leads to automatic scalability, high availability and reduces costs dramatically&lt;/strong&gt;. It also makes things simpler since there are less moving parts: no servers, no load balancers, no auto-scaling groups. All these are abstracted away and all we care about is one function.&lt;/p&gt;

&lt;p&gt;We take an entire Node.js app and package it as a single AWS Lambda function. An API Gateway routes all traffic to it and the Node.js app sees it as a regular HTTP request.&lt;/p&gt;

&lt;p&gt;We picked apex/up for setting up the stack, updating it and deploying our functions. It’s really as simple as writing up in your terminal. It is highly configurable, so you can customize the deployment for your needs, but if you have no special requirements, the default is good to go.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Zero servers to provision, configure or apply security patches to 👏&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;#3. Packing for Serverless&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Deploying a Lambda function has a 52Mb limitation of the function including all of its dependencies. If you’ve coded a decent Node.js project recently, you’ll know we can pass this limit easily. Note: There’s a way to deploy it from S3 which allows to bypass this limitation, we haven’t tried that yet.&lt;/p&gt;

&lt;p&gt;To mitigate this, we‘re including only the required dependencies and trimming their size by excluding unused files like READMEs, history of package, tests, documentation and examples. We published a package that helps do this named &lt;a href="https://www.npmjs.com/package/lambdapack"&gt;lambdapack&lt;/a&gt;. It will pack your code with webpack to provide with the latest Node.js and JavaScript features, while keeping your node_modules as small as possible. lambdapack fully integrates with apex/up so the build process is optimized and packed efficiently.&lt;/p&gt;

&lt;p&gt;Read more about &lt;a href="https://www.npmjs.com/package/lambdapack"&gt;lambdapack&lt;/a&gt; on GitHub.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;#4. Deployments&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This works amazingly well, where &lt;strong&gt;each deployment creates a new version of the Lambda&lt;/strong&gt;. AWS allows to keep multiple versions of each Lambda and have aliases pointing to versions. Popular aliases include: test, staging and production. So a new deployment means uploading a new version of the Lambda and pointing the production alias to it. Fortunately, up does this automatically with up deploy production. Rollbacks are just aliasing the pointer to the required version.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;#5. Local testing/development&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Since we are using a regular Node.js server, running locally just means running your server as usual. However, this doesn’t mimic the AWS infrastructure with all the important differences like: enforcing the same Node.js version, API gateway timeouts, Lambda timeouts, communicating with other AWS resources and more. &lt;strong&gt;Unfortunately, The best way to test is on the AWS infrastructure itself.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;#6. Background jobs&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;For background jobs such as file processing or syncing with 3rd party APIs, we keep a set of dedicated Lambda functions that are not part of the API server. These jobs are scheduled to run by CloudWatch or as a response to events in our system.&lt;/p&gt;

&lt;p&gt;Currently we use a “sibling” project to handle these background job Lambdas — using the open source &lt;a href="https://github.com/apex/apex"&gt;apex/apex&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;These functions only run when needed and there’s no need to keep servers up to process these jobs. Another win for the Serverless approach 🚀&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;#7. Logging&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;AWS services comes with the build in CloudWatch logs service which has awful UI, UX and DX. While the up cli has a log feature to view the logs, there’s still much more to ask: alerts, aggregated logs, etc.&lt;/p&gt;

&lt;p&gt;Our first solution was logging directly from the API server to a 3rd party logging service (we use &lt;a href="https://papertrailapp.com"&gt;papertrail&lt;/a&gt;), but this kept the Lambda functions always up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A better approach is to stream the Lambda logs&lt;/strong&gt; into a dedicated Lambda that is responsible for sending it to the 3rd party logging service. We used an updated version of &lt;a href="https://github.com/apiaryio/cloudwatch-to-papertrail"&gt;cloudwatch-to-papertrail&lt;/a&gt;. I also suggest streaming the API Gateway logs to get the full picture.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;#8. Environment variables and secrets&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Don’t commit your secrets to source control.&lt;/strong&gt; Now that we got this out of the way, we should store them encrypted somewhere. AWS has a solution exactly for this and it is called &lt;a href="https://aws.amazon.com/ec2/systems-manager/parameter-store/"&gt;AWS Parameter Store&lt;/a&gt;. You add your parameters, choose whether to encrypt them or not and then choose who can read these secrets. We will allow our Lambda function to read these secrets as soon as it starts running. Since Lambda functions are re-used, this will happen only on the first invocation of the Lambda (First API call). To set this up, we add the parameters with an hierarchy of /{env}/env_variable, for example /production/MYSQL_PASSWORD. Now we can read all /production parameters and use them as environment variables or just store them in-memory.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;#9. Performance and Cold starts&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When a Lambda hasn’t been invoked in a while it will freeze and the next invocation will incur the time of launching a new instance of the server. This can take some time depending on the complexity of the app, sometimes between 600ms–2000ms. &lt;strong&gt;There’s currently no real solution for this&lt;/strong&gt; other than (1) warming the Lambda (periodically calling it using a monitoring service or just another scheduled Lambda invocation using CloudWatch) and (2) making your Node.js app load faster. Hopefully, AWS will find a way to reduce the cold start time in the future.&lt;/p&gt;

&lt;p&gt;If your API server has to comply with an SLA, Serverless at this point might not be a great fit 😞&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;#10. No parallel requests&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When building Node.js servers, we’re used to handling multiple requests with the help of the event loop and asynchronous functions. However, when ran inside an AWS Lambda, each Lambda container will only handle one request.&lt;/p&gt;

&lt;p&gt;This means that &lt;strong&gt;parallelism is achieved by the API Gateway&lt;/strong&gt; spawning multiple Lambdas vs. one Node.js app serving multiple requests.&lt;/p&gt;

&lt;p&gt;Test your app and use cases to see if this model fits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Is Serverless a step forward in the operations space? With &lt;strong&gt;devops&lt;/strong&gt; we wanted to understand how ops work while with Serverless we benefit from delegating the responsibility for operations to someone else (in this case AWS) and we can call it &lt;strong&gt;no-ops&lt;/strong&gt;. While we lose flexibly, we gain a lot of features, ease of mind and ability to focus our energy on our code and product.&lt;/p&gt;

&lt;p&gt;Serverless will surely take over in the next few years, including more specific serverless offerings like serverless databases, serverless streaming services and others.&lt;/p&gt;

&lt;p&gt;For us developers, this is almost the holy grail. &lt;strong&gt;Build it, ship it, it works.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Originally posted at &lt;a href="https://hackernoon.com/lessons-learned-a-year-of-going-fully-serverless-in-production-3d7e0d72213f"&gt;https://hackernoon.com/lessons-learned-a-year-of-going-fully-serverless-in-production-3d7e0d72213f&lt;/a&gt;&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>javascript</category>
    </item>
    <item>
      <title>So why did GitHub send me this T-shirt?</title>
      <dc:creator>Tal Bereznitskey</dc:creator>
      <pubDate>Sun, 25 Nov 2018 19:41:40 +0000</pubDate>
      <link>https://dev.to/ketacode/so-why-did-github-send-me-this-t-shirt-l4p</link>
      <guid>https://dev.to/ketacode/so-why-did-github-send-me-this-t-shirt-l4p</guid>
      <description>&lt;p&gt;So why did @github send me this T-shirt? Here's the story and why they've been awesome.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fqf4mdmj5v2mhnqgz0sv3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fqf4mdmj5v2mhnqgz0sv3.jpg" width="800" height="965"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A while ago I created a Chrome extension that improves GitHub. They've seen it and also noticed I've used their logo as the extension's logo.&lt;/p&gt;

&lt;p&gt;This is not allowed and they've reached out and asked that I'll change the logo. I promptly did and they've thanked me and sent me a gift of my choice from their store.&lt;/p&gt;

&lt;p&gt;Other companies would have sent a cease and desist letter, but GitHub knew how to turn a bad situation into a winning situation 👏&lt;/p&gt;

&lt;p&gt;.&lt;br&gt;
.&lt;br&gt;
.&lt;br&gt;
BTW. Here's the repo &lt;a href="https://github.com/berzniz/github_pr_tree" rel="noopener noreferrer"&gt;https://github.com/berzniz/github_pr_tree&lt;/a&gt;&lt;/p&gt;

</description>
      <category>github</category>
      <category>tshirt</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
