<?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: gsshop</title>
    <description>The latest articles on DEV Community by gsshop (@gsshop).</description>
    <link>https://dev.to/gsshop</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%2Forganization%2Fprofile_image%2F1683%2F2088e814-5811-4ffc-9b56-25f54c6f45d7.jpeg</url>
      <title>DEV Community: gsshop</title>
      <link>https://dev.to/gsshop</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gsshop"/>
    <language>en</language>
    <item>
      <title>Vue.js Carousels: SSR Support And Performance</title>
      <dc:creator>KyuWoo Choi</dc:creator>
      <pubDate>Mon, 20 Jan 2020 15:05:44 +0000</pubDate>
      <link>https://dev.to/gsshop/vue-js-carousels-ssr-support-and-performance-24nh</link>
      <guid>https://dev.to/gsshop/vue-js-carousels-ssr-support-and-performance-24nh</guid>
      <description>&lt;h1&gt;
  
  
  Web Performance Optimization
&lt;/h1&gt;

&lt;p&gt;I am one of the CoE members in &lt;a href="http://company.gsshop.com/" rel="noopener noreferrer"&gt;GSShop&lt;/a&gt;. Our company invests startups, and I help them to grow. Last time, I was helping the Vietnamese company by making their web faster. Cool! See how &lt;a href="https://web.dev/why-speed-matters/" rel="noopener noreferrer"&gt;web performance affects your business&lt;/a&gt;. This article is from the journey exploring the SSR support of the &lt;a href="https://vuejs.org/" rel="noopener noreferrer"&gt;Vue.js&lt;/a&gt; carousels. It ends with making the &lt;a href="https://github.com/gs-shop/vue-slick-carousel" rel="noopener noreferrer"&gt;vue-slick-carousel&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  CSR(Client Side Rendering) With A Spinner
&lt;/h2&gt;

&lt;p&gt;The site is a SPA(Single Page Application) made with &lt;a href="https://vuejs.org/" rel="noopener noreferrer"&gt;Vue.js&lt;/a&gt;. Vue.js, like &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React&lt;/a&gt;, is one of the famous tech stacks of modern web development. Despite the SPA's many advantages, it has the disadvantage of long loading time due to the &lt;a href="https://developers.google.com/web/updates/2019/02/rendering-on-the-web#server-rendering" rel="noopener noreferrer"&gt;CSR(Client Side Rendering)&lt;/a&gt;. The long loading time is because the browser doesn't know what to render on the screen until the browser evaluates javascript. So it usually put the spinner to say, "Please, don't leave. We're working on it." I wish the magic circle works, but It doesn't.&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fgm64fsrszya86t5a505k.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fgm64fsrszya86t5a505k.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  SSR(Server Side Rendering) With Placeholders
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developers.google.com/web/updates/2019/02/rendering-on-the-web#server-rendering" rel="noopener noreferrer"&gt;SSR(Server Side Rendering)&lt;/a&gt; allows the server to render the HTML so that the browser can quickly show what visitors want without evaluating javascript. &lt;a href="https://nuxtjs.org/" rel="noopener noreferrer"&gt;Nuxt.js&lt;/a&gt;(like &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt; for React) provides best practices, including SSR, to help us build fast web sites.&lt;/p&gt;

&lt;p&gt;We've enabled SSR using Nuxt.js to get rid of the spinner and quickly render the site's contents. SSR made the browser to render fast without having to wait for evaluating the javascript. But this site is made up of many carousel components. The carousel component doesn't support SSR, so it can't quickly render important things like promotions. We removed the spinner, rendered contents instantly, but had to put a lot of placeholders for the carousels. As with before, the contents of the carousels were rendered only a long time after it evaluates the javascript.&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fwd77hgfl1w02d4zxnwvn.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fwd77hgfl1w02d4zxnwvn.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Wanted: Server Side Rendering Vue.js Carousel
&lt;/h1&gt;

