<?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: Tarun Pai</title>
    <description>The latest articles on DEV Community by Tarun Pai (@painotpi).</description>
    <link>https://dev.to/painotpi</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%2F214045%2F1eb87d8c-5293-4409-8c83-55a573453408.jpg</url>
      <title>DEV Community: Tarun Pai</title>
      <link>https://dev.to/painotpi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/painotpi"/>
    <language>en</language>
    <item>
      <title>How we improved the load time of our VueJS app from 15s to 1s</title>
      <dc:creator>Tarun Pai</dc:creator>
      <pubDate>Sun, 08 Aug 2021 17:43:40 +0000</pubDate>
      <link>https://dev.to/painotpi/how-we-got-our-vuejs-app-to-load-in-1-second-3gc7</link>
      <guid>https://dev.to/painotpi/how-we-got-our-vuejs-app-to-load-in-1-second-3gc7</guid>
      <description>&lt;h3&gt;
  
  
  📝 Context
&lt;/h3&gt;

&lt;p&gt;Livspace is a &lt;a href="https://www.livspace.io/who-we-are/livspace-platform/"&gt;three-way platform&lt;/a&gt; for homeowners, designers, and contractors. Our homeowner facing web application is the Livspace Hub. We’ll discuss the performance improvements we made on Hub in this article.&lt;/p&gt;

&lt;p&gt;Livspace Hub is a web-app we’ve developed for homeowners to track all of their project-related updates and documents in one place. It is a single stop shop for tracking the progress of their project. Homeowners who design their homes through Livspace are internally called “customers”, and their projects are internally called “projects” (seems obvious, but terminologies matter, and we like to keep nomenclature simple but clear). In the rest of the article, I will refer to Livspace Hub as “Hub”.&lt;/p&gt;




&lt;h3&gt;
  
  
  🗓 History
&lt;/h3&gt;

&lt;p&gt;Hub was initially architected as a Laravel app, serving the UI and the backend server. The UI was then later split to be a Vue SPA, while the Laravel server remained and served as our proxy layer.&lt;/p&gt;

&lt;p&gt;Our main goal for the initial re-architecture (splitting our UI to an SPA) was speed — we wanted to get the SPA version of our app to our customers as soon as possible. Then we could focus on improving the overall architecture.&lt;br&gt;
This obviously (and unfortunately) came with some trade-offs in the HOW’s of our implementation.&lt;/p&gt;

&lt;p&gt;This is what our initial high-level architecture diagram for Hub looked like after splitting the UI into a Vue SPA:&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frnaqwmcw1umwy1pqwimn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frnaqwmcw1umwy1pqwimn.png" alt="image" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This speed to market approach resulted in a SPA that was (in essence) hacked up together. The average load times our customers faced was about 15 seconds (un-throttled)! 🤯&lt;/p&gt;

&lt;p&gt;Here’s what our lighthouse score looked like under simulated throttling,&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7rfx5pgvekgf2jyl09ym.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7rfx5pgvekgf2jyl09ym.png" alt="image" width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this post, we will talk about the steps we took to improve that, and how we went from a load time of 15 seconds to under 1 second.&lt;/p&gt;


&lt;h3&gt;
  
  
  🏛 Incremental Improvements
&lt;/h3&gt;

&lt;p&gt;Given now that our frontend and backend codebases were separate, it gave us the flexibility to incrementally and iteratively improve parts of our stack.&lt;/p&gt;

&lt;p&gt;We set a roadmap to better the experience for our customers and classified this into 3 main goals,&lt;/p&gt;

&lt;p&gt;1) Remove the dependency on Laravel&lt;br&gt;
&lt;strong&gt;Tl;dr&lt;/strong&gt;&lt;br&gt;
The main reason for wanting to do this was maintenance difficulties — a mix of legacy code and lack of expertise around the tech with newer team-members joining us.&lt;br&gt;
We’ve replaced this layer with a thin NodeJS express server.&lt;/p&gt;

&lt;p&gt;2) Add a GraphQL layer&lt;br&gt;
&lt;strong&gt;Tl;dr&lt;/strong&gt;&lt;br&gt;
Livspace has a (surprise surprise) micro-services architecture on the backend, and client-side apps have to make API calls to multiple services to fetch the data to render any given page.&lt;/p&gt;

