<?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: yellow1912</title>
    <description>The latest articles on DEV Community by yellow1912 (@yellow1912).</description>
    <link>https://dev.to/yellow1912</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%2F246624%2F012cd6d5-a1c5-483a-bddd-394634c0446b.png</url>
      <title>DEV Community: yellow1912</title>
      <link>https://dev.to/yellow1912</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yellow1912"/>
    <language>en</language>
    <item>
      <title>On the topic of death</title>
      <dc:creator>yellow1912</dc:creator>
      <pubDate>Wed, 23 Dec 2020 05:48:41 +0000</pubDate>
      <link>https://dev.to/yellow1912/on-the-topic-of-death-40io</link>
      <guid>https://dev.to/yellow1912/on-the-topic-of-death-40io</guid>
      <description>&lt;p&gt;Recently, I noticed that I have more grey hair than I expected, and then I realized I'm turning old. I have this mid-life crisis of life's goals and values. I haven't reached most of the goals I set out, and the thought of missing out on new things that will happen in the far future saddens me. You know, the space travel, the exploration of new horizons, the meetings with aliens perhaps,... I will never ever see that.&lt;/p&gt;

&lt;p&gt;I'm not a religious person. I have always been pondering what will happen after death. Will it be the end of everything, or will there be some continuation after death? Whatever it will be, I'm pretty sure that the "me" that exists now will cease its existence completely. Death is a fascinating topic and I have read and watched lots of documents on it.&lt;/p&gt;

&lt;p&gt;It's not all grim, however. When I look at my children, still of a very young age, I see a glimpse of hope. Through them, I see a continuation of life. Some day, my grand grand daughter may ride her own spaceship out of the Solar system during her day trip. Some day, we the human may even find the fountain of youth that death seems like a strange concept to us all. Imagine the possibilities when you can live for centuries. Oh the things you can learn, the places you can see, the stuffs you can do.&lt;/p&gt;

</description>
      <category>watercooler</category>
    </item>
    <item>
      <title>Using an iphone in 3rd world country can hurt you</title>
      <dc:creator>yellow1912</dc:creator>
      <pubDate>Sat, 28 Nov 2020 06:42:02 +0000</pubDate>
      <link>https://dev.to/yellow1912/using-an-iphone-in-3rd-world-country-can-hurt-you-4gip</link>
      <guid>https://dev.to/yellow1912/using-an-iphone-in-3rd-world-country-can-hurt-you-4gip</guid>
      <description>&lt;p&gt;Recently, I was doing speed test on a new website for a client, and I was puzzled by Chrome's report saying that my images were too big.&lt;/p&gt;

&lt;p&gt;I looked at the details and it seems like the browser is using a way bigger image than what I think it should use. All my images use srcset with w descriptor to provide different sizes of images for different device resolution, and on iphone it shows an image of 2600px being used. dang. How can it be so big when the phone screen is relatively small? I spent hours thinking it was a bug and tried various ways to fix it. &lt;/p&gt;

&lt;p&gt;It turned out that new devices have this thing called DPR (device pixel ratio), and apparently high end devices may have very high DPR such as 3 or even more. What it means is that now if the normal css pixel is 500, you need an image of 1500px for the given device.&lt;/p&gt;

&lt;p&gt;This can have huge impact on the site performance because the device needs to download 3 times more data (more or less). For third world countries like mine where 4g feels sluggish, this can really delay the rendering of the site. For the clients they have to wait longer, and also unknowingly pay for more bandwidth.&lt;/p&gt;

&lt;p&gt;Do we really need those big images? Only sometimes. And should not come at the cost of potential users abandon the site due to slow load.&lt;/p&gt;

&lt;p&gt;For people using lazysizes, you can use the optimumux plugin to set the optimal DPR. The default is 1.6 mx which is reasonable IMHO. &lt;/p&gt;