&lt;p&gt;Although it looked much better than before, visitors didn't come to see the placeholders. To truly improve UX, we needed a carousel with SSR support.&lt;/p&gt;

&lt;h2&gt;
  
  
  Top 5 Vue.js Carousels
&lt;/h2&gt;

&lt;p&gt;To see which carousels work with SSR best, I tested the top 5 carousels on GitHub(except &lt;a href="https://github.com/wlada/vue-carousel-3d" rel="noopener noreferrer"&gt;vue-carousel-3d&lt;/a&gt;, which has a specialty in 3d rendering).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://github.com/surmon-china/vue-awesome-swiper" rel="noopener noreferrer"&gt;&lt;strong&gt;vue-awesome-swiper&lt;/strong&gt;&lt;/a&gt; 🏆 Swiper component for @vuejs&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/SSENSE/vue-carousel" rel="noopener noreferrer"&gt;&lt;strong&gt;vue-carousel&lt;/strong&gt;&lt;/a&gt; A flexible, responsive, touch-friendly carousel for Vue.js&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/warpcgd/vue-concise-slider" rel="noopener noreferrer"&gt;&lt;strong&gt;vue-concise-slider&lt;/strong&gt;&lt;/a&gt; vue-concise-slider,A simple vue sliding component&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/lukaszflorczak/vue-agile" rel="noopener noreferrer"&gt;&lt;strong&gt;vue-agile&lt;/strong&gt;&lt;/a&gt; A carousel component for Vue.js&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/staskjs/vue-slick" rel="noopener noreferrer"&gt;&lt;strong&gt;vue-slick&lt;/strong&gt;&lt;/a&gt; Vue component for Slick-carousel&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Example Settings
&lt;/h2&gt;