&lt;p&gt;With that in mind, it made (common) sense for us to add a GraphQL layer that can aggregate this data for us (from the different services) while also stripping out the unnecessary bits from the response.&lt;/p&gt;

&lt;p&gt;This also helped us serve smaller payloads to our 3 apps — Web, Android, and iOS.&lt;br&gt;
This is what our high-level architecture for Hub looks like now after implementing points 1 and 2,&lt;/p&gt;

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

&lt;p&gt;Our customers can access Hub via the web-app(VueJS), or via the iOS and Android native apps(ReactNative).&lt;/p&gt;

&lt;p&gt;For the rest of this article we’re going to focus on the improvements we’ve made to our web app. Our VueJS app is built with an Nginx docker image and deployed to a Kubernetes cluster hosted on AWS.&lt;/p&gt;

&lt;p&gt;The web-app primarily talks to Hub gateway — our NodeJS proxy layer — the gateway in-turn talks to multiple services, primarily Darzi — our data-stitching graphql layer — which is responsible for aggregating data from a whole host of micro-services.&lt;/p&gt;

&lt;p&gt;3) Reduce Front-End Load Times&lt;br&gt;
&lt;strong&gt;Tl;dr&lt;/strong&gt;&lt;br&gt;
On the front-end side, a SPA for Hub seemed adequate as it served the purpose well for our users. We consciously decided to not use something like Nuxt (with SSR/SSG) as the effort to “rewrite” with Nuxt wouldn’t really give us a significantly better app over a well-optimized SPA, and also since SEO isn’t a necessity for Hub.&lt;br&gt;
We’re going to focus on point 3 for the rest of this post and discuss in detail how we went about identifying and fixing performance bottlenecks on the front-end.&lt;/p&gt;


&lt;h3&gt;
  
  
  👀 Identifying Performance Bottlenecks
&lt;/h3&gt;

&lt;p&gt;Identifying performance bottlenecks is far easier than it may seem, thanks to some amazingly wonderful tools that have been developed in the past few years.&lt;/p&gt;
&lt;h5&gt;
  
  
  Analyzing issues
&lt;/h5&gt;

&lt;p&gt;We used VueCLI, Chrome Devtools, and Lighthouse for this, which is a fairly standard toolset.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Some of the steps mentioned might be specific to Vue, but these could easily be applied to your app in any other UI framework with alternative tools.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://cli.vuejs.org/"&gt;VueCLI3&lt;/a&gt; comes with some amazing features, one such is &lt;code&gt;vue ui&lt;/code&gt; which gives a GUI for developers to visualise and manage projects configurations, dependencies, and tasks.&lt;/p&gt;

&lt;p&gt;The simplest way to analyse your production build is to go to,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Task &amp;gt; build &amp;gt; Run Task | Run Analyzer&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's a point-in-time snapshot of what the analyzer looks like,&lt;/p&gt;

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

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

&lt;p&gt;If you've used &lt;a href="https://www.npmjs.com/package/webpack-bundle-analyzer"&gt;Webpack Bundle Analyzer&lt;/a&gt;, this may seem familiar, just has a (much) nicer UI.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;vue ui&lt;/code&gt;, we were able to get an easy-to-read view of what parts of our app and dependencies were bloated as it gave a handy table view to analyze stats, parsed, and gzipped aspects of our build.&lt;/p&gt;

&lt;p&gt;We identified the problematic parts of our app to be,&lt;/p&gt;

&lt;p&gt;Vendor files&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bootstrap-vue.org/"&gt;Bootstrap Vue&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://momentjs.com/"&gt;MomentJS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Unused packages and assets&lt;/li&gt;
&lt;li&gt;Our build chunk files were massive — in the order of MBs.&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  🛠 Putting Fixes In Place
&lt;/h3&gt;

&lt;p&gt;1) Bootstrap Vue&lt;br&gt;
Our initial codebase had bootstrap-vue imported as a whole,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Don't do this!&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BootstrapVue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;IconsPlugin&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;bootstrap-vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This obviously becomes problematic in the sense that we end up using a lot more than we need, which results in a really large chunk-vendor file.&lt;/p&gt;

