<?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: Rico Sta. Cruz</title>
    <description>The latest articles on DEV Community by Rico Sta. Cruz (@rstacruz).</description>
    <link>https://dev.to/rstacruz</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%2F210749%2F5a04873b-dab2-4b4e-b5c6-1900d644d9b4.jpeg</url>
      <title>DEV Community: Rico Sta. Cruz</title>
      <link>https://dev.to/rstacruz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rstacruz"/>
    <language>en</language>
    <item>
      <title>Why I’m moving from Jest to Vitest</title>
      <dc:creator>Rico Sta. Cruz</dc:creator>
      <pubDate>Thu, 07 Apr 2022 13:21:38 +0000</pubDate>
      <link>https://dev.to/rstacruz/why-im-moving-from-jest-to-vitest-27d7</link>
      <guid>https://dev.to/rstacruz/why-im-moving-from-jest-to-vitest-27d7</guid>
      <description>&lt;p&gt;I've always reached out to &lt;a href="https://jestjs.io/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt; for any JavaScript testing, but I think it's time to rethink that. I just discovered &lt;a href="https://vitest.dev/" rel="noopener noreferrer"&gt;Vitest&lt;/a&gt;, and thought I'd try it out in one of my projects. It feels like a test runner for 2022 - it covers everything Jest does, plus a few extras that just make it a great alternative.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F998qgqm1q2llkv661l0h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F998qgqm1q2llkv661l0h.png" alt="Section 1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  It has a UI!
&lt;/h2&gt;

&lt;p&gt;Vitest comes with a UI that runs in the browser. It can show code, and even print out &lt;code&gt;console.log()&lt;/code&gt; calls!&lt;/p&gt;

&lt;p&gt;This might seem excessive for those who prefer the command line, but it makes for a lot of convenient things like drilling down to specific tests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FPKpfZ94.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FPKpfZ94.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
☝Run `vitest --ui` to run the test UI in the browser.






&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnjny1r5hen7rbppx9hso.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnjny1r5hen7rbppx9hso.png" alt="Section 2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ES modules, TypeScript and more
&lt;/h2&gt;

&lt;p&gt;Vitest supports modern features like ES modules, TypeScript, JSX, PostCSS, async-await and more—all without the need for complex configuration. (&lt;a href="https://vitest.dev/guide/features.html#common-web-idioms-out-of-the-box" rel="noopener noreferrer"&gt;docs&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;In contrast, getting these things to work with Jest has often been frustrating. The most practical way is to &lt;a href="https://jestjs.io/docs/getting-started#using-babel" rel="noopener noreferrer"&gt;use Babel&lt;/a&gt; alongside Jest to compile JavaScript, and use workarounds to &lt;a href="https://jestjs.io/docs/webpack#mocking-css-modules" rel="noopener noreferrer"&gt;make Jest ignore CSS files&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With Vitest, it seems these things just work.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&lt;/span&gt;

&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;works&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;hello&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;, document.body&lt;/span&gt;&lt;span class="err"&gt;)
&lt;/span&gt;  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
☝ A test like this will require a Babel pipeline in Jest. In Vitest, it should work with the default config.






&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjp9p27qxbz9lw3nafoa0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjp9p27qxbz9lw3nafoa0.png" alt="Section 3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The API is Jest-compatible (mostly)
&lt;/h2&gt;

&lt;p&gt;Vitest makes migrating from Jest as easy as possible. It supports Jest assertions by default.&lt;/p&gt;

&lt;p&gt;That was exciting enough, but I was surprised to see that the Jest interop goes even further. Special functions like &lt;code&gt;jest.useFakeTimers()&lt;/code&gt; have equivalents Vitest as &lt;code&gt;vi.useFakeTimers()&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="cm"&gt;/* Vitest */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;spy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spyOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getApples&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;mockImplementation&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;apples&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="cm"&gt;/* Jest */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;spy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spyOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getApples&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;mockImplementation&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;apples&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
☝ Just change `jest` to `vi`.






&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4uv5lk77615zhfwxeay1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4uv5lk77615zhfwxeay1.png" alt="Section 4"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Jsdom is optional
&lt;/h2&gt;

&lt;p&gt;Vitest also supports browser emulation via Jsdom… and there’s more.&lt;/p&gt;

&lt;p&gt;Unlike Jest which always runs with Jsdom by default, Jsdom can be turned off in Vitest. In fact, there are options of what environment to emulate. As of v0.8, Vitest supports &lt;code&gt;node&lt;/code&gt;, &lt;code&gt;jsdom&lt;/code&gt; and &lt;code&gt;happy-dom&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="cm"&gt;/**
 * @vitest-environment jsdom
 */&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
☝ Adding this to the top of a test file enables Jsdom.






&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv73gusel2p8hj9yrj9u3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv73gusel2p8hj9yrj9u3.png" alt="Section 5"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  No global pollution
&lt;/h2&gt;

&lt;p&gt;Unlike Jest which automatically drops things into the global context (eg, &lt;code&gt;expect()&lt;/code&gt;, &lt;code&gt;describe()&lt;/code&gt;, etc), Vitest requires importing them in every test file. While this may be a bit more typing, I think it’s more explicit and follows principle of least surprise.&lt;/p&gt;

&lt;p&gt;It’s also possible to have them globalised automatically to make migration from Jest easier. (&lt;a href="https://vitest.dev/config/#globals" rel="noopener noreferrer"&gt;docs&lt;/a&gt;)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vitest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;My test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
☝ The functions `expect` and `test` are explicitly imported before use.






&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9waw39ra4mfg5lu7xvci.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9waw39ra4mfg5lu7xvci.png" alt="Section 6"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Parallel tests work great
&lt;/h2&gt;

&lt;p&gt;Vitest can run tests in parallel—and the feature is stable!&lt;/p&gt;

&lt;p&gt;While Jest has &lt;code&gt;test.concurrent&lt;/code&gt;, it’s been considered as “experimental” for as long as Jest has been around. Vitest’s counterpart of &lt;a href="https://vitest.dev/api/#test-concurrent" rel="noopener noreferrer"&gt;&lt;code&gt;test.concurrent&lt;/code&gt;&lt;/a&gt; seems to be considered stable.&lt;/p&gt;

&lt;p&gt;Vitest has multi-threaded support built in and is enabled by default. (&lt;a href="https://vitest.dev/guide/features.html#threads" rel="noopener noreferrer"&gt;docs&lt;/a&gt;)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="cm"&gt;/*
 * Vitest will attempt to run these tests
 * in parallel:
 */&lt;/span&gt;

&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;concurrent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;concurrent test 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/* ... */&lt;/span&gt;

&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;concurrent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;concurrent test 2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp2ibk6i7lxfbo0cg4rad.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp2ibk6i7lxfbo0cg4rad.png" alt="Section 7"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Thanks for reading!
&lt;/h2&gt;

&lt;p&gt;Thanks for checking out my post! I'm a web developer who loves open source and JavaScript. If you liked this post, consider &lt;a href="https://dev.to/rstacruz"&gt;following me on Dev.to (@rstacruz)&lt;/a&gt; or &lt;a href="https://twitter.com/rstacruz" rel="noopener noreferrer"&gt;Twitter (@rstacruz)&lt;/a&gt;!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://vitest.dev/" rel="noopener noreferrer"&gt;Vitest&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>vite</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Switching apps slows down my productivity (and how I fixed it)</title>
      <dc:creator>Rico Sta. Cruz</dc:creator>
      <pubDate>Mon, 04 Apr 2022 04:58:17 +0000</pubDate>
      <link>https://dev.to/rstacruz/switching-apps-slow-down-my-productivity-and-how-i-fixed-it-2anb</link>
      <guid>https://dev.to/rstacruz/switching-apps-slow-down-my-productivity-and-how-i-fixed-it-2anb</guid>
      <description>&lt;p&gt;Switching apps is something I do hundreds of times a day on both MacOS and Windows. I found a way to make this faster, which has made my workflow a lot more efficient.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FhsfyFU8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FhsfyFU8.png" alt="Image: alt-tab-tab-tab-tab..."&gt;&lt;/a&gt;&lt;/p&gt;