&lt;p&gt;I prepared the SSR examples for the carousels using Nuxt.js(&lt;a href="https://github.com/kyuwoo-choi/nuxt-vue-awesome-swiper-example" rel="noopener noreferrer"&gt;vue-awesome-swiper&lt;/a&gt;, &lt;a href="https://github.com/kyuwoo-choi/nuxt-vue-agile-example" rel="noopener noreferrer"&gt;vue-agile&lt;/a&gt;, &lt;a href="https://github.com/kyuwoo-choi/nuxt-vue-carousel-example" rel="noopener noreferrer"&gt;vue-carousel&lt;/a&gt;, &lt;a href="https://github.com/kyuwoo-choi/nuxt-vue-concise-slider-example" rel="noopener noreferrer"&gt;vue-concise-slider&lt;/a&gt;, &lt;a href="https://github.com/kyuwoo-choi/nuxt-vue-slick-carousel-example" rel="noopener noreferrer"&gt;vue-slick&lt;/a&gt;, &lt;a href="https://github.com/kyuwoo-choi/nuxt-vue-slick-carousel-example" rel="noopener noreferrer"&gt;vue-slick-carousel&lt;/a&gt;). Also, you can run those on codesandbox(&lt;a href="https://codesandbox.io/s/github/kyuwoo-choi/nuxt-vue-awesome-swiper-example" rel="noopener noreferrer"&gt;vue-awesome-swiper&lt;/a&gt;, &lt;a href="https://codesandbox.io/s/github/kyuwoo-choi/nuxt-vue-agile-example" rel="noopener noreferrer"&gt;vue-agile&lt;/a&gt;, &lt;a href="https://codesandbox.io/s/github/kyuwoo-choi/nuxt-vue-carousel-example" rel="noopener noreferrer"&gt;vue-carousel&lt;/a&gt;, &lt;a href="https://codesandbox.io/s/github/kyuwoo-choi/nuxt-vue-concise-slider-example" rel="noopener noreferrer"&gt;vue-concise-slider&lt;/a&gt;, &lt;a href="https://codesandbox.io/s/github/kyuwoo-choi/nuxt-vue-slick-carousel-example" rel="noopener noreferrer"&gt;vue-slick&lt;/a&gt;, &lt;a href="https://codesandbox.io/s/github/kyuwoo-choi/nuxt-vue-slick-carousel-example" rel="noopener noreferrer"&gt;vue-slick-carousel&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  The Examples:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Are created on top of Nuxt.js with universal(SSR) mode.&lt;/li&gt;
&lt;li&gt;Are wrote by following the examples of the components.&lt;/li&gt;
&lt;li&gt;Have image items as we're likely having one or more in real life.&lt;/li&gt;
&lt;li&gt;Have identically styled. No dots, no arrows.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Profile Configuration:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Build for production and run a local server to minimize network Interference.&lt;/li&gt;
&lt;li&gt;Chrome performance profile with Fast 3G Network + 4x slowdown CPU throttling.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/lukaszflorczak/vue-agile" rel="noopener noreferrer"&gt;vue-agile&lt;/a&gt;, &lt;a href="https://github.com/SSENSE/vue-carousel" rel="noopener noreferrer"&gt;vue-carousel&lt;/a&gt;, &lt;a href="https://github.com/warpcgd/vue-concise-slider" rel="noopener noreferrer"&gt;vue-concise-slider&lt;/a&gt;, &lt;a href="https://github.com/staskjs/vue-slick" rel="noopener noreferrer"&gt;vue-slick&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;These carousels do not support SSR. Trying to render these carousels on the server will throw errors. In most cases, the carousels try to access the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window" rel="noopener noreferrer"&gt;browser&lt;/a&gt; through &lt;code&gt;window&lt;/code&gt; object to manipulate the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Element" rel="noopener noreferrer"&gt;DOM elements&lt;/a&gt;. However, this problem occurs because that does not exist on the server.&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fnhrx1aq83l6sy2vfrmbe.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fnhrx1aq83l6sy2vfrmbe.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To avoid the errors, The carousels should be registered on &lt;a href="https://nuxtjs.org/guide/plugins/#client-side-only" rel="noopener noreferrer"&gt;client-side only mode&lt;/a&gt; and wrapped by &lt;a href="https://nuxtjs.org/api/components-client-only/" rel="noopener noreferrer"&gt;client-only(no-ssr)&lt;/a&gt; component. Here're the demos(&lt;a href="https://github.com/kyuwoo-choi/nuxt-vue-agile-example" rel="noopener noreferrer"&gt;vue-agile&lt;/a&gt;, &lt;a href="https://github.com/kyuwoo-choi/nuxt-vue-carousel-example" rel="noopener noreferrer"&gt;vue-carousel&lt;/a&gt;, &lt;a href="https://github.com/kyuwoo-choi/nuxt-vue-concise-slider-example" rel="noopener noreferrer"&gt;vue-concise-slider&lt;/a&gt;, &lt;a href="https://github.com/kyuwoo-choi/nuxt-vue-slick-carousel-example" rel="noopener noreferrer"&gt;vue-slick&lt;/a&gt;) and codesandboxes(&lt;a href="https://codesandbox.io/s/github/kyuwoo-choi/nuxt-vue-agile-example" rel="noopener noreferrer"&gt;vue-agile&lt;/a&gt;, &lt;a href="https://codesandbox.io/s/github/kyuwoo-choi/nuxt-vue-carousel-example" rel="noopener noreferrer"&gt;vue-carousel&lt;/a&gt;, &lt;a href="https://codesandbox.io/s/github/kyuwoo-choi/nuxt-vue-concise-slider-example" rel="noopener noreferrer"&gt;vue-concise-slider&lt;/a&gt;, &lt;a href="https://codesandbox.io/s/github/kyuwoo-choi/nuxt-vue-slick-carousel-example" rel="noopener noreferrer"&gt;vue-slick&lt;/a&gt;)&lt;/p&gt;

&lt;h3&gt;
  
  
  Component Template
&lt;/h3&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;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"carousel-wrapper"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;client-only&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;agile&lt;/span&gt; &lt;span class="na"&gt;:options=&lt;/span&gt;&lt;span class="s"&gt;"options"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"i in 5"&lt;/span&gt; &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"i"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"img-wrapper"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;:src=&lt;/span&gt;&lt;span class="s"&gt;"`./${i}-200x100.jpg`"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/agile&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/client-only&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The carousel components need to be wrapped by  &lt;code&gt;client-only&lt;/code&gt; to avoid the error.&lt;/p&gt;

&lt;h3&gt;
  
  
  Server Render Result
&lt;/h3&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;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"carousel-wrapper"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="c"&gt;&amp;lt;!----&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The server renders blank inside &lt;code&gt;client-only&lt;/code&gt;. The browser will render the carousel after it evaluates the necessary javascript.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance Profile
&lt;/h3&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ffdgsubeidxrnoarj1vqy.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ffdgsubeidxrnoarj1vqy.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After receiving the server's response, the browser must evaluate the javascript to draw the carousel. Images included in the carousel children can only be downloaded and painted afterward.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/surmon-china/vue-awesome-swiper" rel="noopener noreferrer"&gt;vue-awesome-swiper&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/surmon-china/vue-awesome-swiper" rel="noopener noreferrer"&gt;vue-awesome-swiper&lt;/a&gt; is the most popular Vue.js carousel component. vue-awesome-swiper offers a &lt;a href="https://github.com/surmon-china/vue-awesome-swiper/tree/master/examples/nuxt-ssr-example" rel="noopener noreferrer"&gt;special way for server rendering&lt;/a&gt;. You write the rendered DOM structure manually into the component template then the browser runs the &lt;a href="https://vuejs.org/v2/guide/custom-directive.html" rel="noopener noreferrer"&gt;custom directive&lt;/a&gt; to render again. Thus the server just renders what you wrote in the component template without evaluating the carousel script. It means the SSR result doesn't respect any options passed to the carousel. Below is a vue-awesome-swiper with &lt;code&gt;slidesPerView: 3&lt;/code&gt; options. Here's the &lt;a href="https://github.com/kyuwoo-choi/nuxt-vue-awesome-swiper-example" rel="noopener noreferrer"&gt;demo project&lt;/a&gt; &amp;amp; &lt;a href="https://codesandbox.io/s/github/kyuwoo-choi/nuxt-vue-awesome-swiper-example" rel="noopener noreferrer"&gt;codesandbox&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Component Template
&lt;/h3&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;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"carousel-wrapper"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-swiper:mySwiper=&lt;/span&gt;&lt;span class="s"&gt;"options"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"swiper-wrapper"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"i in 5"&lt;/span&gt; &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"i"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"img-wrapper swiper-slide"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;:src=&lt;/span&gt;&lt;span class="s"&gt;"`./${i}-200x100.jpg`"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The custom directive &lt;code&gt;v-swiper&lt;/code&gt; is for browsers, server renderer doesn't evaluate it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Server Render Result
&lt;/h3&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;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"carousel-wrapper"&lt;/span&gt; &lt;span class="na"&gt;data-v-d589df72&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-v-d589df72&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"swiper-wrapper"&lt;/span&gt; &lt;span class="na"&gt;data-v-d589df72&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"img-wrapper swiper-slide"&lt;/span&gt; &lt;span class="na"&gt;data-v-d589df72&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./1-200x100.jpg"&lt;/span&gt; &lt;span class="na"&gt;data-v-d589df72&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"img-wrapper swiper-slide"&lt;/span&gt; &lt;span class="na"&gt;data-v-d589df72&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./2-200x100.jpg"&lt;/span&gt; &lt;span class="na"&gt;data-v-d589df72&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"img-wrapper swiper-slide"&lt;/span&gt; &lt;span class="na"&gt;data-v-d589df72&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./3-200x100.jpg"&lt;/span&gt; &lt;span class="na"&gt;data-v-d589df72&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"img-wrapper swiper-slide"&lt;/span&gt; &lt;span class="na"&gt;data-v-d589df72&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./4-200x100.jpg"&lt;/span&gt; &lt;span class="na"&gt;data-v-d589df72&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"img-wrapper swiper-slide"&lt;/span&gt; &lt;span class="na"&gt;data-v-d589df72&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./5-200x100.jpg"&lt;/span&gt; &lt;span class="na"&gt;data-v-d589df72&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The server renders the template as it is. Browser shows a default vue-awesome-swiper having one slide in it. After the browser evaluates the component directive, It updates the carousel for the given options.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance Profile
&lt;/h3&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F393ca2nk13i8e4wsb7m9.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F393ca2nk13i8e4wsb7m9.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Browsers can download and paint images in the early stages because the first HTML response contains images. As soon as the browser evaluates the script, It can render the carousel with images. But it seems to render the carousel takes more time than the other carousels. It is because of the heavier script. Not only downloading but also evaluating the javascript takes longer.&lt;/p&gt;

&lt;h1&gt;
  
  
  Writing SSR Support Carousel: &lt;a href="https://github.com/gs-shop/vue-slick-carousel" rel="noopener noreferrer"&gt;vue-slick-carousel&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;Ok. I tested the most popular carousels. I also looked around the other carousels. But all seemed not working. And I excluded carousels in the UI Frameworks because they do not provide rich features we needed.&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fswtvpz2o82lcymkjc2gk.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fswtvpz2o82lcymkjc2gk.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here it is. I made the &lt;a href="https://github.com/gs-shop/vue-slick-carousel" rel="noopener noreferrer"&gt;vue-slick-carousel&lt;/a&gt; because of the reasons. Long story short, I ended up writing the vue-slick-carousel by porting the &lt;a href="https://github.com/akiran/react-slick" rel="noopener noreferrer"&gt;react-slick&lt;/a&gt;. I tested by matching the result of the &lt;a href="https://github.com/vuejs/vue/tree/dev/packages/vue-server-renderer" rel="noopener noreferrer"&gt;vue-server-renderer&lt;/a&gt; for the vue-slick-carousel to the result of the &lt;a href="https://reactjs.org/docs/react-dom-server.html" rel="noopener noreferrer"&gt;react-dom server&lt;/a&gt; for react-slick. I kept in mind that the rendering result works for every carousel settings. Here's the &lt;a href="https://github.com/kyuwoo-choi/nuxt-vue-slick-carousel-example" rel="noopener noreferrer"&gt;example&lt;/a&gt; &amp;amp; &lt;a href="https://codesandbox.io/s/github/kyuwoo-choi/nuxt-vue-slick-carousel-example" rel="noopener noreferrer"&gt;codesandbox&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Component Template
&lt;/h2&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;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"carousel-wrapper"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;VueSlickCarousel&lt;/span&gt; &lt;span class="na"&gt;v-bind=&lt;/span&gt;&lt;span class="s"&gt;"slickOptions"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"i in 5"&lt;/span&gt; &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"i"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"img-wrapper"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;:src=&lt;/span&gt;&lt;span class="s"&gt;"`./${i}-200x100.jpg`"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/VueSlickCarousel&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;vue-slick-carousel works well on the server. Therefore, you can write the template in the usual way, without the &lt;code&gt;client-only&lt;/code&gt; tag.&lt;/p&gt;

&lt;h2&gt;
  
  
  Server Render Result
&lt;/h2&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;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"carousel-wrapper"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;"ltr"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"slick-slider slick-initialized"&lt;/span&gt; &lt;span class="na"&gt;data-v-6bed67a2&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"slick-list"&lt;/span&gt; &lt;span class="na"&gt;data-v-6bed67a2&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"slick-track"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"width:433.33333333333337%;left:-100%;"&lt;/span&gt; &lt;span class="na"&gt;data-v-4dc0f449&lt;/span&gt; &lt;span class="na"&gt;data-v-6bed67a2&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;tabIndex=&lt;/span&gt;&lt;span class="s"&gt;"-1"&lt;/span&gt; &lt;span class="na"&gt;data-index=&lt;/span&gt;&lt;span class="s"&gt;"-3"&lt;/span&gt; &lt;span class="na"&gt;aria-hidden=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"slick-slide slick-cloned"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"width:7.6923076923076925%;"&lt;/span&gt; &lt;span class="na"&gt;data-v-4dc0f449&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-v-4dc0f449&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;tabIndex=&lt;/span&gt;&lt;span class="s"&gt;"-1"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"img-wrapper"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"width:100%;display:inline-block;"&lt;/span&gt; &lt;span class="na"&gt;data-v-4dc0f449&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./3-200x100.jpg"&lt;/span&gt; &lt;span class="na"&gt;data-v-4dc0f449&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                    &lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;tabIndex=&lt;/span&gt;&lt;span class="s"&gt;"-1"&lt;/span&gt; &lt;span class="na"&gt;data-index=&lt;/span&gt;&lt;span class="s"&gt;"9"&lt;/span&gt; &lt;span class="na"&gt;aria-hidden=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"slick-slide slick-cloned"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"width:7.6923076923076925%;"&lt;/span&gt; &lt;span class="na"&gt;data-v-4dc0f449&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-v-4dc0f449&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;tabIndex=&lt;/span&gt;&lt;span class="s"&gt;"-1"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"img-wrapper"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"width:100%;display:inline-block;"&lt;/span&gt; &lt;span class="na"&gt;data-v-4dc0f449&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./5-200x100.jpg"&lt;/span&gt; &lt;span class="na"&gt;data-v-4dc0f449&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The server fully make the DOM elements and sends them to the browser. The browser can render on the screen without evaluating any javascript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Profile
&lt;/h2&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fu3z2vsotwxu8eyh2e3ct.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fu3z2vsotwxu8eyh2e3ct.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The browser renders the carousel right after the first HTML response. Since the carousel was rendered quick, downloading images can also be started fast.&lt;br&gt;
Undoubtedly, the vue-slick-carousel can show content the fastest and prepare the image resources it needs. The actual site contains a much heavier script, and this performance gap will be even more significant.&lt;/p&gt;

&lt;h1&gt;
  
  
  Component Support Completes The SSR
&lt;/h1&gt;

&lt;p&gt;All components used by the site must support it for the server to fully render. Thus, the site can deliver what visitors want quickly. Otherwise, In many cases, Trying without the support of components can make the site even slower due to the heavier HTML. Component support completes the Server Side Rendering.&lt;br&gt;
My last project had the same issue. To show content to users faster, we enabled SSR, but this was not possible because no Vue.js carousel supported it. The server is now able to fully render the content using the vue-slick-carousel so that it can deliver content to visitors faster.&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Flbhfxi4u0hsxb7ka7y6k.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Flbhfxi4u0hsxb7ka7y6k.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  What's Next?
&lt;/h1&gt;

&lt;p&gt;Since I started this project to improve performance, I'd like to focus on the goal. And the vue-slick-carousel itself is a new project that has been only a few months old. I want to make it stable. Every issue and PR are welcomed. Your help can make this project mature. Finally, Thank you, react-slick contributors. I'd like to contribute as much as I can while I'm working on this.&lt;br&gt;
Besides the project, I'm thinking of two more articles to share what I learned in the last project. Perhaps due to the population differences, I feel that the react ecosystem is more versatile and mature than the Vue.js ecosystem. Just as is the case with the vue-slick-carousel, I guess it's worth sharing "How to port the react component for the Vue.js." And "Vue.js SSR the hard parts" that I struggled with in my last project.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>vue</category>
      <category>webdev</category>
      <category>webperf</category>
    </item>
  </channel>
</rss>