&lt;p&gt;For above the fold content which should not be loaded lazily IMHO, I'm looking into the setting of srcset with the x descriptor and sizes. I will update this post once I have a solid answer.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>mobile</category>
      <category>performance</category>
    </item>
    <item>
      <title>PHP 8 has finally arrived</title>
      <dc:creator>yellow1912</dc:creator>
      <pubDate>Thu, 26 Nov 2020 18:02:37 +0000</pubDate>
      <link>https://dev.to/yellow1912/php-8-has-finally-arrived-3b29</link>
      <guid>https://dev.to/yellow1912/php-8-has-finally-arrived-3b29</guid>
      <description>&lt;p&gt;PHP 8 is now available for download. Hate it or love it, PHP has come a long way. I cannot wait to finally bump my PHP version on dev server and see how things go (fingers crossed).&lt;/p&gt;

&lt;p&gt;The PHP team has done an amazing job. Thanks guys.&lt;/p&gt;

</description>
      <category>php</category>
    </item>
    <item>
      <title>A super weird case with SVG performance</title>
      <dc:creator>yellow1912</dc:creator>
      <pubDate>Tue, 24 Nov 2020 09:40:32 +0000</pubDate>
      <link>https://dev.to/yellow1912/a-super-weird-case-with-svg-performance-1oco</link>
      <guid>https://dev.to/yellow1912/a-super-weird-case-with-svg-performance-1oco</guid>
      <description>&lt;p&gt;(Image from By W3C, CC BY-SA 4.0, &lt;a href="https://commons.wikimedia.org/w/index.php?curid=89557878"&gt;https://commons.wikimedia.org/w/index.php?curid=89557878&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;I have this super weird case where I need to display a big tree of text with svg icons. For some reason on the latest Chrome it took almost 30seconds just to render the whole tree (insane). I took a look at Webflow which has a similar tree and there seems to be no issue at all. &lt;/p&gt;

&lt;p&gt;My tree was rendered by Vuejs 2.x, I'm not sure if there is anything to do with that, I could not figure out why. The only thing that I could think of, is that inside the Vuejs template I use something like this to render the svg:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;svg&amp;gt;
  &amp;lt;use xlink:href="#general_small--arrow_2_down"&amp;gt;&amp;lt;/use&amp;gt;
&amp;lt;/svg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(The svg sprite is printed on the top of the body tag with display none)&lt;/p&gt;

&lt;p&gt;In any case, I put in this temporary fix which manages to bring down the rendering from 30s to 2s:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a class to hide (display:none) all svg inside the tree every time I need to re-render the tree&lt;/li&gt;
&lt;li&gt;Set time out (something like 200ms)&lt;/li&gt;
&lt;li&gt;Remove the class&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And now all the SVG icons are shown nicely, instantly.&lt;/p&gt;

&lt;p&gt;Edit 1:&lt;/p&gt;

&lt;p&gt;So I think I found the issue. The inline sprite svg file that I was including was huge (hundreds of svg files), and it seems like that slows down the lookup drastically (even though the file was already included inline in html). By splitting the file into smaller files I was able to speed up the rendering multiple times.&lt;/p&gt;

</description>
      <category>html</category>
      <category>css</category>
      <category>performance</category>
    </item>
    <item>
      <title>Create a log service with PHP and Clickhouse [Part 2]</title>
      <dc:creator>yellow1912</dc:creator>
      <pubDate>Sun, 11 Oct 2020 10:56:50 +0000</pubDate>
      <link>https://dev.to/yellow1912/create-a-log-service-with-php-and-clickhouse-part-2-22ha</link>
      <guid>https://dev.to/yellow1912/create-a-log-service-with-php-and-clickhouse-part-2-22ha</guid>
      <description>&lt;p&gt;With Vector taking care of mining and shipping our logs, we need a place to store all these logs. &lt;/p&gt;

&lt;p&gt;I built this logging service for simple and quick debugging and alerting for dev team. My goals are: fast and cheap. The log service can fail and it's okie to fail and get restarted again quickly.&lt;/p&gt;

&lt;p&gt;I came up with the following table schema for my log (I want it to be as generic as possible to store logs from different sources)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE IF NOT EXISTS log (
        instance_id String,
        node_id String,
        project_id String,    
        app_name String, 
        app_version String,
        client_ip String,            
        log_level String,
        log_message String,
        log_code Int32,
        log_context String,        
        log_created_timestamp UInt32,
        log_time DateTime,
        log_date Date DEFAULT toDate(log_time)               
    )
    ENGINE = MergeTree()
    PARTITION BY toYYYYMM(log_date)
    TTL log_date + INTERVAL 1 Week
    ORDER BY (project_id, log_created_timestamp)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There are several things I would like to point out:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I don't care about old logs, for now, so I decided that logs older than 1 week can be deleted.&lt;/li&gt;
&lt;li&gt;I want logs to always be listed by created date (newest logs first).&lt;/li&gt;
&lt;li&gt;I want to filter by certain criteria (to group logs by application, client, etc)&lt;/li&gt;
&lt;li&gt;I'm a Clickhouse newbie, and I'm still figuring things out. I secretly hope that someone will look at the table schema and point out improvements that I can do.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the beginning, I logged error logs as well as access logs, and the number of records quickly reach billions after just a few days. The good thing is that the log service still runs surprisingly well on a rather small server instance (CPU: 2 vCore RAM: 4096 MB Storage: 80 GB SSD). The bad thing is that listing keeps timing out. I later found out that I didn't set up correct indexes for my table (you really really must setup indexes for the columns you want to filter and order by).&lt;/p&gt;

&lt;p&gt;Next time I will show how I handle the logs using PHP.&lt;/p&gt;

</description>
      <category>php</category>
      <category>clickhouse</category>
      <category>database</category>
      <category>logging</category>
    </item>
    <item>
      <title>Create a log service with PHP and Clickhouse [Part 1]</title>
      <dc:creator>yellow1912</dc:creator>
      <pubDate>Tue, 29 Sep 2020 15:16:57 +0000</pubDate>
      <link>https://dev.to/yellow1912/create-a-log-keep-service-with-php-and-clickhouse-part-1-4hm5</link>
      <guid>https://dev.to/yellow1912/create-a-log-keep-service-with-php-and-clickhouse-part-1-4hm5</guid>
      <description>&lt;p&gt;I would like to share my experience configuring a very simple logging service with PHP and Clickhouse. I would like to stress that this is by no mean an optimal setup, I simply want to share my experience and I would love to hear feedbacks to improve.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;A very simple logging service to track all kinds of events such as nginx error or php error internally and externally. I find ELK too complicated to properly setup and guard, and too resource intensive (and thus costly) for my needs.&lt;/li&gt;
&lt;li&gt;Performant enough to handle tens of millions of logs per day on an average server (I pick the Vultr instance below which has 2 CPU and 4 GB of RAM). I'm handling over tens of million logs per day with this setup and still have resources to spare.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Tech stacks
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;PHP&lt;/li&gt;
&lt;li&gt;Clickhouse&lt;/li&gt;
&lt;li&gt;Vector&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Why PHP?&lt;/strong&gt;&lt;br&gt;
Because I'm familiar with it and because why not? I don't want to spend days and weeks trying to learn a new thing just for something really quick that I can do for a 1-2 hour with PHP.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Clickhouse?&lt;/strong&gt;&lt;br&gt;
Clickhouse is a very performant, easy-to-setup database designed and optimized for writing data. I have great experience using it to track views and clicks on my website.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Vector?&lt;/strong&gt;&lt;br&gt;
I looked at many log collectors such as syslog, syslog-ng, filebeat etc... I'm not a system guy and their documents are terrible, terrible. Filebeat is not so bad but I was not entirely impressed with it (I used it in the past). Then I found Vector and I was blown away by the website (so clean), the documents, the options, and the support.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparation
&lt;/h2&gt;

&lt;p&gt;First, we need to collect the logs. Vector is super simple for collecting logs, you can find the website here with all the documents:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vector.dev/"&gt;https://vector.dev/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm going to share some of my current configs, please do note that I'm a Vector virgin, so please do review before use and please let me know if I can improve anything:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/yellow1912/782d53cb97b9de86d4fdb2848cc2e520"&gt;https://gist.github.com/yellow1912/782d53cb97b9de86d4fdb2848cc2e520&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will notice that I'm opting to send the logs to a remote server via http/https protocol. You can choose any other protocol you want. I also pass along an authorization token so my log service can check.&lt;/p&gt;

&lt;p&gt;Next time, I will cover Clickhouse database setup.&lt;/p&gt;

</description>
      <category>php</category>
      <category>database</category>
      <category>vector</category>
      <category>logging</category>
    </item>
    <item>
      <title>Please recommend me a tech stack</title>
      <dc:creator>yellow1912</dc:creator>
      <pubDate>Fri, 25 Sep 2020 00:04:00 +0000</pubDate>
      <link>https://dev.to/yellow1912/please-recommend-me-a-tech-stack-21gj</link>
      <guid>https://dev.to/yellow1912/please-recommend-me-a-tech-stack-21gj</guid>
      <description>&lt;p&gt;This hacktoberfest, I want to give back something to the community where I'm living. I'm thinking of creating a map which you can review the living condition of certain area. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Once you give the lat long you can see reports regarding crime rate, noise, air quality, pollution etc. Each criterion is going to be on a different layer of the map which you can turn on off. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There should also be historical reports to see simple charts and stuffs. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Information may come from official sources or from user reports. Users can also upload reviews and pictures. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The site should be in multiple language.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scalability would be great.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I code in php and JavaScript and know a bit about golang and lua. I'm also familiar with nginx, redis, mariadb, clickhousedb. I can learn new things if necessary. Thank you ❤️.&lt;/p&gt;

</description>
      <category>hacktoberfest</category>
      <category>webdev</category>
    </item>
    <item>
      <title>I failed the spam report captcha on dev.to (20+ times)</title>
      <dc:creator>yellow1912</dc:creator>
      <pubDate>Tue, 15 Sep 2020 01:06:28 +0000</pubDate>
      <link>https://dev.to/yellow1912/i-fail-the-spam-report-captcha-on-dev-3397</link>
      <guid>https://dev.to/yellow1912/i-fail-the-spam-report-captcha-on-dev-3397</guid>
      <description>&lt;p&gt;I saw several spam posts today on dev.to and tried to report. Unfortunately, I failed the captcha like 20 times and finally gave up.&lt;/p&gt;

&lt;p&gt;It makes me think though, what is the priority here? We can post without any captcha, but cannot report spam behavior without going through hoops.&lt;/p&gt;

&lt;p&gt;On another hand, asking a human to prove himself a human while using a flawed script can be really annoying and frustrating.&lt;/p&gt;

</description>
      <category>watercooler</category>
    </item>
    <item>
      <title>Integrate Symfony form with Vuejs</title>
      <dc:creator>yellow1912</dc:creator>
      <pubDate>Sun, 22 Mar 2020 03:55:41 +0000</pubDate>
      <link>https://dev.to/yellow1912/integrate-symfony-form-with-vuejs-2ajo</link>
      <guid>https://dev.to/yellow1912/integrate-symfony-form-with-vuejs-2ajo</guid>
      <description>&lt;p&gt;I think I'm old style because I prefer to separate html from javascript. I don't like how Angular (the new versions) and React force you to mingle html and javascript. Separating html, css, js is just something I've got used to and it's difficult to change that way of thinking. &lt;/p&gt;

&lt;p&gt;In any case, I'm working on a huge Symfony (4) based application, and most of my forms were built on Symfony form and twigs. The javascript library I used was Angularjs 1.x and it allowed me to support the "legacy" codebase just fine. I could easily embed Angularjs directive right into the html code by adding attributes/classes.&lt;/p&gt;

&lt;p&gt;We are stuck with Angularjs 1.x however, the later version of Angular requires significant changes in the codebase that is impractical for us. That is until we found out about Vuejs. With Vuejs we could still keep our legacy codebase and it was possible to migrate from Angularjs 1.x to Vuejs 2.x without any difficulty except for 1 thing: form.&lt;/p&gt;

&lt;p&gt;In Symfony, the form is a very powerful component and can be generated dynamically so it's difficult to know the exact structure of the form (which fields, nested structure, etc). With Vuejs if you want to use v-model you will have to ensure that data is already available. &lt;/p&gt;

&lt;p&gt;Let's use an example here (open the console log on codepen to see the error):&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/raineng/embed/dyoqppE?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;You can see that if I have a v-model referring to undefined data I will get an error with Vuejs (in Angularjs it will automatically be set for you).&lt;/p&gt;

&lt;p&gt;Many current tutorials on the internet recommend hard-coding the form data structure into your components. This is not good for us because:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Symfony form can have deeply nested structure.&lt;/li&gt;
&lt;li&gt;There is no way that we know the form structure beforehand (form has events and transfomers that can take options and modify form's structure).&lt;/li&gt;
&lt;li&gt;Even if we do know the form structure beforehand, we will have to create many components for all the forms that we have. This is not practical.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The solution I came up with, was to pre-populate a custom form component with the form data structure. I broke this into 2 phases:&lt;/p&gt;

&lt;h3&gt;
  
  
  I. Phase 1:
&lt;/h3&gt;

&lt;p&gt;For fast migration, in phase 1 I want to keep all the current twig rendering of the form. For this purpose, I figured out that I could dump the form view (the view data object returned by Symfony) to a prop of the form component (I called it initialData). Using that initialData I populated the data of the form component to make sure that all the fields are pre-populated (meaning that all v-model are referring to valid data).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note 1:&lt;/strong&gt; Do note that Symfony form view object is huge, you don't want to dump every single thing in there, just enough for you to build the necessary data structure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note 2:&lt;/strong&gt; Handling prototype was a pain in the a**, but it was possible to do. Prototype in Symfony form refers to the dynamic fields that can be added/removed on the fly. I used Vuejs dynamic components to get around it. Whenever the user clicks on the add button, the form wrapper component automatically adds a child component dynamically that can be rendered by Vuejs (using &lt;code&gt;&amp;lt;component :is="something"&amp;gt;&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note 3:&lt;/strong&gt; Be careful with Vuejs dynamic components. I had to spend days to debug why part of my form was re-rendered every time I make any change to the form data. It turned out that I was missing keep-alive and I was not "caching" the dynamic components properly.&lt;/p&gt;

&lt;p&gt;I don't include any code sample for this here because the dump code that I'm using is rather hacky and only optimized for our app. If you want to see it please feel free to let me know.&lt;/p&gt;

&lt;h3&gt;
  
  
  II. Phase 2:
&lt;/h3&gt;

&lt;p&gt;In phase 2, I wanted to render the whole Symfony form using Vuejs (so no more twig). The reasons are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It's faster (Symfony form prototype can generate huge amount of code)&lt;/li&gt;
&lt;li&gt;It's easier to re-render part of the form&lt;/li&gt;
&lt;li&gt;It just feels better&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For this to work, I had to write a helper method in Symfony controller to dump the form view object via ajax request. This was quite simple but also a bit hacky. The form view object contains a huge amount of information, I had to cherry-pick only the necessary information I need.&lt;/p&gt;

&lt;p&gt;I also wrote some helper method inside my form component to replicate the functionality of Symfony's form_row, form_widget, ... twig helper methods. These helper methods loop through the block_prefixes (if you are Symfony dev you know what I'm talking about) to pick the exact template to use. These templates are stored as script snippets with the corresponding ids. I believe I could create separate components for each form(input) type but for now, this feels more natural to the team. I could copy whatever code we have on twig and with some minor tweaks turn it into Vuejs compatible code. &lt;/p&gt;

&lt;p&gt;I hope this helps someone struggling out there. I know I should share some code but at the moment the code is still unstable, messy and ugly and I feel shameful to share it. If you want though, please do let me know.&lt;/p&gt;

&lt;p&gt;Also, if there is a better way to integrate with Symfony form, please do share with me as well. I'm very new to Vuejs.&lt;/p&gt;

</description>
      <category>vue</category>
      <category>symfony</category>
      <category>form</category>
      <category>ajax</category>
    </item>
  </channel>
</rss>