☝ Has this been as frustrating for me as anyone else?






&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F998qgqm1q2llkv661l0h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F998qgqm1q2llkv661l0h.png" alt="Section 1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Is switching apps really difficult?
&lt;/h2&gt;

&lt;p&gt;Well, just a bit. Not much, but small frustrations easily add up over time. Switching with a keyboard always required too much effort for me. I often try one of these, but each one requires some thinking (or typing):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;win-4&lt;/code&gt; to launch the 4th taskbar app &lt;em&gt;(Windows)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ctrl-alt-4&lt;/code&gt; using uBar to emulate Windows behaviour &lt;em&gt;(MacOS)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;alt-tab-tab-tab&lt;/code&gt; to switch to a window &lt;em&gt;(Windows and MacOS)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cmd-space firefox&lt;/code&gt; to use Spotlight &lt;em&gt;(MacOS)&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnjny1r5hen7rbppx9hso.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnjny1r5hen7rbppx9hso.png" alt="Section 2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My solution: fixed key bindings
&lt;/h2&gt;

&lt;p&gt;I settled a way that’s easier for me: shortcuts that always do one—and only one—thing. For example, &lt;code&gt;ctrl-win-w&lt;/code&gt; will always focus my web browser, where &lt;code&gt;alt-tab&lt;/code&gt; requires some thinking to figure out how many Tabs to press.&lt;/p&gt;

&lt;p&gt;The result: I save a second of thinking for every app switch I do. For something I do hundreds of times a day, it all adds up! 🎉&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FxCUMMtB.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FxCUMMtB.png" alt="Image: ctrl-win-W for Web, ctrl-win-V for Visual Studio Code, and more"&gt;&lt;/a&gt;&lt;/p&gt;
☝ Just a small selection of the shortcuts I use.






&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjp9p27qxbz9lw3nafoa0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjp9p27qxbz9lw3nafoa0.png" alt="Section 3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  MacOS via Raycast
&lt;/h2&gt;

&lt;p&gt;There are many ways this can be achieved in MacOS. The simplest one I think is with &lt;a href="https://www.raycast.com/" rel="noopener noreferrer"&gt;Raycast&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5vjl451sq4aqswe7gtfg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5vjl451sq4aqswe7gtfg.png" alt="Raycast shortcuts screen"&gt;&lt;/a&gt;&lt;/p&gt;
☝ Raycast allows defining shortcuts for many actions, including launching apps.






&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4uv5lk77615zhfwxeay1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4uv5lk77615zhfwxeay1.png" alt="Section 4"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  MacOS via Hammerspoon
&lt;/h2&gt;

&lt;p&gt;For my MacBook, I used &lt;a href="https://www.hammerspoon.org/" rel="noopener noreferrer"&gt;Hammerspoon&lt;/a&gt;, a hotkey automation suite for MacOS. Writing a Lua script to launch apps with hotkeys isn’t too difficult:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- ~/.hammerspoon/init.lua&lt;/span&gt;
&lt;span class="n"&gt;hs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hotkey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s2"&gt;"ctrl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"cmd"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="s2"&gt;"v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Visual Studio Code"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;hs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;launchOrFocus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Visual Studio Code"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;hs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hotkey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s2"&gt;"ctrl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"cmd"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="s2"&gt;"w"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Firefox"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;hs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;launchOrFocus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Firefox"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;hs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hotkey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s2"&gt;"ctrl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"cmd"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="s2"&gt;"s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Slack"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;hs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;launchOrFocus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Slack"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
☝A simple Hammerspoon script to launch apps from hotkeys. (Docs: &lt;a href="https://www.hammerspoon.org/docs/hs.application.html#launchOrFocus" rel="noopener noreferrer"&gt;launchOrFocus&lt;/a&gt;, &lt;a href="https://www.hammerspoon.org/docs/hs.hotkey.html#bind" rel="noopener noreferrer"&gt;bind&lt;/a&gt;)








&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv73gusel2p8hj9yrj9u3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv73gusel2p8hj9yrj9u3.png" alt="Section 5"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Windows via AutoHotkey
&lt;/h2&gt;