&lt;p&gt;Thankfully, Bootstrap Vue has an ESM build variant which is tree-shakable, which allows us to import only what we need, and reduce our bundle size, you can read more about it &lt;a href="https://bootstrap-vue.org/docs#tree-shaking-with-module-bundlers"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Our imports then changed to,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// --&lt;/span&gt;
&lt;span class="c1"&gt;// This sort of a "single export" syntax allows us to import&lt;/span&gt;
&lt;span class="c1"&gt;// only the specifics while bundlers can tree-shake &lt;/span&gt;
&lt;span class="c1"&gt;// and remove the unnecessary parts from the library.&lt;/span&gt;
&lt;span class="c1"&gt;// --&lt;/span&gt;
&lt;span class="c1"&gt;// Snippet is trimmed down for brevity.&lt;/span&gt;
&lt;span class="k"&gt;import&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;span class="nx"&gt;LayoutPlugin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;CardPlugin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;ModalPlugin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;FormPlugin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;NavPlugin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;NavbarPlugin&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;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="s2"&gt;bootstrap-vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Takeaway point: Whenever you're looking to add a new plugin to your app, always look for plugins that allow for tree-shaking.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2) MomentJS&lt;br&gt;
Moment is/was a fantastic library but unfortunately it has reached &lt;a href="https://momentjs.com/docs/#/-project-status/"&gt;end of life&lt;/a&gt; at least in terms of active development.&lt;br&gt;
It also does not work well with tree-shaking algos, which becomes problematic since you end up with the whole lib.&lt;/p&gt;

&lt;p&gt;As a replacement option, we went ahead with &lt;a href="https://date-fns.org/"&gt;date-fns&lt;/a&gt;, which gave us everything we wanted and also had a small footprint.&lt;/p&gt;

&lt;p&gt;3) Removing Unused Packages and Assets&lt;br&gt;
This was mostly a manual effort, we couldn't find any tools that could reliably tell us which of our packages and assets were going unused.&lt;/p&gt;

&lt;p&gt;After spending sometime in vscode and excessive use of some find-replace, we were able to eliminate unnecessary font-files, images, and some script files and the rest are deleted.&lt;/p&gt;

&lt;p&gt;For packages, a thorough review of our &lt;code&gt;package.json&lt;/code&gt; file and our file structure gave us enough insight to identify packages and application code that weren't used and these were mostly  features that were in active development at one point but are now pushed to the backlog.&lt;/p&gt;

&lt;p&gt;4) Reducing application bundle file size.&lt;/p&gt;

&lt;p&gt;4.1) Optimizing Vue Router Performance&lt;br&gt;
Vue gives some out-of-the-box ways to optimize and lazy-load routes and route-related assets. Lazy-loading routes helps optimize the way webpack generates the dependency graph for your application and hence reduce the size of your chunk files.&lt;/p&gt;

&lt;p&gt;Our initial codebase did not have any lazy-loading on our routes, so a simple change fixed our &lt;code&gt;main&lt;/code&gt; bundle size by a significant amount. Here's a snippet of what lazy-loading your vue-router config looks like,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// router/index.js&lt;/span&gt;
&lt;span class="c1"&gt;// --&lt;/span&gt;
&lt;span class="c1"&gt;// Adding webpackChunkName just gives a nicer more-readable&lt;/span&gt;
&lt;span class="c1"&gt;// name to your chunk file.&lt;/span&gt;
&lt;span class="c1"&gt;// --&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/callback&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OidcCallback&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;component&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="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="cm"&gt;/* webpackChunkName: "auth-callback" */&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../views/AuthCallback.vue&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="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Home&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;component&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="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* webpackChunkName: "home" */&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../views/Home.vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;children&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;p&gt;4.2) Pre-compress static assets&lt;/p&gt;

&lt;p&gt;As seen in our high-level architecture diagram, we serve our application from an nginx server built via docker.&lt;/p&gt;

&lt;p&gt;Although Nginx provides dynamic compression of static assets,  through our testing we found that pre-compressing assets at build time resulted in better compression ratios for our files and helped save a few more KBs!&lt;/p&gt;

&lt;p&gt;4.3) Pre-loading important assets&lt;/p&gt;

&lt;p&gt;This is a tip from lighthouse that we decided to incorporate into our build step. The basic idea is to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload"&gt;preload&lt;/a&gt; all important assets that your (landing) page will need.&lt;/p&gt;