&lt;p&gt;For my Windows laptop, I used a powerful automation scripting language called &lt;a href="https://www.autohotkey.com/" rel="noopener noreferrer"&gt;AutoHotkey&lt;/a&gt;. Here’s an example that launches apps based on start menu items (&lt;code&gt;w&lt;/code&gt; and &lt;code&gt;o&lt;/code&gt;), URL (&lt;code&gt;c&lt;/code&gt;) and file path (&lt;code&gt;v&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;UserStartMenu := A_AppData . "\Microsoft\Windows\Start Menu\"
SysStartMenu := "C:\ProgramData\Microsoft\Windows\Start Menu\Programs"

; [w] Firefox (web)
^#w::LaunchOrFocus({ run: SysStartMenu . "Firefox", select: "ahk_exe firefox.exe" })

; [o] Obsidian
^#o::LaunchOrFocus({ run: UserStartMenu . "Programs\Obsidian", select: "ahk_exe Obsidian.exe" })

; [c] Calendar
^#c::LaunchOrFocus({ run: "outlookcal:" })

; [t] Terminal
^#v::LaunchOrFocus({ run: "wt.exe", select: "ahk_exe WindowsTerminal.exe" })

LaunchOrFocus(app) {
  selector := app["select"]
  If (selector and WinExist(selector))
    WinActivate,
  else
    Run % app["run"]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
☝A simple AutoHotkey script to launch apps from hotkeys using &lt;code&gt;WinActivate&lt;/code&gt; and &lt;code&gt;Run&lt;/code&gt;. Save it as &lt;em&gt;example.ahk&lt;/em&gt; and double-click on it to open in AutoHotkey.








&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9waw39ra4mfg5lu7xvci.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9waw39ra4mfg5lu7xvci.png" alt="Section 6"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My shortcuts
&lt;/h2&gt;

&lt;p&gt;I set up shortcuts for the apps I use 90% of the time. For anything not here, I would use Spotlight or Windows Search.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2F0pi5j0i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2F0pi5j0i.png" alt="Image: Shortcuts diagram"&gt;&lt;/a&gt;&lt;/p&gt;
☝I use the Colemak mod-DH layout, but this can work on any keyboard layout. (The &lt;code&gt;*&lt;/code&gt; keys are reserved for moving windows to the side of my screen, but that’s for another article!)






&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp2ibk6i7lxfbo0cg4rad.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp2ibk6i7lxfbo0cg4rad.png" alt="Section 7"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Thanks for reading!
&lt;/h2&gt;

&lt;p&gt;Thanks for checking out my post! I'm a web developer who loves open source and supercharging productivity. If you liked this post, consider &lt;a href="https://dev.to/rstacruz"&gt;following me on Dev.to (@rstacruz)&lt;/a&gt; or &lt;a href="https://twitter.com/rstacruz" rel="noopener noreferrer"&gt;Twitter (@rstacruz)&lt;/a&gt;!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.autohotkey.com/" rel="noopener noreferrer"&gt;Autohotkey&lt;/a&gt; - automation for Windows&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.raycast.com/" rel="noopener noreferrer"&gt;Raycast&lt;/a&gt; - app launcher for MacOS&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.hammerspoon.org/" rel="noopener noreferrer"&gt;Hammerspoon&lt;/a&gt; - automation for MacOS&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>productivity</category>
      <category>autohotkey</category>
      <category>macos</category>
    </item>
    <item>
      <title>Public CDN's aren't useful anymore</title>
      <dc:creator>Rico Sta. Cruz</dc:creator>
      <pubDate>Fri, 01 Apr 2022 02:30:33 +0000</pubDate>
      <link>https://dev.to/rstacruz/public-cdns-arent-useful-anymore-2b66</link>
      <guid>https://dev.to/rstacruz/public-cdns-arent-useful-anymore-2b66</guid>
      <description>&lt;p&gt;Public CDN’s were supposed to help page speed, but things have changed in 2019. Services like &lt;a href="https://developers.google.com/speed/libraries"&gt;Google Fonts&lt;/a&gt;, &lt;a href="https://cdnjs.com/"&gt;Cloudflare’s cdnjs&lt;/a&gt;, &lt;a href="https://www.jsdelivr.com/"&gt;jsDelivr&lt;/a&gt; and &lt;a href="https://developers.google.com/speed/libraries"&gt;Google Hosted Libraries&lt;/a&gt; may not help make sites load faster anymore.&lt;/p&gt;




&lt;h2&gt;
  
  
  Shared caches don’t work anymore
&lt;/h2&gt;

&lt;p&gt;Today, the primary advantage of public CDN’s is no longer supported by modern browsers.&lt;/p&gt;

&lt;p&gt;Resources (like .js files) loaded by a site the user visits will no longer be cached for other sites they visit. Browsers have stopped having shared caches around Sep 2019 (&lt;a href="https://chromestatus.com/feature/5730772021411840"&gt;Chrome 77&lt;/a&gt;, &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1536058"&gt;Firefox&lt;/a&gt;). This has all been done to address a cross-site leak security issue reported on March 2019:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.jefftk.com/p/shared-cache-is-going-away"&gt;Shared Cache is Going Away&lt;/a&gt; (jefftk.com)&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://sirdarckcat.blogspot.com/2019/03/http-cache-cross-site-leaks.html"&gt;sirdarckcat: HTTP Cache Cross-Site Leaks&lt;/a&gt; (sirdarckcat.blogspot.com)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  About public CDN’s
&lt;/h2&gt;

&lt;p&gt;CDN’s were supposed to help sites load faster. For example, a popular library like jQuery can be loaded from a CDN by one site, making it load faster for other sites the user will visit who would use the same CDN.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;☝Google has been running a CDN serving popular JavaScript libraries. (via &lt;a href="https://developers.google.com/speed/libraries"&gt;Google&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Other issues with public CDN's
&lt;/h2&gt;

&lt;p&gt;📉 &lt;em&gt;Downtime&lt;/em&gt; — Downtime in Public CDN’s will impair the service of your site. Compare this to something like npm or Rubygems where downtime will affect builds and deploys, but not users.&lt;/p&gt;

&lt;p&gt;⚠ &lt;em&gt;Blocked in some regions&lt;/em&gt; — There are countries that block Google domains, which will impair your site if it loads critical assets from Google Fonts or Google Hosted Libraries.&lt;/p&gt;

&lt;p&gt;🥷 &lt;em&gt;Resource integrity issues&lt;/em&gt; — In the event of a compromised public CDN, malicious code can be inserted into your site. This can be mitigated using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity"&gt;Subresource Integrity (SRI)&lt;/a&gt; (ie, &lt;code&gt;&amp;lt;script src="..." integrity="(sha384_hash_here)"&amp;gt;&lt;/code&gt;) but maintaining these can be a hassle.&lt;/p&gt;




&lt;h2&gt;
  
  
  Are public CDN’s still useful?
&lt;/h2&gt;

&lt;p&gt;While public CDN’s have been heavily nerfed, some have found it to be useful for other reasons.&lt;/p&gt;

&lt;p&gt;💻 &lt;em&gt;Code examples&lt;/em&gt; — Using Google Fonts can be useful in code examples. There are even CDN’s like &lt;a href="https://www.skypack.dev/"&gt;skypack&lt;/a&gt; that will create optimised versions of npm packages, allowing code examples to skip having build &amp;amp; compile pipelines.&lt;/p&gt;

&lt;p&gt;🏗 &lt;em&gt;Simplifying build pipelines&lt;/em&gt; — Tools like Rails’s &lt;a href="https://github.com/rails/importmap-rails"&gt;import-map&lt;/a&gt; recommend using a CDN like &lt;a href="https://jspm.org/"&gt;jspm&lt;/a&gt; to outsource to build step needed by some npm packages. Personally I find this questionable for security reasons, but some prefer to trade security for convenience.&lt;/p&gt;

&lt;p&gt;🔌 &lt;em&gt;Sidestepping max connections?&lt;/em&gt; — Browsers limit HTTP requests to 6 connections per domain, so having some assets served in a different domain can potentially have some advantages. In practice however, &lt;a href="https://en.wikipedia.org/wiki/HTTP_pipelining"&gt;HTTP/1.1 pipelining&lt;/a&gt; and &lt;a href="https://developers.google.com/web/fundamentals/performance/http2#request_and_response_multiplexing"&gt;HTTP/2.0 Multiplexing&lt;/a&gt; should already allow browsers to make multiple concurrent requests.&lt;/p&gt;




&lt;h2&gt;
  
  
  What do we do now?
&lt;/h2&gt;

&lt;p&gt;For production builds, self-hosting seems to be a much better alternative to using CDN’s.&lt;/p&gt;

&lt;p&gt;💡 &lt;em&gt;Self-hosted JavaScript&lt;/em&gt; — There are many options today for self-hosting npm packages.&lt;/p&gt;

&lt;p&gt;💅 &lt;em&gt;Self-hosted fonts&lt;/em&gt; — &lt;a href="https://fontsource.org/"&gt;Fontsource&lt;/a&gt; is an easy way to self-host Google Fonts (and more) without having to manually manage font files.&lt;/p&gt;

&lt;p&gt;⚡ &lt;em&gt;Use a CDN&lt;/em&gt; — Not a public CDN, but CDN services like &lt;a href="https://cloudflare.com"&gt;Cloudflare&lt;/a&gt; and &lt;a href="https://fastly.com"&gt;Fastly&lt;/a&gt; can make pages load fast (&amp;lt;100ms!). This will make self-hosting very viable.&lt;/p&gt;

&lt;p&gt;🔌 &lt;em&gt;Enable HTTP/2&lt;/em&gt; — It’s a great idea to support HTTP/2.0 across all steps in web hosting infrastructure. Cloudflare, for example, allows &lt;a href="https://www.cloudflare.com/website-optimization/http2/"&gt;enabling HTTP/2 support&lt;/a&gt; in their cache proxy service. &lt;/p&gt;




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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.section.io/blog/how-to-adapt-to-browser-shared-cache-going-away/"&gt;How to Adapt to Shared Cache Going Away | Section&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.jefftk.com/p/shared-cache-is-going-away"&gt;Shared Cache is Going Away&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=21429621"&gt;Shared Cache Is Going Away | Hacker News&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://sirdarckcat.blogspot.com/2019/03/http-cache-cross-site-leaks.html"&gt;sirdarckcat: HTTP Cache Cross-Site Leaks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cdn</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Guide: Netlify-to-Discord notifications</title>
      <dc:creator>Rico Sta. Cruz</dc:creator>
      <pubDate>Tue, 29 Mar 2022 11:44:29 +0000</pubDate>
      <link>https://dev.to/rstacruz/netlify-discord-notifications-54fa</link>
      <guid>https://dev.to/rstacruz/netlify-discord-notifications-54fa</guid>
      <description>&lt;p&gt;Discord is a great way to get Netlify notifications! I set up my own private server to collect notifications with my open source projects.&lt;/p&gt;

&lt;p&gt;There’s an official guide to &lt;a href="https://support.discord.com/hc/en-us/articles/228383668" rel="noopener noreferrer"&gt;set up GitHub notifications on Discord&lt;/a&gt;, but I like using it too for other things like monitoring Netlify deployments. Here's how I got it set up.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FKlBWm3T.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FKlBWm3T.png" alt="Screenshot: Discord notifications"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Solution: webhooks
&lt;/h2&gt;

&lt;p&gt;Discord supports any &lt;a href="https://discord.com/developers/docs/resources/webhook#execute-slackcompatible-webhook" rel="noopener noreferrer"&gt;Slack-compatible webhook&lt;/a&gt;. I used this to set up send Netlify notifications to Discord using Slack’s webhook format.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Create a webhook in Discord
&lt;/h3&gt;

&lt;p&gt;In Discord’s channel settings, go to “Integrations” and select “Create Webhook”. In the next screen, use “Copy Webhook URL” to copy the URL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FYuf79HS.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FYuf79HS.png" alt="Screenshot: integrations settings on Discord"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2F4GM2jRU.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2F4GM2jRU.png" alt="Screenshot: creating a webhook"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Site settings in Netlify
&lt;/h3&gt;

&lt;p&gt;Under Netlify’s “Site settings”, go to “Build &amp;amp; deploy” → “Deploy notifications”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FvB0vB6B.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FvB0vB6B.png" alt="Screenshot: Netlify site settings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Add a notification
&lt;/h3&gt;

&lt;p&gt;Under the “Outgoing notifications” section, click the “Add notification” button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FlwrXvf9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FlwrXvf9.png" alt="Screenshot: adding notifications"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Choose Slack integration
&lt;/h3&gt;

&lt;p&gt;In the dropdown, select “Slack integration.” (Yes, select “Slack” even if it’s Discord!)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FWkcI92w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FWkcI92w.png" alt="Screenshot: the “add notification” dropdown"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Add the URL
&lt;/h3&gt;

&lt;p&gt;Paste the webhook URL and add &lt;code&gt;/slack&lt;/code&gt; to the end. Don’t forget to change the “Event to listen for” dropdown.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FR6KiIr1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FR6KiIr1.png" alt="Screenshot: creating a new Slack integration"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  All done!
&lt;/h2&gt;

&lt;p&gt;New notifications should now show up on Discord.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FKlBWm3T.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FKlBWm3T.png" alt="Screenshot: Discord notifications"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>netlify</category>
      <category>discord</category>
    </item>
    <item>
      <title>Faster multi-line jumps in VSCode-Vim</title>
      <dc:creator>Rico Sta. Cruz</dc:creator>
      <pubDate>Tue, 29 Mar 2022 02:37:27 +0000</pubDate>
      <link>https://dev.to/rstacruz/faster-multi-line-jumps-in-vscode-vim-18dk</link>
      <guid>https://dev.to/rstacruz/faster-multi-line-jumps-in-vscode-vim-18dk</guid>
      <description>&lt;p&gt;One of the things that bothered me with VSCode-Vim was with how slow it was to use &lt;code&gt;(number)(arrow)&lt;/code&gt; (eg, &lt;code&gt;42(down)&lt;/code&gt;) to move multiple lines down. In the screencast below, notice how it goes line-by-line rather than skipping ahead instantly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FFRIxRsP.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FFRIxRsP.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;☝ Figure 1: VSCode scrolls slooowly line-by-line when pressing &lt;code&gt;42(down)&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Solution: use j/k
&lt;/h2&gt;

&lt;p&gt;TIL that VSCode-Vim already accounts for this with &lt;code&gt;hjkl&lt;/code&gt; movements, so &lt;code&gt;42(down)&lt;/code&gt; can be pressed at &lt;code&gt;42j&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FWOcSdkS.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FWOcSdkS.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;☝Figure 2: Using j/k keys (eg, &lt;code&gt;3j&lt;/code&gt; instead of &lt;code&gt;3(down)&lt;/code&gt;) hops to the target line instantly. I also did a trick to make this work with arrow keys (see below).&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Making it work with arrow keys
&lt;/h2&gt;

&lt;p&gt;To make this work with &lt;code&gt;(up)&lt;/code&gt; and &lt;code&gt;(down)&lt;/code&gt; arrow keys too, I rebound my arrow keys to j/k movements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;/*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;settings.json&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;*/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"vim.normalModeKeyBindings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Make&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"9j 9k"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;work&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;faster&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"before"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Down"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"after"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"j"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"before"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Up"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"after"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"k"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>vscode</category>
      <category>vim</category>
    </item>
    <item>
      <title>Windows Subsystem for Linux - explained by a Linux user</title>
      <dc:creator>Rico Sta. Cruz</dc:creator>
      <pubDate>Fri, 04 Oct 2019 20:59:27 +0000</pubDate>
      <link>https://dev.to/rstacruz/windows-subsystem-for-linux-explained-by-a-linux-user-39o3</link>
      <guid>https://dev.to/rstacruz/windows-subsystem-for-linux-explained-by-a-linux-user-39o3</guid>
      <description>&lt;p&gt;You can now run Linux apps on Windows thanks to a feature called &lt;a href="https://docs.microsoft.com/en-us/windows/wsl/faq" rel="noopener noreferrer"&gt;Windows Subsystem for Linux&lt;/a&gt; ("WSL" for short). But what is it, exactly? Is it an emulation layer like Wine? Is it a VM like VirtualBox? Is it dual-booting like Boot Camp? It's none of the above—it's something pretty unique and hard to explain.&lt;/p&gt;

&lt;p&gt;👇&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Next:&lt;/strong&gt; Let me try to explain it anyway!&lt;/p&gt;




&lt;center&gt;

&lt;br&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Ficon.png"&gt;&lt;br&gt;

## Ubuntu as a Windows app

&lt;/center&gt;

&lt;p&gt;To get Linux working on Windows, you first need to install Linux. Not from an ISO... but from the Microsoft Store (think: Windows's version of the Mac App Store). A full guide to &lt;a href="https://docs.microsoft.com/en-us/windows/wsl/install-win10" rel="noopener noreferrer"&gt;installing WSL&lt;/a&gt; is available from Microsoft.&lt;/p&gt;

&lt;p&gt;Linux distributions are available as apps. To be specific, they're command-line apps, just like &lt;code&gt;git&lt;/code&gt; or &lt;code&gt;vim&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Fget-ubuntu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Fget-ubuntu.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;
Many devs use Ubuntu as their Linux distribution in WSL.
&lt;/p&gt;




&lt;center&gt;👇&lt;/center&gt;

&lt;p&gt;&lt;strong&gt;Next:&lt;/strong&gt; To understand WSL, let's first look at how the Windows command line works.&lt;/p&gt;




&lt;center&gt;

&lt;br&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Ficon.png"&gt;&lt;br&gt;

## Command-line apps

&lt;/center&gt;

&lt;p&gt;Windows has support command line interface (CLI) apps, just like Linux. In fact, many built-in system utilities are CLI apps.&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Try this:&lt;/strong&gt; press &lt;code&gt;Win&lt;/code&gt; + &lt;code&gt;R&lt;/code&gt;, then run &lt;code&gt;ping 8.8.8.8&lt;/code&gt;. It will open a new window.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Frun-ping.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Frun-ping.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;
&lt;em&gt;ping.exe&lt;/em&gt; is a built-in command line application.
&lt;/p&gt;




&lt;p&gt;👇 &lt;strong&gt;Next:&lt;/strong&gt; Let's see what makes this window work.&lt;/p&gt;




&lt;center&gt;

&lt;br&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Ficon.png"&gt;&lt;br&gt;

## Windows console host

&lt;/center&gt;

&lt;p&gt;CLI apps are ran inside the &lt;a href="https://docs.microsoft.com/en-us/previous-versions/orphan-topics/ws.11/mt427362(v=ws.11)?redirectedfrom=MSDN" rel="noopener noreferrer"&gt;&lt;em&gt;Windows console host&lt;/em&gt;&lt;/a&gt;. The console host, or &lt;em&gt;conhost.exe&lt;/em&gt;, is a GUI app that draws a terminal inteface in a graphical window.&lt;/p&gt;

&lt;p&gt;💡&lt;strong&gt;Try this:&lt;/strong&gt; open the task manager (&lt;code&gt;Ctrl&lt;/code&gt; + &lt;code&gt;Shift&lt;/code&gt; + &lt;code&gt;Esc&lt;/code&gt;). Now run &lt;code&gt;ping -t 8.8.8.8&lt;/code&gt;. You'll see a new application in the task manager called &lt;em&gt;TCP/IP Ping Command&lt;/em&gt;. Under this group are 2 processes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;ping.exe&lt;/em&gt;—the command you just ran; and&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;conhost.exe&lt;/em&gt;—also known as &lt;em&gt;Console Window Host&lt;/em&gt;, the GUI that shows ping's output.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Fping-task-manager.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Fping-task-manager.png" alt="Windows Task Manager showing two processes: conhost.exe and ping.exe"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;
&lt;em&gt;ping.exe&lt;/em&gt; is running alongside the &lt;em&gt;conhost.exe&lt;/em&gt; GUI.
&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;In Linux terms:&lt;/strong&gt; Think of &lt;em&gt;conhost.exe&lt;/em&gt; as a terminal emulator, like &lt;a href="https://en.m.wikipedia.org/wiki/Xterm" rel="noopener noreferrer"&gt;XTerm&lt;/a&gt; might be for Linux. It's a graphical UI that shows terminal output. &lt;em&gt;ping.exe&lt;/em&gt; runs on &lt;em&gt;conhost.exe&lt;/em&gt; in the same way &lt;em&gt;/usr/bin/ping&lt;/em&gt; runs inside &lt;em&gt;Xterm&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;👇 &lt;strong&gt;Next:&lt;/strong&gt; Let's see how the Windows Command Prompt works.&lt;/p&gt;




&lt;center&gt;

&lt;br&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Ficon.png"&gt;&lt;br&gt;

## Cmd.exe on Conhost

&lt;/center&gt;

&lt;p&gt;All CLI apps open in &lt;em&gt;conhost.exe&lt;/em&gt;. This includes the Windows Command Prompt, or &lt;em&gt;cmd.exe&lt;/em&gt;—which is a CLI app, just like &lt;em&gt;ping.exe&lt;/em&gt;!&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Try this:&lt;/strong&gt; Go to &lt;code&gt;Win&lt;/code&gt; + &lt;code&gt;R&lt;/code&gt; and run &lt;code&gt;cmd.exe&lt;/code&gt;. You'll see this open in the same Windows &lt;em&gt;console host&lt;/em&gt; window that &lt;code&gt;ping.exe&lt;/code&gt; opened.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Frun-cmd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Frun-cmd.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;
cmd.exe opens in a &lt;em&gt;Conhost&lt;/em&gt; window.
&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;In Linux terms:&lt;/strong&gt; Think of &lt;em&gt;cmd.exe&lt;/em&gt; like the Bash shell. A terminal window in Linux will run Bash, and will close the window when Bash exits. &lt;em&gt;cmd.exe&lt;/em&gt; (the shell) and &lt;em&gt;conhost.exe&lt;/em&gt; (the terminal GUI) works the same way.&lt;/p&gt;

&lt;center&gt;👇&lt;/center&gt;

&lt;p&gt;&lt;strong&gt;Next:&lt;/strong&gt; This may be the case for the Command Prompt, but why does Powershell's window look different?&lt;/p&gt;




&lt;center&gt;

&lt;br&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Ficon.png"&gt;&lt;br&gt;

## Powershell's blue window

&lt;/center&gt;

&lt;p&gt;If you open Powershell, you'll notice that the window is blue. It's not a different app, it's still the same &lt;em&gt;conhost.exe&lt;/em&gt; with different settings! You'll notice it has the same menus as &lt;em&gt;cmd.exe&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Powershell.exe&lt;/code&gt; is a CLI app, too—just like &lt;code&gt;cmd.exe&lt;/code&gt;. &lt;em&gt;Conhost&lt;/em&gt; simply lets you choose different settings per app. It simply comes with different color settings for Powershell by default.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Fcmd-and-powershell.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Fcmd-and-powershell.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;
Powershell's &lt;em&gt;Properties&lt;/em&gt; window lets you configure &lt;em&gt;conhost&lt;/em&gt; settings.
&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;In Linux terms:&lt;/strong&gt; Most terminal emulators on Linux would support different profiles, and you may be assigning different profiles per command. Windows's &lt;em&gt;conhost.exe&lt;/em&gt; has a different profile for Powershell that has its &lt;em&gt;Screen Background&lt;/em&gt; set to blue.&lt;/p&gt;

&lt;center&gt;👇&lt;/center&gt;

&lt;p&gt;&lt;strong&gt;Next:&lt;/strong&gt; Is WSL just like &lt;em&gt;cmd.exe&lt;/em&gt; and Powershell then?&lt;/p&gt;




&lt;center&gt;

&lt;br&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Ficon.png"&gt;&lt;br&gt;

## The WSL launcher: `wsl.exe`

&lt;/center&gt;

&lt;p&gt;Yes! You can think of WSL as another CLI application just like &lt;em&gt;cmd.exe&lt;/em&gt; and &lt;em&gt;powershell.exe&lt;/em&gt;. Just like other CLI apps, you can run &lt;code&gt;wsl.exe&lt;/code&gt;. This is the &lt;em&gt;WSL Launcher&lt;/em&gt;, which boots up the WSL platform and drops you into the bash (your user's shell by default).&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Try this:&lt;/strong&gt; Try running &lt;code&gt;wsl.exe&lt;/code&gt; via &lt;code&gt;Win&lt;/code&gt; + &lt;code&gt;R&lt;/code&gt;. This should get you a Linux bash prompt running inside a &lt;em&gt;conhost.exe&lt;/em&gt; window. Seems very similar to Cmd and Powershell, doesn't it?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Frun-wsl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Frun-wsl.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;
Running &lt;code&gt;wsl&lt;/code&gt; gets you a &lt;em&gt;conhost&lt;/em&gt; window, just like &lt;em&gt;cmd.exe&lt;/em&gt;.
&lt;/p&gt;




&lt;center&gt;👇&lt;/center&gt;

&lt;p&gt;&lt;strong&gt;Next:&lt;/strong&gt; Let's try mixing all these together.&lt;/p&gt;




&lt;center&gt;

&lt;br&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Ficon.png"&gt;&lt;br&gt;

## Shells inside shells

&lt;/center&gt;

&lt;p&gt;Windows's &lt;em&gt;cmd.exe&lt;/em&gt; and &lt;em&gt;powershell.exe&lt;/em&gt; can run command line applications. You can use it to run &lt;code&gt;ping.exe&lt;/code&gt;, &lt;code&gt;chkdsk.exe&lt;/code&gt;, or—wouldn't you know it—even &lt;code&gt;wsl.exe&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Try this:&lt;/strong&gt; Try running &lt;code&gt;wsl.exe&lt;/code&gt; or &lt;code&gt;bash.exe&lt;/code&gt; from within a Command Prompt (&lt;em&gt;cmd.exe&lt;/em&gt;). In fact, try running &lt;code&gt;wsl.exe&lt;/code&gt; inside &lt;code&gt;powershell.exe&lt;/code&gt; inside &lt;code&gt;cmd.exe&lt;/code&gt;, or any combination above! Typing &lt;code&gt;exit&lt;/code&gt; will bring you one level out.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Fnested-shells.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Fnested-shells.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In Linux terms:&lt;/strong&gt; Think of them just like shells. Windows's &lt;em&gt;Cmd&lt;/em&gt; might be like Bash, and &lt;em&gt;Powershell&lt;/em&gt; might be &lt;a href="https://fishshell.com" rel="noopener noreferrer"&gt;Fish&lt;/a&gt; or &lt;a href="https://en.wikipedia.org/wiki/Z_shell" rel="noopener noreferrer"&gt;Zsh&lt;/a&gt;. &lt;code&gt;wsl.exe&lt;/code&gt; works the same way.&lt;/p&gt;

&lt;center&gt;👇&lt;/center&gt;

&lt;p&gt;&lt;strong&gt;Next:&lt;/strong&gt; Why do the backslashes (&lt;code&gt;\&lt;/code&gt;) in Windows appear as forward slashes (&lt;code&gt;/&lt;/code&gt;) in WSL?&lt;/p&gt;




&lt;center&gt;

&lt;br&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Ficon.png"&gt;&lt;br&gt;

## The WSL filesystem

&lt;/center&gt;

&lt;p&gt;WSL has its own filesystem! If you do &lt;code&gt;ls /&lt;/code&gt; inside WSL, you'll find &lt;code&gt;/usr&lt;/code&gt;, &lt;code&gt;/bin&lt;/code&gt; and the other usual suspects in a Linux filesystem. This is a full POSIX-compliant filesystem managed by WSL, away from the limitations of your Windows's NTFS.&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Try this:&lt;/strong&gt; Go to your Linux's home directory with &lt;code&gt;cd&lt;/code&gt;. Create two files with the same filename, but different case: &lt;code&gt;touch xyz.txt XYZ.TXT&lt;/code&gt;. These two files can't co-exist in Windows's case-insensitive filesystem, can it? They will live happily inside WSL just fine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Fcase-sensitive-files.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Fcase-sensitive-files.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In Linux terms:&lt;/strong&gt; Think of WSL as a separate Linux system—a bit like a VirtualBox VM. It has its own filesystem, processes, &lt;code&gt;/dev&lt;/code&gt; devices. Running &lt;code&gt;wsl.exe&lt;/code&gt; will tunnel you into this Linux subsystem.&lt;/p&gt;

&lt;center&gt;👇&lt;/center&gt;

&lt;p&gt;&lt;strong&gt;Next:&lt;/strong&gt; So is it a virtual machine?&lt;/p&gt;




&lt;center&gt;

&lt;br&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Ficon.png"&gt;&lt;br&gt;

## Linux in a box

&lt;/center&gt;

&lt;p&gt;Not only does WSL have its own filesystem, it's a full Linux system that runs as an app in Windows! It may be easy to think it's like VirtualBox, but it's not a VM.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why is it not a VM?&lt;/strong&gt; There's no CPU or hardware emulation involved like in a VM. A whole Linux system runs like any other app in Windows.&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Try this:&lt;/strong&gt;  Run &lt;code&gt;htop&lt;/code&gt; inside WSL (you may need to install it first), and view it as a tree (&lt;code&gt;shift-T&lt;/code&gt;). It has a whole process tree, even with an &lt;code&gt;/init&lt;/code&gt; process! You'll see your machine's full CPU and memory capacity—it's not pre-allocated, unlike a VM. It shares these hardware resources just as any other Windows app would.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Fhtop.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Fhtop.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In Linux terms:&lt;/strong&gt; On a typical system, Linux's entry point would be in &lt;em&gt;/boot/vmlinuz-linux&lt;/em&gt;, which is fired by a bootloader like GRUB. Think of WSL as a version of this packaged as a &lt;em&gt;wsl.exe&lt;/em&gt; file. The whole Linux subsystem will be running as a process inside Windows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note about WSL2:&lt;/strong&gt; There are two versions of WSL. The new experimental version, &lt;a href="https://docs.microsoft.com/en-us/windows/wsl/wsl2-install" rel="noopener noreferrer"&gt;WSL2&lt;/a&gt;, actually works as a Virtual Machine.&lt;/p&gt;

&lt;center&gt;👇&lt;/center&gt;

&lt;p&gt;&lt;strong&gt;Next:&lt;/strong&gt; If WSL is a separate subsystem from your Windows environment, how do they share files?&lt;/p&gt;




&lt;center&gt;

&lt;br&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Ficon.png"&gt;&lt;br&gt;

## Windows files inside WSL

&lt;/center&gt;

&lt;p&gt;Your Windows files are visible inside WSL under &lt;code&gt;/mnt/c&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Try these:&lt;/strong&gt; Here are some experiments you can try inside WSL:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Case insensitive files:&lt;/strong&gt; In WSL, try &lt;code&gt;cd /mnt/c/Windows&lt;/code&gt; and &lt;code&gt;cd /mnt/c/WINDOWS&lt;/code&gt;. They'll both work! The Windows filesystem you're accessing in &lt;code&gt;/mnt/c&lt;/code&gt; is case-insensitive.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Check mount points:&lt;/strong&gt; Run &lt;code&gt;findmnt&lt;/code&gt;. You'll see &lt;code&gt;/mnt/c&lt;/code&gt; is mounted as &lt;em&gt;drvfs&lt;/em&gt;, just as how you would mount a drive in Linux.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Two home directories:&lt;/strong&gt; Look at &lt;code&gt;/mnt/c/Users&lt;/code&gt;. You'll see you have 2 home directories: your WSL/Linux one in &lt;code&gt;/home&lt;/code&gt;, and your Windows one in &lt;code&gt;/mnt/c/Users&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Permissions won't work:&lt;/strong&gt; Try to make a file in &lt;code&gt;/mnt/c&lt;/code&gt; and run &lt;code&gt;chmod&lt;/code&gt; to change its permissions. It won't work—the filesystem these files live on is NTFS, which doesn't support UNIX-style permissions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Ffindmnt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Ffindmnt.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;findmnt&lt;/em&gt; will tell you where &lt;code&gt;/mnt/c&lt;/code&gt; comes from.&lt;/p&gt;




&lt;center&gt;👇&lt;/center&gt;

&lt;p&gt;&lt;strong&gt;Next:&lt;/strong&gt; We can see Windows files in WSL. Can we see WSL files in Windows?&lt;/p&gt;




&lt;center&gt;

&lt;br&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Ficon.png"&gt;&lt;br&gt;

## WSL files from Windows

&lt;/center&gt;

&lt;p&gt;WSL exposes your files as a network resource in &lt;code&gt;\\wsl$&lt;/code&gt;. (The actual files live &lt;a href="https://superuser.com/a/1280916" rel="noopener noreferrer"&gt;somewhere&lt;/a&gt; in &lt;code&gt;C:\Windows&lt;/code&gt;, though it's not a good idea to use them directly.)&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Try this:&lt;/strong&gt; Open Windows Explorer. In the location bar, type in &lt;code&gt;\\wsl$\Ubuntu&lt;/code&gt;. This should get you access to the WSL filesystem as a network folder.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Fexplore-ubuntu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Fexplore-ubuntu.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In Linux terms:&lt;/strong&gt;  &lt;code&gt;\\wsl$\Ubuntu&lt;/code&gt; is called a UNC path, which is Windows's way of accessing network resources. Think of it like &lt;code&gt;smb://wsl/Ubuntu&lt;/code&gt;.&lt;/p&gt;




&lt;center&gt;

&lt;br&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Ficon.png"&gt;&lt;br&gt;

## Running Windows apps in WSL

&lt;/center&gt;

&lt;p&gt;You can run Windows &lt;code&gt;*.exe&lt;/code&gt; programs inside WSL. It will simply open them in Windows, just as you would have ran those programs from Windows itself.&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Try this:&lt;/strong&gt; In WSL, type &lt;code&gt;notepad.exe&lt;/code&gt;. In fact, you can even try running &lt;code&gt;cmd.exe&lt;/code&gt;—this should get you a Windows command prompt! To see how this works, try &lt;code&gt;which notepad.exe&lt;/code&gt;, which shows that it's simply running &lt;code&gt;/mnt/c/WINDOWS/system32/notepad.exe&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;user@desktop ~$ notepad.exe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;In Linux terms:&lt;/strong&gt; Linux can run ELF binaries (ie, Linux's native executable format). Once it finds a PE32+ binary (ie, Windows's format), it'll simply tell Windows to open it outside of WSL. Also, Windows's &lt;code&gt;%PATH%&lt;/code&gt; carries over into Bash's &lt;code&gt;$PATH&lt;/code&gt;, making the system &lt;code&gt;.exe&lt;/code&gt; files available anywhere in WSL.&lt;/p&gt;




&lt;center&gt;

&lt;br&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Ficon.png"&gt;&lt;br&gt;

## Running WSL apps in Windows

&lt;/center&gt;

&lt;p&gt;Linux apps can be ran from Windows using &lt;code&gt;wsl.exe&lt;/code&gt;, the WSL launcher. This starts up the WSL subsystem (if it hasn't been yet) and runs a command from within it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try this:&lt;/strong&gt; Open a command prompt (&lt;code&gt;Win&lt;/code&gt;+&lt;code&gt;R&lt;/code&gt; to run &lt;code&gt;cmd.exe&lt;/code&gt;), then type: &lt;code&gt;wsl ls /&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Microsoft Windows [Version 10.0.18985.1]
(c) 2019 Microsoft Corporation. All rights reserved.

C:\&amp;gt;wsl ls /
bin/   dev/  home/  lib/    lost+found/  mnt/  proc/  run/
boot/  etc/  init*  lib64/  media/       opt/  root/  sbin/
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;center&gt;👇&lt;/center&gt;

&lt;p&gt;&lt;strong&gt;Next:&lt;/strong&gt; Can we replace conhost?&lt;/p&gt;

&lt;center&gt;

&lt;br&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Ficon.png"&gt;&lt;br&gt;

## Alternatives to _conhost_

&lt;/center&gt;

&lt;p&gt;You don't need to use &lt;em&gt;conhost.exe&lt;/em&gt; to run CLI apps. You can run them in third party terminal emulators. There's &lt;a href="https://dev.towsltty"&gt;wsltty&lt;/a&gt; (based on Cygwin's mintty), &lt;a href="https://dev.toterminus"&gt;Terminus&lt;/a&gt; (an Electron-basde terminal), &lt;a href="https://dev.toconemu"&gt;Conemu&lt;/a&gt; (supports tabs and panes), and a few more.&lt;/p&gt;

&lt;p&gt;Any of these apps can run any CLI application. They often usually come with built-in shortcuts for cmd, Powershell, WSL, and possibly a few others.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In Linux terms:&lt;/strong&gt; Just like XTerm has many alternatives, conhost has its own alternatives as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Fwindows-terminal.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Fwindows-terminal.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;
Windows Terminal is an alternative to conhost. It supports WSL, Powershell, cmd, and more.
&lt;/p&gt;




&lt;center&gt;👇&lt;/center&gt;

&lt;p&gt;&lt;strong&gt;Next:&lt;/strong&gt; Let's recap what we know so far.&lt;/p&gt;




&lt;center&gt;

&lt;br&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fricostacruz.com%2Fdev-posts%2Fwsl-explained%2Ficon.png"&gt;&lt;br&gt;

## Recap

&lt;/center&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ubuntu is a command-line app.&lt;/strong&gt; It's installed from the Microsoft Store.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Windows provides &lt;code&gt;wsl.exe&lt;/code&gt; that launches an installed Linux distribution&lt;/strong&gt; (Ubuntu in this case). This is a command-line program that brings you to a Bash prompt. There's also &lt;code&gt;bash.exe&lt;/code&gt;, which does the same thing (it's like an alias for &lt;em&gt;"wsl.exe bash"&lt;/em&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CLI apps:&lt;/strong&gt; are ran inside &lt;code&gt;conhost.exe&lt;/code&gt;, the built-in Windows terminal. There are alternatives to this that developers might like better.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Environments:&lt;/strong&gt; &lt;code&gt;cmd.exe&lt;/code&gt;, &lt;code&gt;powershell.exe&lt;/code&gt;, and &lt;code&gt;wsl.exe&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;WSL launcher:&lt;/strong&gt; &lt;code&gt;wsl.exe&lt;/code&gt; runs the WSL subsystem and drops you into a Bash prompt. It's just a CLI app.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>linux</category>
      <category>windows</category>
      <category>wsl</category>
    </item>
    <item>
      <title>What media query breakpoints should I use?</title>
      <dc:creator>Rico Sta. Cruz</dc:creator>
      <pubDate>Mon, 12 Aug 2019 07:41:35 +0000</pubDate>
      <link>https://dev.to/rstacruz/what-media-query-breakpoints-should-i-use-292c</link>
      <guid>https://dev.to/rstacruz/what-media-query-breakpoints-should-i-use-292c</guid>
      <description>&lt;p&gt;Responsive design calls for a lot of media queries. This is universally agreed upon, but should we write &lt;em&gt;min-width&lt;/em&gt; or &lt;em&gt;max-width&lt;/em&gt;? Should we use &lt;code&gt;768px&lt;/code&gt; or &lt;code&gt;780px&lt;/code&gt;? There's a lot of variance here, so I went to dig up to see if there's an established consensus on the topic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c"&gt;/* ??? */&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What are we designing for?
&lt;/h2&gt;

&lt;p&gt;Before we can figure out what media query breakpoints to use, we need to look at what devices we're designing for.&lt;/p&gt;

&lt;p&gt;I've dug into some common device resolutions, and most can be grouped into categories. I've listed these categories, along with the resolutions they cater to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mobile portait&lt;/strong&gt; (320px to 414px) &lt;br&gt; For devices with 4" to 6.9" screens.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mobile landscape&lt;/strong&gt; (568px to 812px) &lt;br&gt; Same, but landscape.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tablet portait&lt;/strong&gt; (768px to 834px) &lt;br&gt; For devices 7" to 10"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tablet landscape&lt;/strong&gt; (1024px to 1112px) &lt;br&gt; Ditto, but also 12" tablets on portrait&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Laptop &amp;amp; desktop displays&lt;/strong&gt; (1200px+) &lt;br&gt; Varies a lot, but is usually 1200px and above&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;






&lt;h2&gt;
  
  
  Devices
&lt;/h2&gt;

&lt;p&gt;Let's look at a few iOS devices. While Android devices are important too, they have a lot of variance—device DPI's are adjustable in most phones. Most Android phones ship with defaults that are comparable to iOS's anyway, so let's look at those.&lt;/p&gt;

&lt;p&gt;Here's a list of some common devices, along with their &lt;a href="https://en.wikipedia.org/wiki/Device-independent_pixel"&gt;device-independent pixel widths&lt;/a&gt;: &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Width&lt;/th&gt;
&lt;th&gt;Device&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mobile, portrait&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;320px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;iPhone SE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;375px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;iPhone 6, 7, 8, X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;414px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;iPhone 8 Plus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mobile, landscape&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;568px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;iPhone SE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;667px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;iPhone 6, 7, 8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;736px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;iPhone 8 Plus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;812px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;iPhone X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tablet, portrait&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;768px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;iPad Air, iPad Mini, iPad Pro 9"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;834px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;iPad Pro 10"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tablet, landscape&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1024px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;iPad Air, iPad Mini, iPad Pro 9"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1024px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;iPad Pro 12" (portrait)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1112px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;iPad Pro 10"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Laptop displays&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1366px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;HD laptops (768p)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1366px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;iPad Pro 12" (landscape)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1440px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;13" MacBook Pro (2x scaling)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Desktop displays&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1680px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;13" MacBook Pro (1.5x scaling)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1920px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1080p displays&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;






&lt;h2&gt;
  
  
  The most common breakpoints
&lt;/h2&gt;

&lt;p&gt;I took a look at some of the most popular CSS frameworks on 2019 (and some from the past) to see what breakpoints they use. Most of them use the same points, with a small bit of variance.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Framework&lt;/th&gt;
&lt;th&gt;Small&lt;/th&gt;
&lt;th&gt;Medium&lt;/th&gt;
&lt;th&gt;Large&lt;/th&gt;
&lt;th&gt;Exra large&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Bulma&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;min: 769px&lt;/code&gt; &lt;br&gt; ("mobile")&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;min: 1024px&lt;/code&gt; &lt;br&gt; ("desktop")&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;min: 1216px&lt;/code&gt; &lt;br&gt; ("fullhd")&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bootstrap 3&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;&lt;code&gt;min: 768px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;min: 992px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;min: 1200px&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bootstrap 4&lt;/td&gt;
&lt;td&gt;&lt;code&gt;min: 576px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;min: 768px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;min: 992px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;min: 1200px&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tailwind&lt;/td&gt;
&lt;td&gt;&lt;code&gt;min: 576px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;min: 768px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;min: 992px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;min: 1200px&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Zurb Foundation&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;&lt;code&gt;min: 640px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;min: 1024px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;min: 1200px&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  768px, 992px, 1200px
&lt;/h3&gt;

&lt;p&gt;Many frameworks use &lt;code&gt;768px&lt;/code&gt;, &lt;code&gt;992px&lt;/code&gt; and &lt;code&gt;1200px&lt;/code&gt;. This has been Bootstrap 3's default breakpoints, and seems to be considered sensible enough to have been adopted by other projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  No small breakpoints?
&lt;/h3&gt;

&lt;p&gt;Some opt not to have breakpoints below 700px. This is likely taken from Bootstrap 3, which advocated making the mobile landscape view the same as the portrait view. Bootstrap 4 has since changed their position on this, which I personally agree with—seeing tall headers on a landscape screen is pretty annoying!&lt;/p&gt;

&lt;h3&gt;
  
  
  Where did 576px come from?
&lt;/h3&gt;

&lt;p&gt;Before Bootstrap 4 added the &lt;code&gt;576px&lt;/code&gt; breakpoint, &lt;code&gt;480px&lt;/code&gt; was a &lt;a href="https://github.com/twbs/bootstrap/issues/10203"&gt;popular choice&lt;/a&gt;. 576px was eventually chosen since it was &lt;a href="https://github.com/twbs/bootstrap/issues/21333"&gt;roughly halfway&lt;/a&gt; between 320px and 768px (+32px). I personally don't think choosing 576px over 480px is a big deal (or the other way around); either one should be enough to cover the 414px width of the iPhone 8 Plus. However, I prefer &lt;code&gt;480px&lt;/code&gt; since 576px still covers the iPhone SE landscape view.&lt;/p&gt;

&lt;h3&gt;
  
  
  640px
&lt;/h3&gt;

&lt;p&gt;Zurb's &lt;code&gt;640px&lt;/code&gt; breakpoint is an interesting choice. It covers both tablet-portait and (most of) mobile-landscape.&lt;/p&gt;




&lt;h2&gt;
  
  
  So what should I use?
&lt;/h2&gt;

&lt;p&gt;This is mostly subjective and may depend on what screens you would design for. I use this set of breakpoints as a starting point, and I can recommend them for most projects.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Breakpoint&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;(default)&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;Mobile-portrait&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;min-width: &lt;code&gt;480px&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Mobile-landscape (and larger)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;min-width: &lt;code&gt;768px&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Tablet-portrait (and larger)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;min-width: &lt;code&gt;992px&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Tablet-landscape (and larger)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;min-width: &lt;code&gt;1200px&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Laptops (and langer)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Avoid max-width
&lt;/h3&gt;

&lt;p&gt;I prefer only using &lt;code&gt;min-width&lt;/code&gt; and avoiding &lt;code&gt;max-width&lt;/code&gt; as much as possible. Mixing min-width and max-width can make CSS code shorter, but much more difficult to read.&lt;/p&gt;

&lt;h3&gt;
  
  
  Offset your max-widths
&lt;/h3&gt;

&lt;p&gt;If you must you &lt;code&gt;max-width&lt;/code&gt;, be sure to offset it by at least 0.02px. That is, use &lt;code&gt;max-width: 479.98px&lt;/code&gt; instead of &lt;code&gt;max-width: 480px&lt;/code&gt;, since the latter will have a small overlap with &lt;code&gt;min-width: 480px&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  480px or 576px?
&lt;/h3&gt;

&lt;p&gt;I suggest using &lt;code&gt;480px&lt;/code&gt; instead of &lt;code&gt;576px&lt;/code&gt; simply because it would cover smaller phones as well (eg, iPhone SE).&lt;/p&gt;

&lt;h3&gt;
  
  
  Should I use 768px?
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;min-width: 768px&lt;/code&gt; might not be as useful as most would think. If you're designing for tablet-portrait, consider using &lt;code&gt;min-width: 480px&lt;/code&gt;, it might look good on mobile-landscape as well. Zurb Foundation seems to promote this idea of co-designing for mobile-landscape + tablet-portait too, considering they use &lt;code&gt;640px&lt;/code&gt; as a breakpoint.&lt;/p&gt;

&lt;h3&gt;
  
  
  The mystery of 768px
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;min-width: 768px&lt;/code&gt; breakpoint is often described in guides as "tablet landscape". This is misleading, because it also matches tablet-portrait mode as well. Use &lt;code&gt;min-width: 992px&lt;/code&gt; if you need to target tablet-landscape. (You can also use &lt;code&gt;769px&lt;/code&gt;, but that won't cover iPad Pro 10".)&lt;/p&gt;

&lt;h2&gt;
  
  
  How should I name them?
&lt;/h2&gt;

&lt;p&gt;I personally don't like calling things &lt;code&gt;small&lt;/code&gt;, &lt;code&gt;medium&lt;/code&gt; and &lt;code&gt;large&lt;/code&gt;. These words can be ambiguous; does an iPad Pro 10" count as medium or large? Would the iPhone SE be counted as extra small? These words are relative, and their subjectiveness can cause some confusion.&lt;/p&gt;

&lt;p&gt;I'm not a fan of calling them &lt;code&gt;mobile&lt;/code&gt;, &lt;code&gt;tablet&lt;/code&gt; and so on, either. The iPad Pro 12" is a tablet, but why can you only target it with a &lt;code&gt;desktop&lt;/code&gt; media query? The Samsung Note is technically a phone, but why is it covered with &lt;code&gt;tablet&lt;/code&gt;? Does &lt;code&gt;tablet&lt;/code&gt; account for landscape or portrait? The lines between device classifications are a bit blurry nowadays.&lt;/p&gt;

&lt;p&gt;Instead, I propose calling it with more generic names. Most designers are intimately familiar with "how 700px feels like", so I think that would make a more appropriate name. I like naming them by their closest hundredths like so.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@custom-media&lt;/span&gt; &lt;span class="n"&gt;--viewport-4&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;480px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;@custom-media&lt;/span&gt; &lt;span class="n"&gt;--viewport-7&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;768px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;@custom-media&lt;/span&gt; &lt;span class="n"&gt;--viewport-9&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;992px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;@custom-media&lt;/span&gt; &lt;span class="n"&gt;--viewport-12&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1200px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--viewport-4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Thank you!
&lt;/h3&gt;

&lt;p&gt;I hope you'll find all these helpful. References:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bulma.io/documentation/overview/responsiveness/"&gt;https://bulma.io/documentation/overview/responsiveness/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://getbootstrap.com/docs/3.4/css/"&gt;https://getbootstrap.com/docs/3.4/css/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://getbootstrap.com/docs/4.3/layout/overview/#responsive-breakpoints"&gt;https://getbootstrap.com/docs/4.3/layout/overview/#responsive-breakpoints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://foundation.zurb.com/sites/docs/media-queries.html"&gt;https://foundation.zurb.com/sites/docs/media-queries.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tailwindcss.com/docs/responsive-design/"&gt;https://tailwindcss.com/docs/responsive-design/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.apple.com/library/archive/documentation/DeviceInformation/Reference/iOSDeviceCompatibility/Displays/Displays.html"&gt;https://developer.apple.com/library/archive/documentation/DeviceInformation/Reference/iOSDeviceCompatibility/Displays/Displays.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>css</category>
    </item>
  </channel>
</rss>