&lt;p&gt;4.4) Split chunks&lt;/p&gt;

&lt;p&gt;The easiest way to do a split chunks is just by adding the following config,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;optimization: {
  splitChunks: {
    chunks: "all"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But we gained the best result by splitting chunks for certain important libraries and the rest of our 3rd party packages went into a common chunk.&lt;/p&gt;

&lt;p&gt;Here's what our config files look like,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// vue-config.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CompressionPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;compression-webpack-plugin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PreloadPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@vue/preload-webpack-plugin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myCompressionPlug&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CompressionPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;algorithm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gzip&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;js$|&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;css$|&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;png$|&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;svg$|&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;jpg$|&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;woff2$/i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;deleteOriginalAssets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myPreloadPlug&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PreloadPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;preload&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;css$/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;style&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;woff2$/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;font&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;script&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="na"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allAssets&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fileWhitelist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;woff2&lt;/span&gt;&lt;span class="se"&gt;(\?&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;)?&lt;/span&gt;&lt;span class="sr"&gt;$/i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\/(&lt;/span&gt;&lt;span class="sr"&gt;vue|vendor~app|chunk-common|bootstrap~app|apollo|app|home|project&lt;/span&gt;&lt;span class="se"&gt;)\.&lt;/span&gt;&lt;span class="sr"&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;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;productionSourceMap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;chainWebpack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&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;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prefetch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CompressionPlugin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myCompressionPlug&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;types&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-modules&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;normal-modules&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;normal&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nx"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="nf"&gt;addStyleResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stylus&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;oneOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&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;span class="na"&gt;configureWebpack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;myPreloadPlug&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;optimization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;splitChunks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;cacheGroups&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;vendors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;vue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;all&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[\\/]&lt;/span&gt;&lt;span class="sr"&gt;node_modules&lt;/span&gt;&lt;span class="se"&gt;[\\/]((&lt;/span&gt;&lt;span class="sr"&gt;vue&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;)[\\/]&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="na"&gt;bootstrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;all&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[\\/]&lt;/span&gt;&lt;span class="sr"&gt;node_modules&lt;/span&gt;&lt;span class="se"&gt;[\\/]((&lt;/span&gt;&lt;span class="sr"&gt;bootstrap&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;)[\\/]&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="na"&gt;apollo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;all&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[\\/]&lt;/span&gt;&lt;span class="sr"&gt;node_modules&lt;/span&gt;&lt;span class="se"&gt;[\\/]((&lt;/span&gt;&lt;span class="sr"&gt;apollo&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;)[\\/]&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="na"&gt;vendor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;all&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[\\/]&lt;/span&gt;&lt;span class="sr"&gt;node_modules&lt;/span&gt;&lt;span class="se"&gt;[\\/]((?!(&lt;/span&gt;&lt;span class="sr"&gt;vue|bootstrap|apollo&lt;/span&gt;&lt;span class="se"&gt;))&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;)[\\/]&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="c1"&gt;// common chunk&lt;/span&gt;
          &lt;span class="na"&gt;common&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[\\/]&lt;/span&gt;&lt;span class="sr"&gt;src&lt;/span&gt;&lt;span class="se"&gt;[\\/]&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;minChunks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;all&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;reuseExistingChunk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;enforce&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&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;span class="p"&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;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;addStyleResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;rule&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;style-resource&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="nf"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;style-resources-loader&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="nf"&gt;options&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;patterns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/styles/sass/*.scss&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And our nginx config only required the following lines,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Enable gzip for pre-compressed static files
gzip_static on;
gzip_vary on;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  🎉 End Result
&lt;/h3&gt;

&lt;p&gt;Desktop - [No] Clear Storage - [No] Simulated Throttling&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxykjv02aayueaqkig599.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxykjv02aayueaqkig599.png" alt="DCSST" width="733" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mobile - [No] Clear Storage - [No] Simulated Throttling&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5qoy7irs2dqcghog1x51.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5qoy7irs2dqcghog1x51.png" alt="MCSST" width="727" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Desktop - [Yes] Clear Storage - [Yes] Simulated Throttling&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F93mfj3asjn08dsfbt86t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F93mfj3asjn08dsfbt86t.png" alt="DCSST2" width="753" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mobile - [Yes] Clear Storage - [Yes] Simulated Throttling&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5b3jur9bziju2eqy40sv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5b3jur9bziju2eqy40sv.png" alt="MCSST2" width="720" height="351"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🔮 Future Plans
&lt;/h3&gt;

&lt;p&gt;We plan to reduce our mobile load times under simulated throttling, the goal is to get as low as possible! This will require us to revisit our gateway and GraphQL layers, and we’ll definitely share a part 2 blog discussing details of our upgrades.&lt;/p&gt;

&lt;p&gt;We are also exploring Brotli compression, caching, http2/3 as these will definitely help add some level of network level optimizations. Of course, this is not merely for Hub, but for the designer-facing and vendor-facing web-apps as well.&lt;/p&gt;




&lt;h3&gt;
  
  
  💻 We're hiring!
&lt;/h3&gt;

&lt;p&gt;We’re always on the lookout for amazing talent, do check out the work we do at Livspace Engineering &lt;a href="https://www.livspace.io/"&gt;here&lt;/a&gt;. We are hiring across roles, details of which you will find &lt;a href="https://www.livspace.io/work-with-us/careers/"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>vue</category>
      <category>performance</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Contributing to Open-Source - A beginner's guide</title>
      <dc:creator>Tarun Pai</dc:creator>
      <pubDate>Thu, 09 Apr 2020 16:13:34 +0000</pubDate>
      <link>https://dev.to/painotpi/contributing-to-open-source-a-beginner-s-guide-1hm5</link>
      <guid>https://dev.to/painotpi/contributing-to-open-source-a-beginner-s-guide-1hm5</guid>
      <description>&lt;p&gt;Before we begin: The "beginner" in the title is for open-source newbies. The article assumes some level of front-end knowledge; having said that, I'd encourage you to read-on nonetheless 🙂&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What's going to be covered in this article?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This article aims to be a simplistic guide for people who want to get started with open-source contributions; it's to help newbies navigate through issues, the code base, etc.&lt;/p&gt;

&lt;p&gt;We're going to,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pick and Fork a repository (repo)&lt;/li&gt;
&lt;li&gt;Pick an issue to solve&lt;/li&gt;
&lt;li&gt;Build a fix (and refactor it) &lt;/li&gt;
&lt;li&gt;Raise a pull request (PR)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why am I writing this?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When I googled "How to get started with open-source contributions", I didn't find any solid how-to guides. Most articles or tips I could find were centered around making documentation changes for Hactoberfest, while those are great and they give you a good sense of how to get started with Github and PRs, they still did not offer enough of a platform to build on.&lt;/p&gt;




&lt;p&gt;I've picked Vue as an example, but you could equate these steps to most open-source repositories.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 1 - The Issue
&lt;/h3&gt;

&lt;p&gt;The first thing you'd want to do is go to the Github repo for VueJS, go to the issues tab and filter by label - "good first issue" and look for PRs that don't have the "has PR" label.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F37mb898cm4hjmunnm7hf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F37mb898cm4hjmunnm7hf.png" alt="Alt Text" width="800" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: These labels are pretty standard but they're not guaranteed to be the same if you're looking at a different project.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the list of open "good first issues", we're picking the second one titled: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/vuejs/vue/issues/11090"&gt;$http.delete shows warning "avoid using JavaScript unary operator as property name"&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you open the issue you'll find the following details,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Version&lt;br&gt;
2.6.11&lt;/p&gt;

&lt;p&gt;Reproduction link&lt;br&gt;
&lt;a href="https://codepen.io/frOracle/pen/vYOEEVW"&gt;https://codepen.io/frOracle/pen/vYOEEVW&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Steps to reproduce&lt;br&gt;
use $http.delete in @click&lt;/p&gt;

&lt;p&gt;What is expected?&lt;br&gt;
$http.delete is a function, not unary operator&lt;/p&gt;

&lt;p&gt;What is actually happening?&lt;br&gt;
a warning "avoid using JavaScript unary operator as property name"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Note: Issue logging is usually driven by a template that's decided by the project authors.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;In this case Vue has decided that they want the person logging the issue to&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Provide a reproduction link&lt;/li&gt;
&lt;li&gt;Provide steps to reproduce&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;and answer a few questions around the behavior.&lt;/p&gt;

&lt;p&gt;If you open the codepen link and open the console you'll see the following error,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;"[Vue warn]: Error compiling template:

avoid using JavaScript unary operator as property name: 'delete()' in expression @click.prevent='$http.delete('/rest/close')'

1  |  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;'app'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
2  |  &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;'#'&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click.prevent=&lt;/span&gt;&lt;span class="s"&gt;'$http.delete('&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="na"&gt;rest&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="err"&gt;')'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;click&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3  |  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

(found in &lt;span class="nt"&gt;&amp;lt;Root&amp;gt;&lt;/span&gt;)"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's try to understand what's happening here; based on the issue description, the expectation is that Vue does not throw a warning when &lt;code&gt;$http.delete&lt;/code&gt; is used as delete is a valid HTTP verb (others being GET, POST, PUT, PATCH).&lt;/p&gt;

&lt;p&gt;Come to think of it, Vue shouldn't throw a warning when any form of &lt;code&gt;.delete&lt;/code&gt; is used, either with &lt;code&gt;$http&lt;/code&gt; or any other object as &lt;code&gt;delete&lt;/code&gt; is a valid property name on objects. You can read more about &lt;a href="https://javascript.info/object#property-names-limitations"&gt;property name limitations&lt;/a&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 2 - The Solution
&lt;/h3&gt;

&lt;p&gt;So before we get to understanding the project structure and where we can make this change; this issue (and not all issues can be solved in this manner) can be solved as a generic JavaScript problem statement.&lt;/p&gt;

&lt;p&gt;To solve this issue, we essentially need to check a string and not throw a warning in case &lt;code&gt;delete()&lt;/code&gt; (or any other unary operator) was invoked as an object property.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For given string &lt;code&gt;str&lt;/code&gt;,&lt;br&gt;
We need to return a truthy value if the &lt;code&gt;str&lt;/code&gt; has a &lt;code&gt;.&lt;/code&gt; prefixing the &lt;code&gt;delete&lt;/code&gt; keyword&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The simplest way to solve this for the most basic case would be,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;unaryOp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;delete&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.delete&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;charAt&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;delete&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="c1"&gt;// continue and DO NOT throw a warning&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the above code is in no way ideal for a variety of reasons, some being:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;It caters to only the &lt;code&gt;delete&lt;/code&gt; operator; we need to also take care of &lt;code&gt;typeof&lt;/code&gt; and &lt;code&gt;void&lt;/code&gt; for instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It assumes the string &lt;code&gt;str&lt;/code&gt; would always be of a particular format.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Works only for &lt;code&gt;.&lt;/code&gt; as a prefix; the logic is not flexible enough to add another prefix.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We need to write this in a more robust manner to cater to the problems mentioned above - as a rule of thumb (and not just for open-source projects), challenge or question the code you've written, because almost always, there's a better way to write it.&lt;/p&gt;

&lt;p&gt;We can use the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp"&gt;RegExp&lt;/a&gt; and the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match"&gt;string match method&lt;/a&gt; for this!&lt;/p&gt;

&lt;p&gt;Now like all experience developers, I too have the lowest level of proficiency with regular expressions, so I'm going to use one I found online.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;re&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
  &lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;bdelete&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;s*&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;([^&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;)]*&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;)|
  &lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;btypeof&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;s*&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;([^&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;)]*&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;)|
  &lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;bvoid&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;s*&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;([^&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;)]*&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;)
`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// PS: this is the same regex being used in the Vue repo!&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;matched&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;re&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;allowedPrefixes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;matched&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;allowedPrefixes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;matched&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// continue and DO NOT throw a warning&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 3: Finding the right file
&lt;/h3&gt;

&lt;p&gt;To simplify testing and debugging, I created a minimal setup - a &lt;code&gt;vue-oss-testing&lt;/code&gt; folder which resides in the same directory as the cloned &lt;code&gt;vue&lt;/code&gt; repository folder.&lt;/p&gt;

&lt;p&gt;Within this folder, we need to setup an example similar to the codepen link in the issue and refer to the local copy of the the Vue dev build.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Directory structure&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
+-- vue 
+-- vue-oss-testing
|   +-- index.html
|   +-- app.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;index.html&lt;/strong&gt;&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;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Document&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"test"&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;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"obj.delete()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Click here&lt;span class="nt"&gt;&amp;lt;/button&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;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"../vue/dist/vue.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&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;"app.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;app.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Calling delete function&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="p"&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;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$mount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// this is the entry point&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The quickest way to find the desired file is to use this complicated series of steps called "Find All" 😁&lt;/p&gt;

&lt;p&gt;Just go to VS Code (or whatever editor you prefer) and search for the error,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;avoid using JavaScript unary operator as property name&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This led me to a file called &lt;code&gt;errorDetector.js&lt;/code&gt; which had the following function which seems to be what we need to fix!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0ycdt9oz9snaa6ing9nw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0ycdt9oz9snaa6ing9nw.png" alt="Alt Text" width="800" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Pro tip: You can run your &lt;code&gt;vue-oss-testing&lt;/code&gt; project and set a break-point at this line in the dist vue.js file in DevTools and go through the call stack to understand the execution flow right from the first &lt;code&gt;app.$mount()&lt;/code&gt; function.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A quick glance at the function gives the notion that it allows for unary operators to be prefixed by &lt;code&gt;$&lt;/code&gt; only, so we need to extend this solution to allow for more than just &lt;code&gt;$&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We could fix making the following changes (similar to what we did earlier),&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;allowedPrefixes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;keywordMatch&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;allowedPrefixes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stripped&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;keywordMatch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing else changes in the function,&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4gpcatp53pt3i8gctgj8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4gpcatp53pt3i8gctgj8.png" alt="Alt Text" width="800" height="329"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can now run your code again and observe the console - Vue doesn't throw a warning anymore!&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 4 - Write a test case
&lt;/h3&gt;

&lt;p&gt;Now again, to find the right spec file, let's use our &lt;code&gt;Cmd/Ctrl + Shift + F&lt;/code&gt; superpower! and we'll find this in the &lt;code&gt;template.spec.js&lt;/code&gt; file,&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fipjyxot5lhu8qsbu61mb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fipjyxot5lhu8qsbu61mb.png" alt="Alt Text" width="800" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's add our spec after this,&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fea7nagfz9sf0xgksxdfn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fea7nagfz9sf0xgksxdfn.png" alt="Alt Text" width="800" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that's it!&lt;/p&gt;

&lt;p&gt;As the final step in the build/contribution step is to (raise a Pull Request)[&lt;a href="https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request"&gt;https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request&lt;/a&gt;].&lt;/p&gt;

&lt;p&gt;For this specific issue, there is already a &lt;a href="https://github.com/vuejs/vue/pull/11143"&gt;PR in review&lt;/a&gt; with a very similar fix!&lt;/p&gt;




&lt;h3&gt;
  
  
  Recap
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Go to any open-source repo of your choice&lt;/li&gt;
&lt;li&gt;Filter through features or issues marked as "good first issue"&lt;/li&gt;
&lt;li&gt;Clone the code and replicate the issue&lt;/li&gt;
&lt;li&gt;Add a fix, refactor it to be robust!&lt;/li&gt;
&lt;li&gt;Raise a PR and wait for review comments&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Next Steps
&lt;/h3&gt;

&lt;p&gt;Although I've covered a front-end repository here, I hope I was able to keep the steps generic enough for you to apply them to a language of your choice.&lt;/p&gt;

&lt;p&gt;Here's a &lt;a href="https://github.com/search?q=label%3A%22good+first+issue%22+label%3Ahacktoberfest+state%3Aopen&amp;amp;type=Issues&amp;amp;ref=advsearch&amp;amp;l=&amp;amp;l="&gt;list of all open issues&lt;/a&gt; - labelled "good first issue" or "Hacktoberfest" - across all languages, so you can filter!&lt;/p&gt;




&lt;h3&gt;
  
  
  What more? ... Participate!
&lt;/h3&gt;

&lt;p&gt;Another way to be involved is to participate in the community channels, interact with developers - there are a lot of really good people out there and there's a lot to learn!&lt;/p&gt;

&lt;p&gt;Don't be afraid to ask questions, there's no such thing as a stupid question.&lt;/p&gt;

&lt;p&gt;Link to the VueJS discord channel - &lt;a href="https://chat.vuejs.org/"&gt;https://chat.vuejs.org/&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;And finally, I would love to hear your thoughts on this article. ✌&lt;br&gt;
PS: Shout out to all the light-theme coders!&lt;/p&gt;

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