<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Lighthouse - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Lighthouse - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Mon, 25 May 2026 10:50:10 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/lighthouse/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How Your Gatsby Site Can Get a Perfect Google Lighthouse Score After the Version 6 Update ]]>
                </title>
                <description>
                    <![CDATA[ By Erik Larsson Google Lighthouse is the free, go-to SEO tool for determining your website's overall health.  Enter your URL, and Google Lighthouse will score the performance metrics of your website, including page-speed, accessibility, best-practice... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/gatsby-perfect-lighthouse-score/</link>
                <guid isPermaLink="false">66d45e3db3016bf139028d29</guid>
                
                    <category>
                        <![CDATA[ Gatsby ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Lighthouse ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ SEO ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web performance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 28 Sep 2020 14:24:10 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/09/header-image.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Erik Larsson</p>
<p><a target="_blank" href="https://developers.google.com/web/tools/lighthouse">Google Lighthouse</a> is the free, go-to SEO tool for determining your website's overall health. </p>
<p>Enter your URL, and Google Lighthouse will score the <em>performance metrics</em> of your website, including page-speed, accessibility, best-practices and on-page SEO.</p>
<p>With the release of <strong>Lighthouse version 6</strong> earlier this year, many developers <strong>observed a drastic decrease</strong> in the performance metrics of their websites.</p>
<p>This especially came as a shock to the community of developers that use the popular React-based framework GatsbyJS, praised for its speed and performance.</p>
<p>As a GatsbyJS developer myself, I too, was puzzled. We had gotten used to seeing those sweet, green, 90+ performance ratings, without much effort on our part.</p>
<p>After the version 6 update, however, our site dropped into the orange, down to 60 points! And some us were even experiencing red, <a target="_blank" href="https://github.com/gatsbyjs/gatsby/issues/24332">sub 40 points scores</a>.</p>
<p>I want to share with you <strong>the steps I took in order to re-achieve a perfect 100 Google Lighthouse score</strong>.</p>
<h2 id="heading-step-1-the-quick-and-easy-fix-switching-to-preact">Step 1. The quick and easy fix: switching to Preact</h2>
<p>With the <a target="_blank" href="https://web.dev/lighthouse-whats-new-6.0/">release of Lighthouse version 6</a>, three new performance metrics were introduced: Largest Contentful Paint (LCP), Cumulative Layout Shift (CLS), and Total Blocking Time (TBT).</p>
<p>After scouring the <a target="_blank" href="https://github.com/gatsbyjs/gatsby">Gatsby Github repo</a>, as well as the Lighthouse docs, it seemed clear that <em>Total Blocking Time</em> (TBT) was the main culprit responsible for hampering the performance score for many sites.</p>
<p><a target="_blank" href="https://web.dev/tbt/">Total Blocking Time</a> (TBT) is defined as the <em>total amount of time between First Contentful Paint (FCP) and Time to Interactive (TTI)</em>. </p>
<p>Simply put, TBT is a measurement of how long the browser's <em>main thread</em> is blocked by long tasks, such as parsing JavaScript (JS).</p>
<p>That being said, any steps taken to reduce the amount of JS, as well as JS execution time, will positively impact site performance by reducing TBT.</p>
<p>Preact is a small (3kb), <a target="_blank" href="https://preactjs.com/">fast alternative to React</a>. And thanks to <a target="_blank" href="https://www.gatsbyjs.com/plugins/gatsby-plugin-preact/">gatsby-plugin-preact</a>, switching your Gatsby-site from running on React to Preact is incredibly easy.</p>
<p>Navigate to your project root and install the following packages using NPM:</p>
<p>    npm install --save gatsby-plugin-preact preact preact-render-to-string</p>
<p>...or Yarn:</p>
<p>    yarn add gatsby-plugin-preact preact preact-render-to-string</p>
<p>Then simply add </p>
<p>    ...
    <code>gatsby-plugin-preact</code>,
    ...</p>
<p>to your gatsby-config.js</p>
<p>Then run </p>
<p>    yarn gatsby build</p>
<p>If you use the <a target="_blank" href="https://www.gatsbyjs.com/plugins/gatsby-plugin-webpack-bundle-analyser-v2/">webpack bundle analyzer</a>, you should now be seeing a ~100kb smaller bundle size! Not bad, right.</p>
<p>Check out the difference this switch made to our bundle size in the image below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/preact-2.PNG" alt="The difference in bundle size between React and Preact" width="600" height="400" loading="lazy">
<em>An 8 percent decrease in bundle size for one line of code - not bad!</em></p>
<p>Switching to Preact should bump your performance score about <strong>5-10 points</strong>.</p>
<h2 id="heading-step-2-reconsider-the-necessity-of-the-hero-image">Step 2. Reconsider the necessity of the <em>Hero-Image</em></h2>
<p>Another metric that made our site, <a target="_blank" href="https://www.smartrate.se/">SmartRate</a>, take a beating performance-wise was the <a target="_blank" href="https://web.dev/lcp/">Largest Contentful Paint</a> (LCP).</p>
<p>LCP is a metric for measuring <em>perceived load speed</em>. And together with Total Blocking Time, LCP and TBT makes up 50% of the total Lighthouse Performance score.</p>
<p>With that in mind, it's not a big surprise that an image covering 80 percent of the fold negatively impacts the LCP-metric, even when optimized using the webp format.</p>
<p>We tweaked the hero image and achieved partial success by disabling fade-in and switching loading from the default parameter (lazy) to eager:</p>
    <img src="{heroImage}" width="600" height="400" alt="{heroImage}" loading="lazy">

<p>However, the improvements were only marginal and barely noticable in Lighthouse (about 2-4 points), so we decided to regroup and rethink.</p>
<p>What <em>was</em> the purpose of our hero-image, really?</p>
<p>The hero image is commonly used to grab the user's attention and convey a central message to strenghten your brand. </p>
<p>In our case however, that's not how we use <em>the fold</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/www.smartrate.se_-Desktop-monitor--1.png" alt="A screenshot of the SmartRate landing page" width="600" height="400" loading="lazy">
<em>A screenshot of the fold as it looks today, showing the hero-unit and user-input area.</em></p>
<p>As you can see from the image, the <em>fold</em> is dedicated to <em>user-input</em>. And the hero-image we were using before the current one was just a blurred photo in order to give some ambience to the fold.</p>
<p>After a bit of thinking, we realized we couldn't justify using a hero-image, given the negative impact it had on our performance metrics.</p>
<p>Instead, inspired by sites such as <a target="_blank" href="https://www.spotify.com">Spotify.com</a>,  we decided to go with an SVG background.</p>
<p><strong>This single decision reduced the size of the initial page-load by a whooping 65kb!</strong></p>
<p>From an optimized webp image of ~67kb down to a mere 2kb SVG for the same real estate.</p>
<p>Upon finding that this solution completely fixed our issues with the LCP metric, we quickly dropped the idea of using a <em>hero-image</em> from our most important subpage, <a target="_blank" href="https://www.smartrate.se/foretagslan/">företagslån</a> - business loans - as well.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/www.smartrate.se_foretagslan_-Desktop-monitor--1.png" alt="A screenshot of the SmartRate jämför företagslån subpage" width="600" height="400" loading="lazy">
<em>Current sub-page design utilizing a hero-unit (although not a hero-image)</em></p>
<p>For this, and our other subpages, we opted for a subtle three-color CSS gradient instead, to make the <em>hero-message</em> stand out.</p>
<p>This solution was perhaps not as sleek as using a custom tailored image, but it did the trick and greatly improved the LCP for our subpages as well.</p>
<p>Which brings me to...</p>
<h3 id="heading-key-considerations-if-your-site-is-using-a-hero-image">Key considerations if your site is using a hero-image</h3>
<p>Dropping the hero-image in favor of a SVG or CSS background will, in our experience, solve the issues caused by a low LCP score.</p>
<p>However, depending on the purpose of your hero-unit, this solution may not be optimal for you.</p>
<p>So, before you decide what to do, you should consider a few things:</p>
<ul>
<li>Is the hero-image <strong>custom made</strong> for your site <strong>or a stock-photo</strong>?</li>
<li>Does the hero-image <strong>add value</strong> to your brand?</li>
<li>What is the purpose of the fold on <strong>your site</strong>?</li>
</ul>
<p>If your hero-image adds great branding value for your site, perhaps the trade-off for better performance simply isn't worth it.</p>
<p>However, if you're ready to give my suggestions a try, you will be happy to hear about the following resources.</p>
<h3 id="heading-great-resources-for-svg-backgrounds">Great resources for SVG backgrounds</h3>
<p>Below I've compiled a short list of valuable resources and tools for anyone who wants to switch from using a hero-image to using SVG/CSS patterns:</p>
<ul>
<li><p><a target="_blank" href="https://www.heropatterns.com/">Hero Patterns</a> by Steve Schoger
 A great tool providing multiple customizable SVG patterns.</p>
</li>
<li><p><a target="_blank" href="https://philiprogers.com/svgpatterns/">SVG Patterns</a> by Philip Rogers
 Another free SVG pattern gallery.</p>
</li>
<li><p><a target="_blank" href="https://jakearchibald.github.io/svgomg/">SVGOMG</a> by Jake Archibald
 A great, free resource for minifying SVG-files. It's all about reducing
 those kb's, right?</p>
</li>
</ul>
<p>The next step is a bit more situational, but will, for those of you who are using a UI library, still be <em>very relevant</em>. For us, this step was just as important as the first two steps in improving our metrics.</p>
<h2 id="heading-step-3-dropping-material-ui-for-tailwindcss">Step 3. Dropping Material UI for TailwindCSS</h2>
<p>Let me state, right off the bat, that I'm a big, big fan of <a target="_blank" href="https://material-ui.com/">Material UI</a>. And I'm not alone in thinking so. Until recently, MUI has been the most popular React UI library on Github (currently at second position).</p>
<p>When we started developing our site, the design was entirely based on MUI components.</p>
<p>The only problem was, <em>it was slowing down the performance of the site</em>.</p>
<p>A lot.</p>
<p>Especially for mobile users.</p>
<p>After the release of Lighthouse version 6, we simply couldn't get the mobile performance ratings above 70 points, due to a very high <em>Total Blocking Time</em> (TBT). </p>
<p>Nothing we did seemed to matter at first. We even tried code-splitting using <a target="_blank" href="https://loadable-components.com/docs/code-splitting/">Loadable Components</a>, and lazy-loading non-essential payloads.</p>
<p>After some digging though, <strong>we identified Material UI as the source for the decrease in performance</strong>.</p>
<p>During page render, layout calculations (and re-calculations) seemed to occur all over the place, which contributed to an increased TBT.</p>
<p>We started removing MUI components, <em>one by one</em>, but this did little to improve the performance.</p>
<p>Finally, we were down to a single MUI component, and a near clean boilerplate website.</p>
<p>And we were still experiencing low performance ratings.</p>
<p><strong>How could this be?</strong></p>
<p>Well, as it appeared, importing a single MUI component would bring in the entire Material UI library into the bundle. And loading the landing-page would require the user to download the entire CSS and JS of Material UI.</p>
<p><strong>But what about <a target="_blank" href="https://webpack.js.org/guides/tree-shaking/">tree-shaking</a> I can hear you say?</strong></p>
<p>Well, to that I can only respond that we followed <a target="_blank" href="https://material-ui.com/guides/minimizing-bundle-size/">the MUI recommendations</a> for minimizing the bundle size. Our efforts, however, did not pay off.</p>
<p>By removing the last MUI import, we noticed <strong>a staggering ~170kb drop in bundle size!</strong></p>
<p>Finally, the performance of our site soared into the green, 90+ points, <em>even on mobile!</em></p>
<p>The TBT was now non-existent, but so was the layout of our website.</p>
<p>We therefore started looking at alternatives, and I remembered <a target="_blank" href="https://www.gatsbyjs.com/docs/tailwind-css/">reading about TailwindCSS integration into Gatsby</a> some time earlier.</p>
<p>One phrase that caught my attention was <em>"Purging your CSS"</em>.</p>
<p><a target="_blank" href="https://purgecss.com/">PurgeCSS</a>, which is now built-into TailwindCSS, does exactly what you think it does - removes unused CSS!</p>
<p>Perfect.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/muitotailwindpostcss-1.png" alt="Image illustrating the switch from Material UI to TailwindCSS" width="600" height="400" loading="lazy">
<em>By transitioning from Material UI to TailwindCSS, we could obtain a material-ish design with a great performance score.</em></p>
<p>Simply following the <a target="_blank" href="https://www.gatsbyjs.com/docs/tailwind-css/">Tailwind installation guide in the Gatsby docs</a> was enough for us to get going. We slowly started designing material-ish looking components using Tailwind through PostCSS.</p>
<p>Not quite as nice looking as MUI components, but not far off. Given the huge performance boost though, <em>it was totally worth it</em>.</p>
<p>For being complete beginners, I must say designing components using <strong>Tailwind is surprisingly intuitive</strong>. You quickly get the hang of it.</p>
<h3 id="heading-reconnecting-to-the-first-step">Reconnecting to the first step</h3>
<p>Another small perk of using Preact over React is the possibility to use the class parameter over the className parameter (which still works). This makes designing components a bit quicker - especially when copying markdown from their <a target="_blank" href="https://tailwindcss.com/docs/installation">official website</a>.</p>
<p>Should you decide to abandon Material UI, Bootstrap, or whatever other React-based UI library you're using in favor of Tailwind, you'll be happy to know about the following resources:</p>
<ul>
<li><a target="_blank" href="https://tailwindui.com/preview">Tailwind UI</a> Made by the creators of TailwindCSS, Tailwind UI is a repo where you can find beautiful, pre-designed components. A few of them can be used for free.</li>
<li><a target="_blank" href="https://tailwindcomponents.com/">Tailwind Components</a> is a repo of free-to-use community-made Tailwind components.</li>
</ul>
<h2 id="heading-bonus-tip-manage-your-bundle-size-going-forward">Bonus tip: Manage your bundle size going forward</h2>
<p>As you probably can imagine, optimizing the bundle size and rebuilding the entire UI of our site was quite taxing. If I learned one important lesson during this process it was this:</p>
<p><strong>Mind the bundle size!</strong></p>
<p>As we grew more and more aware of how bundle size was impacting the performance of our site, we stumbled upon a tool called <strong><a target="_blank" href="https://bundlephobia.com/">bundlephobia</a></strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/bundlephobia1-1.PNG" alt="A screenshot of the Bundlephobia landing page" width="600" height="400" loading="lazy">
<em>Bundlephobia landing page.</em></p>
<p>This great tool will <em>"find the cost of adding a npm package to your bundle"</em>. Not only that, but it will show you similar packages, and how they relate in size to the one you're currently viewing.</p>
<p>This was truly useful for us when we developed the <a target="_blank" href="https://www.smartrate.se/bolan/">bolån</a> (mortgages rates) sub-page. We required a charting library that would let us put together multiple line charts, showing the average mortgage rates for Sweden's largest banks over the last twelve months.</p>
<p>We couldn't find any other website doing this, so we thought it would be a great, free service to offer our visitors.</p>
<p>However, wiser from earlier experiences, we were not keen on simply using the first charting library that crossed our path.</p>
<p>Using bundlephobia, we compared the bundle size of different charting libraries and found that, based on our needs, <a target="_blank" href="https://gionkunz.github.io/chartist-js/">chartist.js</a> would be sufficient or us.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/bundlephobia2.PNG" alt="A screenshot from Bundlephobia showing similar libraries to Chartist.js" width="600" height="400" loading="lazy">
<em>Bundlephobia showing similar libraries (and their respective package-size) to chartist.js</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/bolaneranta-genomsnitt.png" alt="A line chart" width="600" height="400" loading="lazy">
<em>And an image of the resulting line charts showing historical mortgage rates.</em></p>
<p>If our need was simply to display interactive line-charts, why pay more than we need?</p>
<p>In other words, if we have the option to get the desired function with minimal impact to performance, that option should be our default choice.</p>
<p>However, it's also important to recognize that decisions between design and performance almost always implicates a trade-off. <em>And that trade-off should be considered wisely</em>.</p>
<p><strong>Our priority was performance, as shown by the results below:</strong></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/100perfectscore-1.PNG" alt="Image showing near-perfect Lighthouse score" width="600" height="400" loading="lazy">
<em>A near perfect Google Lighthouse score! Only two points off on Accessibility for having too low of a contrast ratio on some buttons. But hey, design has to prevail somewhere, right?</em></p>
<p>In this post we covered <strong>the steps we took in order to achieve a near-perfect Google Lighthouse score</strong>, by:</p>
<ul>
<li>Improving the metric <em>Total Blocking Time</em> by switching from React to Preact </li>
<li>Improving the metric <em>Largest Contentful Paint</em> by optimizing the parameters of the hero-image, or switching the hero-image for a SVG-pattern</li>
<li>Improving the metric <em>Total Blocking Time</em> by switching from Material UI to TailwindCSS, and purging unused CSS using PurgeCSS</li>
<li>Reducing overall bundle size</li>
</ul>
<p>I truly hope the lessons we learned will inspire and benefit you, too!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Keep a Historical Record of Lighthouse Reports ]]>
                </title>
                <description>
                    <![CDATA[ By Adam Henson Lighthouse is an open-source project from the Google Chrome team. It's used to analyze web page quality based on a set of modern, "user-centric" metrics.  When supporting websites that rely on organic search results for revenue, qualit... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-keep-a-historical-record-of-lighthouse-reports/</link>
                <guid isPermaLink="false">66d45d599208fb118cc6cf83</guid>
                
                    <category>
                        <![CDATA[ Lighthouse ]]>
                    </category>
                
                    <category>
                        <![CDATA[ SEO ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Engineering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web performance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ website development, ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 28 May 2020 13:02:03 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/05/lighthouse-logo-in-water-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Adam Henson</p>
<p>Lighthouse is an open-source project from the Google Chrome team. It's used to analyze web page quality based on a set of modern, "user-centric" metrics. </p>
<p>When supporting websites that rely on organic search results for revenue, quality is critical. Performance, accessibility and general SEO best practices are major factors in search engine rankings. </p>
<p>Lighthouse provides a granular set of metrics that represent these factors and suggestions of improvement in reporting. </p>
<p>There are <a target="_blank" href="https://developers.google.com/web/tools/lighthouse">many ways of running Lighthouse</a>, but in the real world you may want to compare reports regularly, especially in continuous change workflows. With that said, you might be wondering - <strong>how can I keep track of SEO, performance, and accessibility changes over time</strong>?</p>
<p>This post covers how to use <a target="_blank" href="https://www.foo.software/lighthouse">Automated Lighthouse Check</a> to analyze website quality over time. But keep in mind that there are many other <a target="_blank" href="https://github.com/GoogleChrome/lighthouse#lighthouse-integrations">Lighthouse integrations</a> to choose from.</p>
<h2 id="heading-saving-reports-and-viewing-results-in-a-timeline">Saving Reports and Viewing Results in a Timeline</h2>
<p><a target="_blank" href="https://developers.google.com/web/tools/lighthouse/v3/scoring">Lighthouse scoring</a> is an interesting aspect of the tool that may feel a little dirty at first. Still, it can be a very useful point of comparison when looking at historical data. </p>
<p>The performance category in particular is quite complicated in its calculation of score and you can find a lot of <a target="_blank" href="https://web.dev/performance-scoring/">great reading about the topic among others on web.dev</a>.</p>
<p>Automated Lighthouse Check provides a means of manually triggering audits or establishing a schedule in which they run automatically throughout the day. These audits are saved in a database so you can visualize and analyze results at a historical level. You can actually drill into any report in time to see full details (<a target="_blank" href="https://www.foo.software/dashboard/page/5d1d459641e33a002f256efc">see an example here</a>).</p>
<p>For a guide to getting started with Automated Lighthouse Check, <a target="_blank" href="https://www.foo.software/automated-lighthouse-check-getting-started/">see the documentation</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/automated-ligthouse-check-timeline.png" alt="Image" width="600" height="400" loading="lazy">
<em>Timeline view of Lighthouse scores</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-28-at-8.15.32-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>A historical list of Lighthouse audits</em></p>
<h2 id="heading-lighthouse-automation-in-devops">Lighthouse Automation in DevOps</h2>
<p>Not only are there many useful cloud-based Lighthouse tools, but there are also many open-source projects that can be implemented in a variety of DevOps workflows. Some of these solutions support persistence of data in one form or another, to track historically. </p>
<p>Below are a few examples that I've contributed to.</p>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/news/how-to-use-lighthouse-in-circleci/">This post covers how to use Lighthouse in CircleCI</a>. You can save reports as "artifacts" in CircleCI or upload to AWS S3 automatically.</li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/how-to-use-lighthouse-in-github-actions/">This post covers how to use Lighthouse in GitHub Actions</a>. This solution also provides a way to save reports as "artifacts" (in GitHub) or upload to AWS S3 automatically.</li>
<li><a target="_blank" href="https://www.npmjs.com/package/@foo-software/lighthouse-persist">Lighthouse Persist is an NPM package</a> that exposes the native Lighthouse API with additional options to set AWS S3 credentials so it can be used to upload reports automatically.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-28-at-8.34.59-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>A few friends - Octocat, Jenkins, CircleCI</em></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>I hope this post was helpful in providing solutions for analyzing website quality historically. Help support your local developers by purchasing their software ?</p>
<p>But in all seriousness, I'd love any feedback about Automated Lighthouse Check... comments, suggestions, feature requests, etc. It's about a year old at the time of this writing and has recently been migrated to Kubernetes for high availability. </p>
<p>Automated Lighthouse Check provides <a target="_blank" href="https://www.foo.software/pricing">free and premium plans</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to use Lighthouse in CircleCI ]]>
                </title>
                <description>
                    <![CDATA[ By Adam Henson CircleCI is a popular tool for orchestrating CI/CD pipelines. Lighthouse is an open-source project from Google for improving the quality of web pages. It provides user-centric metrics to audit SEO, performance, accessibility, best prac... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-lighthouse-in-circleci/</link>
                <guid isPermaLink="false">66d45d6151f567b42d9f841f</guid>
                
                    <category>
                        <![CDATA[ Accessibility ]]>
                    </category>
                
                    <category>
                        <![CDATA[ CircleCI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Lighthouse ]]>
                    </category>
                
                    <category>
                        <![CDATA[ SEO ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Website performance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 06 Jan 2020 12:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/01/nyc-building-in-midtown-east.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Adam Henson</p>
<p><a target="_blank" href="https://circleci.com/">CircleCI</a> is a popular tool for orchestrating CI/CD pipelines. Lighthouse is an open-source project from Google for improving the quality of web pages. It provides user-centric metrics to audit SEO, performance, accessibility, best practices, and progressive web apps. </p>
<p>For a deeper dive about Lighthouse you can read “<a target="_blank" href="https://www.freecodecamp.org/news/three-ways-to-analyze-website-performance-with-lighthouse-8d100966c04b/">How to analyze website performance with Lighthouse</a>”. </p>
<p>By combining these forces, we can establish website quality automation. This post will demonstrate the following:</p>
<ul>
<li>Basic implementation of Lighthouse in a CircleCI workflow.</li>
<li>Advanced setup to display Lighthouse results in pull request comments.</li>
<li>S3 Lighthouse report uploads.</li>
<li>Slack notifications.</li>
</ul>
<h1 id="heading-lighthouse-check-circleci-orb">Lighthouse Check CircleCI Orb</h1>
<p><a target="_blank" href="https://circleci.com/docs/2.0/orb-intro/#section=configuration">CircleCI Orbs</a> are shareable packages of configuration elements, including jobs, commands, and executors you use in your workflows. This post will provide a guide for using the <a target="_blank" href="https://circleci.com/orbs/registry/orb/foo-software/lighthouse-check">Lighthouse Check CircleCI Orb</a> for automating Lighthouse audits.</p>
<h3 id="heading-basic-example">Basic Example</h3>
<p>Below is a minimal example and all we need to run Lighthouse automatically on any code change ? In this example both <a target="_blank" href="https://www.foo.software"><code>https://www.foo.software</code></a> and <a target="_blank" href="https://www.foo.software/contact"><code>https://www.foo.software/contact</code></a> will be audited.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">version:</span> <span class="hljs-number">2.1</span>

<span class="hljs-attr">orbs:</span>
  <span class="hljs-attr">lighthouse-check:</span> <span class="hljs-string">foo-software/lighthouse-check@0.0.8</span>

<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">test:</span> 
    <span class="hljs-attr">executor:</span> <span class="hljs-string">lighthouse-check/default</span>
    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">lighthouse-check/audit:</span>
          <span class="hljs-attr">urls:</span> <span class="hljs-string">https://www.foo.software,https://www.foo.software/contact</span>

<span class="hljs-attr">workflows:</span>
  <span class="hljs-attr">test:</span>
    <span class="hljs-attr">jobs:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">test</span>
</code></pre>
<p>With this minimal setup we have a summary provided in the output of our job. We also have full HTML reports saved as <a target="_blank" href="https://circleci.com/docs/2.0/artifacts/">CircleCI "artifacts"</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/01/circleci-orb-lighthouse-check-output.png" alt="Image" width="600" height="400" loading="lazy">
<em>Lighthouse Check Orb output</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/01/circleci-orb-lighthouse-check-artifacts.png" alt="Image" width="600" height="400" loading="lazy">
<em>Lighthouse Check Orb save artifacts</em></p>
<h3 id="heading-advanced-example">Advanced Example</h3>
<p>Lighthouse Check CircleCI Orb offers a complete set of bells and whistles by utilizing <code>[lighthouse-check](https://github.com/foo-software/lighthouse-check)</code> <a target="_blank" href="https://github.com/foo-software/lighthouse-check">NPM module</a> under the hood. There’s so much more we can do with this. Let’s proceed!</p>
<h2 id="heading-pull-request-comments">Pull Request Comments</h2>
<p>By utilizing this feature, comments are posted with Lighthouse results on every commit. We can do so by following the steps below.</p>
<ol>
<li>Create a new user or find an existing one to act as a “bot”.</li>
<li><a target="_blank" href="https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line">Create a personal access token</a> from this user account.</li>
<li><a target="_blank" href="https://circleci.com/docs/2.0/env-vars/#setting-an-environment-variable-in-a-project">Create a CircleCI environment variable in your project</a> to hold the encrypted value from above. In our example we name it <code>LIGHTHOUSE_CHECK_GITHUB_ACCESS_TOKEN</code>.</li>
<li>Update our config file with the diff shown below.</li>
</ol>
<pre><code class="lang-diff"><span class="hljs-addition">+ prCommentAccessToken: $LIGHTHOUSE_CHECK_GITHUB_ACCESS_TOKEN</span>
<span class="hljs-addition">+ prCommentUrl: https://api.github.com/repos/foo-software/lighthouse-check-orb/pulls/${CIRCLE_PULL_REQUEST##*/}/reviews</span>
urls: https://www.foo.software,https://www.foo.software/contact
</code></pre>
<p>The updates above provides a token to authorize comments on a corresponding pull request. <code>prCommentUrl</code> should be an endpoint in the <a target="_blank" href="https://developer.github.com/v3/pulls/reviews/#create-a-pull-request-review">format specified by the GitHub API</a>. Your endpoint will be similar but with <code>owner</code> and <code>repo</code> params replaced ( <code>foo-software/lighthouse-check-orb</code> ). With this, we’ve created a bot to post Lighthouse results on pull requests ?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/01/lighthouse-check-pr-comment.png" alt="Image" width="600" height="400" loading="lazy">
<em>Lighthouse Check PR comments</em></p>
<h2 id="heading-s3-report-uploads">S3 Report Uploads</h2>
<p>In our example we persist results by uploading reports as artifacts in our job. This solution could be sufficient in some cases, but artifacts aren’t stored permanently. In order to view reports, we need to navigate into the workflow and manually download reports from the artifact view. </p>
<p>But what if we want a more dependable way of storing and referencing reports? This is where the S3 feature comes into play. We can configure AWS S3 storage by following the below steps.</p>
<ol>
<li><a target="_blank" href="https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/">Create an AWS account</a> if you don’t already have one.</li>
<li><a target="_blank" href="https://docs.aws.amazon.com/AmazonS3/latest/gsg/SigningUpforS3.html">Create an S3 bucket</a> if you don’t already have one.</li>
<li><a target="_blank" href="https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html">Acquire an AWS access key id and secret access key</a>.</li>
<li><a target="_blank" href="https://circleci.com/docs/2.0/env-vars/#setting-an-environment-variable-in-a-project">Create a CircleCI environment variables</a> for these two values. In our example we’ll use <code>LIGHTHOUSE_CHECK_AWS_ACCESS_KEY_ID</code> and <code>LIGHTHOUSE_CHECK_AWS_SECRET_ACCESS_KEY</code>, respectively.</li>
<li>Add the bucket name and <a target="_blank" href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html">region</a> (example: <code>us-east-1</code>) as CircleCI environment variables: <code>LIGHTHOUSE_CHECK_AWS_BUCKET</code> and <code>LIGHTHOUSE_CHECK_AWS_REGION</code>.</li>
</ol>
<p>Next, we’ll update our configuration with the following diff.</p>
<pre><code class="lang-diff"><span class="hljs-addition">+ awsAccessKeyId: $LIGHTHOUSE_CHECK_AWS_ACCESS_KEY_ID</span>
<span class="hljs-addition">+ awsBucket: $LIGHTHOUSE_CHECK_AWS_BUCKET</span>
<span class="hljs-addition">+ awsRegion: $LIGHTHOUSE_CHECK_AWS_REGION</span>
<span class="hljs-addition">+ awsSecretAccessKey: $LIGHTHOUSE_CHECK_AWS_SECRET_ACCESS_KEY</span>
prCommentUrl: https://api.github.com/repos/foo-software/lighthouse-check-orb/pulls/${CIRCLE_PULL_REQUEST##*/}/reviews
</code></pre>
<p>In our next commit and push, reports are automatically uploaded to S3 ✅! We also have a them linked in our PR comments.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/01/pr-comment-lighthouse.png" alt="Image" width="600" height="400" loading="lazy">
<em>Lighthouse result PR comment with S3 report linked</em></p>
<h2 id="heading-slack-notifications">Slack Notifications</h2>
<p>What’s a new feature in a DevOps workflow without Slack notifications? A sad one indeed. Let’s ramp things up by adding notifications to a Slack channel for our whole team to see. We can accomplish this in the below steps.</p>
<ol>
<li><a target="_blank" href="https://api.slack.com/messaging/webhooks">Create an “Incoming Webhook” in your Slack workspace and authorize a channel</a>.</li>
<li>Add the Webhook URL as a CircleCI environment variable — <code>LIGHTHOUSE_CHECK_SLACK_WEBHOOK_URL</code>.</li>
</ol>
<pre><code class="lang-diff"><span class="hljs-addition">+ slackWebhookUrl: $LIGHTHOUSE_CHECK_SLACK_WEBHOOK_URL</span>
urls: https://www.foo.software,https://www.foo.software/contact
</code></pre>
<p>Our next commit and push introduces Slack notifications! The “Lighthouse audit” link in the below screenshot navigates to the S3 report as configured ✨</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/01/circleci-orb-lighthouse-check-slack.png" alt="Image" width="600" height="400" loading="lazy">
<em>Lighthouse Slack notification</em></p>
<p>At this point our complete "advanced example" configuration looks like the below.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">usage:</span>
  <span class="hljs-attr">version:</span> <span class="hljs-number">2.1</span>

  <span class="hljs-attr">orbs:</span>
    <span class="hljs-attr">lighthouse-check:</span> <span class="hljs-string">foo-software/lighthouse-check@0.0.8</span>

  <span class="hljs-attr">jobs:</span>
    <span class="hljs-attr">test:</span> 
      <span class="hljs-attr">executor:</span> <span class="hljs-string">lighthouse-check/default</span>
      <span class="hljs-attr">steps:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">lighthouse-check/audit:</span>
            <span class="hljs-attr">awsAccessKeyId:</span> <span class="hljs-string">$LIGHTHOUSE_CHECK_AWS_ACCESS_KEY_ID</span>
            <span class="hljs-attr">awsBucket:</span> <span class="hljs-string">$LIGHTHOUSE_CHECK_AWS_BUCKET</span>
            <span class="hljs-attr">awsRegion:</span> <span class="hljs-string">$LIGHTHOUSE_CHECK_AWS_REGION</span>
            <span class="hljs-attr">awsSecretAccessKey:</span> <span class="hljs-string">$LIGHTHOUSE_CHECK_AWS_SECRET_ACCESS_KEY</span>
            <span class="hljs-attr">prCommentAccessToken:</span> <span class="hljs-string">$LIGHTHOUSE_CHECK_GITHUB_ACCESS_TOKEN</span>
            <span class="hljs-attr">prCommentUrl:</span> <span class="hljs-string">https://api.github.com/repos/foo-software/lighthouse-check-orb/pulls/${CIRCLE_PULL_REQUEST##*/}/reviews</span>
            <span class="hljs-attr">slackWebhookUrl:</span> <span class="hljs-string">$LIGHTHOUSE_CHECK_SLACK_WEBHOOK_URL</span>
            <span class="hljs-attr">urls:</span> <span class="hljs-string">https://www.foo.software,https://www.foo.software/contact</span>

  <span class="hljs-attr">workflows:</span>
    <span class="hljs-attr">test:</span>
      <span class="hljs-attr">jobs:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-string">test</span>
</code></pre>
<h2 id="heading-maintaining-a-historical-record">Maintaining a Historical Record</h2>
<p><a target="_blank" href="https://www.foo.software/lighthouse">Foo’s Automated Lighthouse Check</a> is tool we can use to manage a historical record of Lighthouse audits. We can connect to it with the Lighthouse Check Orb! By doing so you can run Lighthouse remotely versus in a local, dockerized CircleCI environment. With this we can be assured our Lighthouse results aren't flaky from CircleCI infrastructure change. Follow the <a target="_blank" href="https://github.com/foo-software/lighthouse-check-orb#usage-automated-lighthouse-check-api">documented steps to connect with Automated Lighthouse Check</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/01/automated-lighthouse-check.png" alt="Image" width="600" height="400" loading="lazy">
<em>A historical record of Lighthouse audits with "Automated Lighthouse Check"</em></p>
<h1 id="heading-what-now">What Now?</h1>
<p>You can find other of examples of <a target="_blank" href="https://github.com/foo-software/lighthouse-check-orb/tree/master/src/examples">Lighthouse Check Orb usage on GitHub</a>. I hope this article has provided a helpful addition to your DevOps workflow! With Lighthouse integrated in a CI/CD pipeline, we can stay fully equipped to ensure high quality in website SEO, performance, accessibility, best practice, and progressive web apps.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to use Lighthouse in GitHub Actions ]]>
                </title>
                <description>
                    <![CDATA[ By Adam Henson GitHub Actions are used to automate software engineering workflows. Similar to tools like CircleCI, Jenkins, Travis and many others, GitHub Actions provides a declarative API for defining workflows. These workflows can include jobs to ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-lighthouse-in-github-actions/</link>
                <guid isPermaLink="false">66d45d632472e5ed2fa07b9f</guid>
                
                    <category>
                        <![CDATA[ GitHub Actions ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Lighthouse ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 03 Dec 2019 13:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/11/zuccotti.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Adam Henson</p>
<p><a target="_blank" href="https://help.github.com/en/actions/automating-your-workflow-with-github-actions">GitHub Actions</a> are used to automate software engineering workflows. Similar to tools like CircleCI, Jenkins, Travis and many others, GitHub Actions provides a declarative API for defining workflows. These workflows can include jobs to build, test, and deploy applications. </p>
<p>Lighthouse is an open-source project from Google for improving the quality of web pages. It provides user-centric metrics to audit SEO, performance, accessibility, best practices, and progressive web apps. For a deeper dive about Lighthouse please read “<a target="_blank" href="https://www.freecodecamp.org/news/three-ways-to-analyze-website-performance-with-lighthouse-8d100966c04b/">How to analyze website performance with Lighthouse</a>”. This post will demonstrate the following:</p>
<ul>
<li>Basic implementation of Lighthouse in a GitHub Actions workflow.</li>
<li>Advanced setup to display Lighthouse results in pull request comments.</li>
<li>S3 Lighthouse report uploads.</li>
<li>Slack notifications.</li>
</ul>
<h1 id="heading-lighthouse-check-github-action">Lighthouse Check GitHub Action</h1>
<p>This post will provide a guide for using <a target="_blank" href="https://github.com/foo-software/lighthouse-check-action">Lighthouse Check Action</a> for automating Lighthouse audits. It can be used within a workflow - <a target="_blank" href="https://help.github.com/en/actions/automating-your-workflow-with-github-actions/events-that-trigger-workflows">triggered by any event</a>. This post will demonstrate how to use the action when triggered by a pull request event.</p>
<h1 id="heading-basic-example">Basic Example</h1>
<p>With the following steps we can create a basic workflow.</p>
<ol>
<li>Create and checkout a new branch locally.</li>
<li>Create a file in your project with a path similar to the following <code>.github/workflows/my-workflow.yml</code> (replacing <code>my-workflow</code> with any name of your choice).</li>
<li>Populate the file from above with the example shown below, replacing the <code>urls</code> field with a comma separated list of the URLs you’d like to test.</li>
<li>Commit changes locally and push the branch up to your remote.</li>
<li>From your new branch, open a pull request.</li>
</ol>
<pre><code class="lang-yaml"><span class="hljs-attr">name:</span> <span class="hljs-string">Lighthouse</span> <span class="hljs-string">Check</span>
<span class="hljs-attr">on:</span> [<span class="hljs-string">pull_request</span>]

<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">lighthouse-check:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>
    <span class="hljs-attr">steps:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@master</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">run:</span> <span class="hljs-string">mkdir</span> <span class="hljs-string">/tmp/artifacts</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Run</span> <span class="hljs-string">Lighthouse</span>
      <span class="hljs-attr">uses:</span> <span class="hljs-string">foo-software/lighthouse-check-action@master</span>
      <span class="hljs-attr">with:</span>
        <span class="hljs-attr">outputDirectory:</span> <span class="hljs-string">/tmp/artifacts</span>
        <span class="hljs-attr">urls:</span> <span class="hljs-string">'https://www.foo.software,https://www.foo.software/contact'</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Upload</span> <span class="hljs-string">artifacts</span>
      <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/upload-artifact@master</span>
      <span class="hljs-attr">with:</span>
        <span class="hljs-attr">name:</span> <span class="hljs-string">Lighthouse</span> <span class="hljs-string">reports</span>
        <span class="hljs-attr">path:</span> <span class="hljs-string">/tmp/artifacts</span>
</code></pre>
<p>And Voilà ? — we have a workflow with Lighthouse! Assuming you have GitHub Actions enabled in your repo, you should see something like the below (<em>note: at the time of this writing GitHub Actions are in “beta” mode and</em> <a target="_blank" href="https://github.com/features/actions"><em>require registration</em></a>).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/github-tabs.png" alt="Image" width="600" height="400" loading="lazy">
<em>GitHub repository tabs</em></p>
<p>Clicking on “Actions” will list all workflows currently running and previous.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/list-github-actions.png" alt="Image" width="600" height="400" loading="lazy">
<em>List of GitHub Actions workflows</em></p>
<p>After following the steps from our basic example, you should see one item on this list. Clicking in will show us Lighthouse results printed to the console.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/output-github-actions.png" alt="Image" width="600" height="400" loading="lazy">
<em>Lighthouse results printed out in the console</em></p>
<p>From our configuration, we also have results captured in HTML reports saved as “artifacts”.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/artifacts-github-actions.png" alt="Image" width="600" height="400" loading="lazy">
<em>Clicking through the “Artifacts” dropdown downloads the HTML reports</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/lighthouse-report-github-actions.png" alt="Image" width="600" height="400" loading="lazy">
<em>Full Lighthouse report as an HTML file downloaded from “Artifacts”</em></p>
<h1 id="heading-advanced-example">Advanced Example</h1>
<p>Lighthouse Check Action offers a complete set of bells and whistles by utilizing <code>[lighthouse-check](https://github.com/foo-software/lighthouse-check)</code> <a target="_blank" href="https://github.com/foo-software/lighthouse-check">NPM module</a> under the hood. There’s so much more we can do with this. Let’s proceed!</p>
<h2 id="heading-pull-request-comments">Pull Request Comments</h2>
<p>By utilizing this feature, comments are posted with Lighthouse results on every commit. We can do so by following the steps below.</p>
<ol>
<li>Create a new user or find an existing one to act as a “bot”.</li>
<li><a target="_blank" href="https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line">Create a personal access token</a> from this user account.</li>
<li><a target="_blank" href="https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets">Create a GitHub secret to hold the encrypted value</a> from above. In our example we name it <code>LIGHTHOUSE_CHECK_GITHUB_ACCESS_TOKEN</code>.</li>
<li>Update our workflow file with the diff shown below.</li>
<li>Commit and push.</li>
</ol>
<pre><code class="lang-yaml"><span class="hljs-attr">with:</span>
<span class="hljs-string">+</span>  <span class="hljs-attr">accessToken:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.LIGHTHOUSE_CHECK_GITHUB_ACCESS_TOKEN</span> <span class="hljs-string">}}</span>
  <span class="hljs-attr">outputDirectory:</span> <span class="hljs-string">/tmp/artifacts</span>
</code></pre>
<p>With this, we’ve created a bot to post Lighthouse results on pull requests ?!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/pr-comment-1-github-actions.png" alt="Image" width="600" height="400" loading="lazy">
<em>Lighthouse results as PR comments</em></p>
<h2 id="heading-s3-report-uploads">S3 Report Uploads</h2>
<p>In our example we persist results by uploading reports as artifacts in our workflow. This solution could be sufficient in some cases, but artifacts aren’t stored permanently. In order to view reports, we need to navigate into the workflow and manually download reports from the artifact view. </p>
<p>But what if we want a more dependable way of storing and referencing reports? This is where the S3 feature comes into play. We can configure AWS S3 storage by following the below steps.</p>
<ol>
<li><a target="_blank" href="https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/">Create an AWS account</a> if you don’t already have one.</li>
<li><a target="_blank" href="https://docs.aws.amazon.com/AmazonS3/latest/gsg/SigningUpforS3.html">Create an S3 bucket</a> if you don’t already have one.</li>
<li><a target="_blank" href="https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html">Acquire an AWS access key id and secret access key</a>.</li>
<li><a target="_blank" href="https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets">Create GitHub secrets</a> for these two values. In our example we’ll use <code>LIGHTHOUSE_CHECK_AWS_ACCESS_KEY_ID</code> and <code>LIGHTHOUSE_CHECK_AWS_SECRET_ACCESS_KEY</code>, respectively.</li>
<li>Add the bucket name and <a target="_blank" href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html">region</a> (example: <code>us-east-1</code>) as GitHub secrets: <code>LIGHTHOUSE_CHECK_AWS_BUCKET</code> and <code>LIGHTHOUSE_CHECK_AWS_REGION</code>.</li>
</ol>
<p>Next, we’ll update our configuration with the following diff.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">with:</span>
  <span class="hljs-attr">accessToken:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.LIGHTHOUSE_CHECK_GITHUB_ACCESS_TOKEN</span> <span class="hljs-string">}}</span>
<span class="hljs-string">+</span>  <span class="hljs-attr">awsAccessKeyId:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.LIGHTHOUSE_CHECK_AWS_ACCESS_KEY_ID</span> <span class="hljs-string">}}</span>
<span class="hljs-string">+</span>  <span class="hljs-attr">awsBucket:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.LIGHTHOUSE_CHECK_AWS_BUCKET</span> <span class="hljs-string">}}</span>
<span class="hljs-string">+</span>  <span class="hljs-attr">awsRegion:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.LIGHTHOUSE_CHECK_AWS_REGION</span> <span class="hljs-string">}}</span>
<span class="hljs-string">+</span>  <span class="hljs-attr">awsSecretAccessKey:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.LIGHTHOUSE_CHECK_AWS_SECRET_ACCESS_KEY</span> <span class="hljs-string">}}</span>
</code></pre>
<p>In our next commit and push, reports are automatically uploaded to S3 ✅! We also have a them linked in our PR comments.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/pr-comment-github-actions.png" alt="Image" width="600" height="400" loading="lazy">
<em>Lighthouse result PR comment with S3 report linked</em></p>
<h2 id="heading-slack-notifications">Slack Notifications</h2>
<p>What’s a new feature in a DevOps workflow without Slack notifications? A sad one indeed. Let’s ramp things up by adding notifications to a Slack channel for our whole team to see. We can accomplish this in the below steps.</p>
<ol>
<li><a target="_blank" href="https://api.slack.com/messaging/webhooks">Create an “Incoming Webhook” in your Slack workspace and authorize a channel</a>.</li>
<li>Add the Webhook URL as a <a target="_blank" href="https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets">GitHub secret</a> — <code>LIGHTHOUSE_CHECK_WEBHOOK_URL</code>.</li>
<li>Add GitHub data and the Webhook URL to our configuration with the diff below. The GitHub data will be rendered in our notifications. We pass GitHub data through configuration with the <a target="_blank" href="https://help.github.com/en/actions/automating-your-workflow-with-github-actions/contexts-and-expression-syntax-for-github-actions#github-context">GitHub “context”</a>.</li>
</ol>
<pre><code class="lang-yaml"><span class="hljs-attr">with:</span>
  <span class="hljs-attr">accessToken:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.LIGHTHOUSE_CHECK_GITHUB_ACCESS_TOKEN</span> <span class="hljs-string">}}</span>  <span class="hljs-string">+</span>  <span class="hljs-attr">author:</span> <span class="hljs-string">${{</span> <span class="hljs-string">github.actor</span> <span class="hljs-string">}}</span>
  <span class="hljs-attr">awsAccessKeyId:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.LIGHTHOUSE_CHECK_AWS_ACCESS_KEY_ID</span> <span class="hljs-string">}}</span>
  <span class="hljs-attr">awsBucket:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.LIGHTHOUSE_CHECK_AWS_BUCKET</span> <span class="hljs-string">}}</span>
  <span class="hljs-attr">awsRegion:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.LIGHTHOUSE_CHECK_AWS_REGION</span> <span class="hljs-string">}}</span>
  <span class="hljs-attr">awsSecretAccessKey:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.LIGHTHOUSE_CHECK_AWS_SECRET_ACCESS_KEY</span> <span class="hljs-string">}}</span>
<span class="hljs-string">+</span>  <span class="hljs-attr">branch:</span> <span class="hljs-string">${{</span> <span class="hljs-string">github.ref</span> <span class="hljs-string">}}</span>
  <span class="hljs-attr">outputDirectory:</span> <span class="hljs-string">/tmp/artifacts</span>
<span class="hljs-string">+</span>  <span class="hljs-attr">sha:</span> <span class="hljs-string">${{</span> <span class="hljs-string">github.sha</span> <span class="hljs-string">}}</span>
<span class="hljs-string">+</span>  <span class="hljs-attr">slackWebhookUrl:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.LIGHTHOUSE_CHECK_WEBHOOK_URL</span> <span class="hljs-string">}}</span>
  <span class="hljs-attr">urls:</span> <span class="hljs-string">'https://www.foo.software,https://www.foo.software/contact'</span>
</code></pre>
<p>Our next commit and push introduces Slack notifications! The “Lighthouse audit” link in the below screenshot navigates to the S3 report as configured✨.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/slack-github-actions.png" alt="Image" width="600" height="400" loading="lazy">
<em>Lighthouse Slack notification</em></p>
<h2 id="heading-maintaining-a-historical-record"><strong>Maintaining a Historical Record</strong></h2>
<p><a target="_blank" href="https://www.foo.software/lighthouse">Foo’s Automated Lighthouse Check</a> is tool we can use to manage a historical record of Lighthouse audits. We can connect to it with the Lighthouse Check GitHub! By doing so you can run Lighthouse remotely versus in a local, dockerized GitHub environment. With this we can be assured our Lighthouse results aren't flaky from GitHub infrastructure change. Follow the <a target="_blank" href="https://github.com/foo-software/lighthouse-check-action#usage-automated-lighthouse-check-api">documented steps to connect with Automated Lighthouse Check</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/01/automated-lighthouse-check.png" alt="Image" width="600" height="400" loading="lazy">
<em>A historical record of Lighthouse audits with "Automated Lighthouse Check"</em></p>
<h1 id="heading-what-now">What Now?</h1>
<p>You can find a full example from the above in the <a target="_blank" href="https://github.com/foo-software/lighthouse-check-action#example-usage">Lighthouse Check Action documentation</a>. I hope this article can provide a helpful addition to your DevOps workflow! With Lighthouse integrated in a CI/CD pipeline, we can stay fully equipped to ensure high quality in website SEO, performance, accessibility, best practice, and progressive web apps.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Introduction to Chrome Lighthouse ]]>
                </title>
                <description>
                    <![CDATA[ Chrome Lighthouse has been around for a while now, but what if I ask you to explain what it does can you explain vividly? I discovered that a lot of web developers, including beginners, have not heard about this tool and those who have, have not trie... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/introduction-to-chrome-lighthouse/</link>
                <guid isPermaLink="false">66d84e20f20d0925f8515ae6</guid>
                
                    <category>
                        <![CDATA[ Google Chrome ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Developer Tools ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Lighthouse ]]>
                    </category>
                
                    <category>
                        <![CDATA[ optimization ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Bolaji Ayodeji ]]>
                </dc:creator>
                <pubDate>Thu, 13 Jun 2019 12:29:44 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/06/0_ya6nIPxZPogtSBxt.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Chrome Lighthouse has been around for a while now, but what if I ask you to explain what it does can you explain vividly?</p>
<p>I discovered that a lot of web developers, including beginners, have not heard about this tool and those who have, have not tried it yet, that's not cool :(.</p>
<p>In this article, I would introduce you Chrome Lighthouse, what it does and how to start using it.</p>
<blockquote>
<p>PS: This article was first published on my <a target="_blank" href="https://bolajiayodeji.com/introduction-to-chrome-lighthouse-cjx7x1kwe00367vs1qic3jfoi">blog</a></p>
</blockquote>
<p>Let’s get started :)</p>
<blockquote>
<p><em>According to Wikipedia, A</em> <strong><em>lighthouse</em></strong> <em>is a tower, building, or other types of structure designed to emit light from a system of lamps and</em> <a target="_blank" href="https://en.wikipedia.org/wiki/Lens_%28optics%29"><em>lenses</em></a> <em>and to serve as a</em> <a target="_blank" href="https://en.wikipedia.org/wiki/Navigational_aid"><em>navigational aid</em></a> <em>for</em> <a target="_blank" href="https://en.wikipedia.org/wiki/Maritime_pilot"><em>maritime pilots</em></a> <em>at sea or on inland waterways.</em></p>
</blockquote>
<p>Okay, let's turn this into a tech term;</p>
<blockquote>
<p><em>Lighthouse is a tower, building, or other types of structure designed to emit light from a system under the “Audits” panel in Chrome Developer Tools and to serve as a guide for developers</em></p>
</blockquote>
<p>Making any sense? :)</p>
<p>Well, Lighthouse is a tool developed by Google that analyzes web apps and web pages, collecting modern performance metrics and insights on developer best practices.</p>
<p>Think of Lighthouse as the speedometer in a car that checks and balances the cars speed limit.</p>
<p>Basically, Lighthouse works with developer best practices and performance metrics. It runs checks on a web app and gives you feedback on errors, practices below standard, tips for better performance and how to fix them.</p>
<p>According to Google Developers Docs</p>
<blockquote>
<p><em>Lighthouse is an</em> <a target="_blank" href="https://github.com/GoogleChrome/lighthouse"><em>open-source</em></a><em>, automated tool for improving the quality of web pages. You can run it against any web page, public or requiring authentication. It has audits for performance, accessibility, progressive web apps, and more.</em></p>
<p><em>You can run Lighthouse in Chrome DevTools, from the command line, or as a Node module. You give Lighthouse a URL to audit, it runs a series of audits against the page, and then it generates a report on how well the page did. From there, use the failing audits as indicators on how to improve the page. Each audit has a reference doc explaining why the audit is important, as well as how to fix it.</em></p>
</blockquote>
<p>That’s pretty much all about Lighthouse, It audits the URL of a web app and generates a report telling you how bad and good your web app is according to web standards and developers best practices. Also attached to each section of the report is documentation explaining why that part of your app was audited, why you should improve that part of your app and how to fix it.</p>
<p>Here is a demo of Lighthouse audits report for this blog <a target="_blank" href="https://bolajiayodehi.com/">https://bolajiayodeji.com</a></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*UDPKsgsImqhawyB_shQfHw.png" alt="Image" width="800" height="455" loading="lazy"></p>
<p><em>L: My blog :) R: Lighthouse audits report</em></p>
<p>Pretty cool right? :)</p>
<p>What you should note is that I didn’t get great scores like this on my first audit. I had to use my first report to fix and improve the performance and quality of my app.</p>
<p>This is the idea behind Lighthouse, it is to identify and fix common problems that affect your sites performance, accessibility and user experience.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*qvGmdP7ZMfvGT9Acj1Sdgg.png" alt="Image" width="472" height="383" loading="lazy"></p>
<hr>
<p>Now, let's move to the interesting part, <strong>HOW TO GET STARTED!!</strong></p>
<p>LightHouse is available in three workflows</p>
<ul>
<li><p>Chrome Developer Tools</p>
</li>
<li><p>Command line (Node)</p>
</li>
<li><p>A Chrome extension</p>
</li>
</ul>
<p>I personally prefer using LightHouse in Dev Tools. Using the extension does not make sense as the Dev Tool and extension work in the same chrome browser, well our preference varies, use what works best for you.</p>
<p>Lighthouse was first available only with the Chrome extension before it was added to the Chrome DevTools.</p>
<p>Using lighthouse on the command line is really cool also,(For geeks :))</p>
<p><em>Let’s Get Started!!!</em></p>
<hr>
<p><strong>[1] Run Lighthouse in Chrome DevTools</strong></p>
<ul>
<li>Download Google Chrome web browser <a target="_blank" href="https://www.google.com/chrome/browser/desktop/">here</a></li>
</ul>
<blockquote>
<p><em>Note that Lighthouse can only be run on a desktop and not mobile</em></p>
</blockquote>
<ul>
<li>Go to the URL you want to audit in Google Chrome.</li>
</ul>
<blockquote>
<p><em>You can audit any URL on the web.</em></p>
</blockquote>
<ul>
<li>Open Chrome DevTools</li>
</ul>
<pre><code class="lang-bash">Command+Option+C (Mac)
Control+Shift+C (Windows, Linux, Chrome OS).
</code></pre>
<ul>
<li>Click on the <strong>Audits</strong> panel</li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*ACdyR8_RoTjoPNE4mNDeEw.png" alt="Image" width="800" height="434" loading="lazy"></p>
<p>To the left is the viewport of the page that will be audited, here that’s my blog :). To the right is the <strong>Audits panel</strong> of Chrome DevTools, which is now powered by Lighthouse</p>
<ul>
<li>Click on <strong>Run audits</strong></li>
</ul>
<blockquote>
<p><em>DevTools shows you a list of audit categories. Ensure that you leave them all checked. If you want to personalise what part of your app to be audited, you can set that by checking the categories you want to audit.</em></p>
</blockquote>
<ul>
<li>After 60 to 90 seconds — depending on your internet strength, Lighthouse gives you a report on the page.</li>
</ul>
<blockquote>
<p><em>Not that your internet speed and pre installed extensions can affect lighthouse audits. For better experience, run audits in</em> <a target="_blank" href="https://support.google.com/chrome/answer/95464?co=GENIE.Platform%3DDesktop&amp;hl=en"><strong><em>Icognito mode</em></strong></a> to avoid any interference</p>
</blockquote>
<p><strong>[2] Run Lighthouse in Command line</strong></p>
<ul>
<li><p>Download Google Chrome web browser <a target="_blank" href="https://www.google.com/chrome/browser/desktop/">here</a></p>
</li>
<li><p>Download node <a target="_blank" href="https://nodejs.org/en/">here</a>, If you have it installed already, skip this step!</p>
</li>
<li><p>Install Lighthouse</p>
</li>
</ul>
<pre><code class="lang-bash">npm install -g lighthouse
<span class="hljs-comment"># or use yarn:</span>
yarn global add lighthouse
</code></pre>
<blockquote>
<p><em>The</em> <code>-g</code> flag installs it as a global module.</p>
</blockquote>
<ul>
<li>Run your audits</li>
</ul>
<pre><code class="lang-python">lighthouse &lt;url&gt;
</code></pre>
<p>Sample;</p>
<pre><code class="lang-bash">lighthouse https://bolajiayodeji.com/
</code></pre>
<p>By default, Lighthouse writes the report to an HTML file. You can control the output format by passing flags.</p>
<p>The report can be displayed in <strong>HTML</strong> or <strong>JSON</strong> format</p>
<p>Output samples:</p>
<pre><code class="lang-bash">lighthouse
<span class="hljs-comment"># saves `./&lt;HOST&gt;_&lt;DATE&gt;.report.html`</span>

lighthouse --output json
<span class="hljs-comment"># json output sent to stdout</span>

lighthouse --output html --output-path ./report.html
<span class="hljs-comment"># saves `./report.html`</span>

<span class="hljs-comment"># <span class="hljs-doctag">NOTE:</span> specifying an output path with multiple formats ignores your specified extension for *ALL* formats</span>
lighthouse --output json --output html --output-path ./myfile.json
<span class="hljs-comment"># saves `./myfile.report.json` and `./myfile.report.html`</span>

lighthouse --output json --output html
<span class="hljs-comment"># saves `./&lt;HOST&gt;_&lt;DATE&gt;.report.json` and `./&lt;HOST&gt;_&lt;DATE&gt;.report.html`</span>

lighthouse --output-path=~/mydir/foo.out --save-assets
<span class="hljs-comment"># saves `~/mydir/foo.report.html`</span>
<span class="hljs-comment"># saves `~/mydir/foo-0.trace.json` and `~/mydir/foo-0.devtoolslog.json`</span>

lighthouse --output-path=./report.json --output json
<span class="hljs-comment"># saves `./report.json`</span>
</code></pre>
<p>Run <code>$ lighthouse --help</code> for CLI options</p>
<p><strong>[3] Run Lighthouse with the Chrome extension</strong></p>
<p><em>As I earlier said, The DevTools workflow is the best as it provides the same benefits as the Extension workflow, with the added bonus of no installation needed.</em></p>
<p><em>To use this method you need to install the extension, but If you have your reasons, here is the guide</em>;</p>
<ul>
<li><p>Download Google Chrome web browser <a target="_blank" href="https://www.google.com/chrome/browser/desktop/">here</a></p>
</li>
<li><p>Install the <a target="_blank" href="https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk">Lighthouse Chrome Extension</a> from the Chrome Webstore.</p>
</li>
<li><p>Navigate to the page you want to audit</p>
</li>
<li><p>Click <strong>Lighthouse Icon</strong>.</p>
</li>
</ul>
<blockquote>
<p><em>It should be next to the Chrome address bar. If not, open Chrome’s main menu (the three dots on the upper right) and access it at the top of the menu. After clicking, the Lighthouse menu expands.</em></p>
</blockquote>
<ul>
<li>Click <strong>Generate report</strong>.</li>
</ul>
<blockquote>
<p><em>Lighthouse runs its audits against the opened page, then opens up a new tab with a report of the results.</em></p>
</blockquote>
<p>Bingo! You did it</p>
<hr>
<p>That’s pretty much it, Lighthouse is a great tool, especially for beginners.</p>
<p>It is a very useful tool when it comes to auditing Progressive web apps.</p>
<p>I actually learned so much about optimization and performance standards when I started using Lighthouse. In no time you would become an expert in building full optimized web apps with great performance, accessibility and user experience. :)</p>
<blockquote>
<p><em>Lighthouse is not magic, it was created by humans. It is open source and</em> <a target="_blank" href="https://github.com/GoogleChrome/lighthouse/blob/master/CONTRIBUTING.md"><em>contributions are welcome</em></a><em>. Check out the repository’s</em> <a target="_blank" href="https://github.com/GoogleChrome/lighthouse/issues"><em>issue tracker</em></a> <em>to find bugs that you can fix, or audits that you can create or improve upon. The issues tracker is also a good place to discuss audit metrics, ideas for new audits, or anything else related to Lighthouse.</em></p>
</blockquote>
<p>Thank you for reading this, after installing and using Lighthouse, share your success stories in the comments!</p>
<blockquote>
<p><em>Also, I just launched</em> <a target="_blank" href="https://bolajiayodeji.com"><em>my blog</em></a> <em>where I write articles on web and frontend development, don’t forget to visit and share!!!</em></p>
</blockquote>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Boost your Developer Portfolio with GitHub Pages and Lighthouse ]]>
                </title>
                <description>
                    <![CDATA[ By Cam Barts For someone who is trying to break into software development, it doesn’t matter where you look — LinkedIn, career advice boards, youtube tutorials — the advice is always the same: you need a portfolio. freeCodeCamp knows this advise, and... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/boost-your-dev-portfolio-with-github-pages-and-lighthouse/</link>
                <guid isPermaLink="false">66d45dd5bc9760a197a10349</guid>
                
                    <category>
                        <![CDATA[ GitHub ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Lighthouse ]]>
                    </category>
                
                    <category>
                        <![CDATA[ portfolio ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 20 Mar 2019 16:33:16 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9ca42a740569d1a4ca609d.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Cam Barts</p>
<p>For someone who is trying to break into software development, it doesn’t matter where you look — LinkedIn, career advice boards, youtube tutorials — the advice is always the same: you need a portfolio. freeCodeCamp knows this advise, and they make it compulsory to create one to finish their “Responsive Web Design” Certification.</p>
<p>The portfolio is supposed to be a living document. You finish a project, you throw that bad boy onto your portfolio to show it off to the world. You constantly add to it, displaying your personal growth trajectory. You give it to potential recruiters and hiring managers to add some dimension to your resume.</p>
<p>Out of the five projects to get that certification, I put hands-down the most work into my portfolio. If it was going to be my digital first impression, I wanted to ensure that it was the best one I could make.</p>
<p>The de facto method for completing the projects on freeCodeCamp is to use codepen.io. The free version lets you code in an HTML, CSS, and JavaScript pane, and see your changes as you type them in a window. You can open the page in a full view, which eliminates the HTML, CSS, and JavaScript panes, but leaves a black banner at the top. The url is a hash, something like <a target="_blank" href="https://codepen.io/cam-barts/full/ZPWpqo">https://codepen.io/cam-barts/full/ZPWpqo</a>, which is not memorable, doesn’t give any indication about the site’s content, and in my opinion doesn’t make any waves on a resume. Furthermore, unless you pay for a membership with codepen, you can’t change it.</p>
<p>Around the time I was finishing my project, the stars aligned and I discovered two technologies that would help my portfolio stand out: Github Pages and Google Lighthouse.</p>
<p><a target="_blank" href="https://pages.github.com/">Github Pages</a> allows you to host a website directly from a GitHub repository. It offers a pretty slick github.io url, which tickled my fancy for something to put on a resume. It would allow me full control of what my users would see when they navigated to the site (so long, black banner), and I wouldn’t have to deal with self hosting or paying for some other hosting service.</p>
<p>I heard about <a target="_blank" href="https://developers.google.com/web/tools/lighthouse/">Google Lighthouse</a> in the <a target="_blank" href="https://www.codenewbie.org/podcast/what-are-progressive-web-apps">CodeNewbie Podcast featuring Frances Coronel</a>. It audits your website straight from Chrome Dev Tools for five areas: Performance, Progressive Web App, Accessibility, Best Practices, and SEO. SEO, or Search Engine Optimization, is what helps your site float to the top of search engines like Google, which helps you get found. Also, now that I was going to host my site on Pages, I wanted to take responsibility for my site’s performance, and to effectively do that I had to at least have a benchmark.</p>
<p>My goal in writing this article is to help you create a blazing fast, professional looking portfolio site at no cost to you. I want it to be something you’re proud to post about on LinkedIn and plaster on the top of your resume, and I want to leverage GitHub Pages and Google Lighthouse to do it.</p>
<p>To go any further, I’ve made a few assumptions. The first is that you have a Github account. If you don’t already have one, <a target="_blank" href="https://github.com/join">creating one is easy.</a> The second is that you have a basic understanding of git. If you’re brand new, there are plenty of excellent <a target="_blank" href="https://medium.freecodecamp.org/what-is-git-and-how-to-use-it-c341b049ae61">articles</a> on getting started. This article assumes you’ve completed your portfolio on codepen. Finally, you should have Google Chrome installed.</p>
<p>This article follows my personal portfolio. You can find the pen <a target="_blank" href="https://codepen.io/cam-barts/pen/ZPWpqo">here</a>, the code <a target="_blank" href="https://github.com/cam-barts/cam-barts.github.io">here</a>, and the final product is at <a target="_blank" href="https://cam-barts.github.io/">cam-barts.github.io</a>.</p>
<h3 id="heading-getting-started">Getting started</h3>
<p>Setting up your Github Pages site is pretty straightforward. The TL;DR version is:</p>
<ul>
<li>Create Repository following name convention [GitHub Username].github.io</li>
<li>Clone Locally</li>
<li>Create <em>index.html</em>, <em>style.css</em>, <em>script.js</em> files within repository</li>
<li>Add code to those files</li>
<li>Commit and push to GitHub</li>
<li>Profit!</li>
</ul>
<p>You create a repository with a title that follows the convention [Your Github Username].github.io. Here is mine: cam-barts.github.io. Whatever code gets pushed to that repository gets displayed when you navigate to that site.</p>
<p>So, when you’ve cloned the repository locally, what exactly do you put into it?</p>
<p>You should start with three files, an <em>index.html</em> file, a <em>style.css</em> file, and a <em>script.js</em> file. In whatever editor you like (I use <a target="_blank" href="https://atom.io/">Atom</a>), you should start with the following code snippet in your <em>index.html</em>:</p>
<p>There is a lot going on here that might be unfamiliar if you have only been working with codepen.io.</p>
<p>The <em>dir</em> attribute in the html tag indicates that the document should be read <strong>L</strong>eft <strong>T</strong>o <strong>R</strong>ight. That just ensures that when your page shows up, all of the elements are left justified, which is how English speakers read.</p>
<p>The meta tags in the head indicate metadata about the page, which helps search engines like Google index your site.</p>
<p>At this point, you should go ahead fill out the meta tags and the title tag. Note that the <em>keywords</em> meta tag’s content should be comma separated, and should include terms that you would want people to use in Google to find your portfolio. Here’s what mine looks like:</p>
<p>The next step is to copy the HTML section of your portfolio pen into the body section of your snippet. Once that’s completed, if you linked to any outside CSS or JS in your pen settings, such as to <a target="_blank" href="https://getbootstrap.com/">Bootstrap</a> or <a target="_blank" href="https://fontawesome.com/?from=io">Font Awesome</a>, you need to link those in your <em>index.html</em>.</p>
<p>Create more link tags for css and script tags for JavaScript and add the links that are in the settings to the <em>href</em> and <em>src</em> attributes, respectively. To ensure that your styles and scripts show up, be sure to put them before the existing link and script tags in the snippet. For example, linking to Bootstrap and JQuery would look like:</p>
<p>Next, you need to add your own CSS into your <em>style.css</em>, and if you have any JavaScript, add that to your <em>script.js</em>.</p>
<p>After you’ve done that, you’re good to commit all your work and push it to Github. Immediately after you do that, you can navigate to [Your Github Username].github.io and check out your website!</p>
<h3 id="heading-optimizing-your-portfolio-site">Optimizing your portfolio site</h3>
<p>Congratulations on publishing your portfolio!</p>
<p>The next steps involve optimizing your site. For this, we will use <a target="_blank" href="https://developers.google.com/web/tools/lighthouse/">Google Lighthouse</a>. It is better to do this in an In Private Browser window so that any cache or Chrome extensions you may have will not affect the results. When you navigate to your site, open Chrome Developer Tools (Ctrl + Shift+ i) and click on the <em>Audits</em> tab.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*7v572NCjU_EmmpcSfIzHdQ.png" alt="Image" width="800" height="845" loading="lazy">
<em>Google Lighthouse Pane</em></p>
<p>Progressive Web Apps are outside of the scope of this tutorial, but there is no harm in running all of the audits. When you run them, you should get a page that looks like this:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*YJ54LEN5nN3AuoJ5VEVHYg.png" alt="Image" width="800" height="801" loading="lazy"></p>
<p>The best thing about these reports is that it gives you “Opportunities” to improve your scores.</p>
<p>In the performance section, it tells you to serve next gen file formats such as WebP versus traditional .PNG images, and suggests lazy loading the images.</p>
<p>In the SEO section, it suggests SEO improvements such as adding a description meta tag and using legible font sizes. Not only does it make these suggestions, it links to articles with practical examples with things to change in your code to optimize for those areas.</p>
<p>For me, it only took an hour to get the scores for my site in the high 90s for Performance, Accessibility, Best Practices, and SEO. You can see all to the changes I made <a target="_blank" href="https://githistory.xyz/cam-barts/cam-barts.github.io/blob/master/index.html">here</a>.</p>
<h3 id="heading-going-further">Going further</h3>
<p>Next steps for your site are up to you. You could link it to <a target="_blank" href="https://analytics.google.com/analytics/web/">Google Analytics</a> to see how many visitors your Portfolio is getting. You could add sections for your awards to show your freeCodeCamp certifications as you get them. The evolution of your site is completely in your hands! Comment links to your portfolio below.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to improve performance in your apps with Lighthouse, Webpack, and React Loadable Components ]]>
                </title>
                <description>
                    <![CDATA[ By Adam Henson An overview of modern concepts, tools and example strategies to improve web page performance Not Impressed at Penn Station In March of 2018 Google confirmed rumors by announcing the migration of sites for “mobile-first” indexing. What... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/taming-performance-in-todays-web-app-with-lighthouse-webpack-and-react-loadable-components-b2d3fa04e0ab/</link>
                <guid isPermaLink="false">66c3603fc337fbd10a4b5973</guid>
                
                    <category>
                        <![CDATA[ Lighthouse ]]>
                    </category>
                
                    <category>
                        <![CDATA[ performance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ webpack ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 27 Feb 2019 13:57:16 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*9I7geT-jjXNgvszViOfLQA.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Adam Henson</p>
<h4 id="heading-an-overview-of-modern-concepts-tools-and-example-strategies-to-improve-web-page-performance">An overview of modern concepts, tools and example strategies to improve web page performance</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*9I7geT-jjXNgvszViOfLQA.jpeg" alt="Image" width="800" height="468" loading="lazy">
<em>Not Impressed at Penn Station</em></p>
<p>In March of 2018 Google confirmed rumors by announcing the migration of sites for <a target="_blank" href="https://webmasters.googleblog.com/2018/03/rolling-out-mobile-first-indexing.html">“mobile-first” indexing</a>.</p>
<h3 id="heading-what-this-means">What this Means</h3>
<blockquote>
<p>Mobile-first indexing means Google will predominantly use the mobile version of the content for indexing and ranking. Historically, the index primarily used the desktop version of a page’s content when evaluating the relevance of a page to a user’s query. Since the majority of users now access Google via a mobile device, the index will primarily use the mobile version of a page’s content going forward. We aren’t creating a separate mobile-first index. We continue to use only one index.~[Prepare for mobile-first indexing](http://Mobile-first indexing means Google will predominantly use the mobile version of the content for indexing and ranking. Historically, the index primarily used the desktop version of a page's content when evaluating the relevance of a page to a user's query. Since the majority of users now access Google via a mobile device, the index will primarily use the mobile version of a page's content going forward. We aren't creating a separate mobile-first index. We continue to use only one index.)</p>
</blockquote>
<p>“Yikes!” — you may be thinking. This is a reasonable reaction for anyone owning a website relying on organic search results for its success. Consider extreme examples of websites that drive millions of dollars a day who’ve come to depend on such rankings. Many of these websites weren’t necessarily built to support mobile devices as the highest priority.</p>
<h3 id="heading-confronting-performance">Confronting Performance</h3>
<p>The first step in ensuring optimal performance of a web page on a mobile device is to understand key metrics in modern testing. We can go straight to the source by utilizing <a target="_blank" href="https://developers.google.com/web/tools/lighthouse/">Lighthouse</a>, Google’s open-source tool. You can run it in Chrome DevTools, from the command line, or as a Node module.</p>
<p>Lighthouse has a variety of options to allow performance testing under a variety of conditions, specifically notable being device and connection type.</p>
<h4 id="heading-lighthouse-metrics-and-scoring">Lighthouse Metrics and Scoring</h4>
<p>In a Lighthouse performance audit, results are provided as a set of metrics with values. The score is a number between 0 and 100 where the higher number is better. Score is calculated by a weighted group of select metrics as explained in the <a target="_blank" href="https://developers.google.com/web/tools/lighthouse/v3/scoring">documentation</a>.</p>
<blockquote>
<p>Load is not a single moment in time — it’s an experience that no one metric can fully capture. There are multiple moments during the load experience that can affect whether a user perceives it as “fast” or “slow”.</p>
<p>~ <a target="_blank" href="https://w3c.github.io/paint-timing/">Paint Timing Spec</a></p>
</blockquote>
<p>Not only does each metric capture a characteristic of page load, but each metric can encompass the results of others.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*_hTRAwcLq5BHF_YMPkcBjw.jpeg" alt="Image" width="800" height="396" loading="lazy">
<em>Nobody is perfect — an audit of the Lighthouse’s own documentation page</em></p>
<h3 id="heading-opportunities-for-improvement-and-solutions">Opportunities for Improvement and Solutions</h3>
<p>I’ve identified a few commonly low metrics with fairly straightforward solutions, depending on complexity. “<a target="_blank" href="https://developers.google.com/web/tools/lighthouse/audits/time-to-interactive">Time to Interactive</a>” is one of the most important.</p>
<h4 id="heading-time-to-interactive">Time to Interactive</h4>
<p>At the time of this writing, the “Time to Interactive” metric is weighted highest in its influence on the overall performance score.</p>
<blockquote>
<p>The Time to Interactive (TTI) metric measures how long it takes a page to become interactive. “Interactive” is defined as the point where:</p>
<p>The page has displayed useful content, which is measured with <a target="_blank" href="https://developers.google.com/web/tools/lighthouse/audits/first-contentful-paint">First Contentful Paint</a>.</p>
<p>Event handlers are registered for most visible page elements.</p>
<p>The page responds to user interactions within 50 milliseconds.</p>
<p>To improve your TTI score, defer or remove unnecessary JavaScript work that occurs during page load. See <a target="_blank" href="https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/javascript-startup-optimization/">Optimize JavaScript Bootup</a> and <a target="_blank" href="https://developers.google.com/web/fundamentals/performance/optimizing-javascript/tree-shaking/">Reduce JavaScript Payloads with Tree Shaking</a>, and <a target="_blank" href="https://developers.google.com/web/fundamentals/performance/optimizing-javascript/code-splitting/">Reduce JavaScript Payloads with Code Splitting</a>.</p>
<p>~<a target="_blank" href="https://developers.google.com/web/tools/lighthouse/audits/time-to-interactive">Time to Interactive</a></p>
</blockquote>
<h4 id="heading-improving-time-to-interactive">Improving Time to Interactive</h4>
<p>Webpack provides sophisticated customization nowadays to improve optimization. It provides out of the box configuration options to split code and prevent duplication as illustrated in the <a target="_blank" href="https://webpack.js.org/guides/code-splitting/#prevent-duplication">documentation</a>. By using <a target="_blank" href="https://github.com/webpack-contrib/webpack-bundle-analyzer">Webpack Bundle Analyzer</a>, we can visualize the outcome of a “prevent duplication” code splitting approach.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*Kh0cpk3G0KKWym0ZC_ZLcg.png" alt="Image" width="800" height="339" loading="lazy">
<em>Webpack Bundle Analyzer: Standard code splitting of a “vendors” bundle</em></p>
<p>Okay, well… could be worse ?! The important part is we separated common code. By doing this alone we relieve work from the main execution thread, provide asset caching potential, and other interesting things a<a target="_blank" href="https://developers.google.com/web/fundamentals/performance/optimizing-javascript/code-splitting/">s detailed by Addy Osmani and Jeremy Wagner.</a> But wait… there’s more!</p>
<h4 id="heading-dynamic-code-splitting">Dynamic Code Splitting</h4>
<p>We talked about one approach above. Another code splitting technique supported by Webpack involves the use of <a target="_blank" href="https://webpack.js.org/guides/code-splitting/#dynamic-imports">dynamic imports</a>. I accomplished this fairly easily with staggering results by using <a target="_blank" href="https://github.com/smooth-code/loadable-components">Loadable Components</a> to handle rendering in my “universal” app. I chose this library in its support of “Server Side Rendering” and <a target="_blank" href="https://www.smooth-code.com/open-source/loadable-components/docs/server-side-rendering/">documentation of it</a>. It provides a <a target="_blank" href="https://www.smooth-code.com/open-source/loadable-components/docs/api-loadable-webpack-plugin/">Babel Plugin</a> (which delegates chunks under the hood during build) and a <a target="_blank" href="https://www.smooth-code.com/open-source/loadable-components/docs/api-loadable-server/#chunkextractor">Chunk Extractor</a> — to collect chunks server side and provide script tags on page render. This seems confusing, so enough with the words… let’s role up our sleeves!</p>
<p>Imagine a page component, defined with a dynamic import.</p>
<p>And to process and delegate Loadable Components during build, we can configure Webpack with the Babel plugin (mentioned above).</p>
<p>In our client side render entry, we wrap in <a target="_blank" href="https://www.smooth-code.com/open-source/loadable-components/docs/server-side-rendering/#4-add-loadableready-client-side">Loadable Ready</a>. Loadable Components loads all your scripts asynchronously to ensure optimal performance. All scripts are loaded in parallel, so you have to wait for them to be ready using <code>loadableReady</code> .</p>
<p>On server side render, Loadable Components <code>ChunkExtractor</code> provides only the script tags used by initial page load and the rest asynchronously, client side! JS is loaded on-demand, behind the scenes.</p>
<p>Dynamically extracting script and style tags needed by a particular page is quite powerful. I used dynamic imports in all page components and components that uniquely import heavy libraries. What a difference! ?</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*Po8Fa2q8eV-s6XCkIAioGQ.png" alt="Image" width="800" height="388" loading="lazy">
<em>Webpack Bundle Analyzer: Dynamic code splitting</em></p>
<p>We reduced the main vendor bundle by more than 100kb. The blue squares in the image above represent bundles created with dynamically imported page components. The large violet square in the top middle is a vendor split bundle from one specific component I identified as uniquely importing large libraries.</p>
<h4 id="heading-okay-did-we-actually-do-anything">Okay, Did We Actually Do Anything?</h4>
<p>The short answer is — yes!! We can see how JS is loaded by examining the network panel in Chrome Dev Tools. Let’s assume a request to a home page.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*CPgpl5GFDBkqb6H8zrauiw.jpeg" alt="Image" width="800" height="120" loading="lazy">
<em>Chrome Dev Tools network panel: An example home page</em></p>
<p>Okay, wait… it’s all coming back now…</p>
<blockquote>
<p>An alternative to large bundles is code-splitting, which is where JavaScript is split into smaller chunks. This enables sending the minimal code required to provide value upfront, improving page-load times. The rest can be loaded on demand.</p>
<p>~ <a target="_blank" href="https://developers.google.com/web/fundamentals/performance/optimizing-javascript/code-splitting/">Reduce JavaScript Payloads with Code Splitting</a></p>
</blockquote>
<p>Aha, we can see this in action here as a user navigates to another route client side. Assume the user navigates to a “dashboard” page from the home page. <code>Dashboard.fc4871b3.js</code> is downloaded on demand!</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*3fDQdS0c-CAd9dRTuOL3KQ.jpeg" alt="Image" width="800" height="104" loading="lazy">
<em>Chrome Dev Tools network panel: An example home page and client side navigation to a “dashboard” page</em></p>
<p>And… Google loves it! With the above changes, I saw a Lighthouse score improvement of more than 10 points. ?</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*RC7X-N0kf8qOKnGRVwmPWw.jpeg" alt="Image" width="800" height="405" loading="lazy">
<em>A Lighthouse audit with success written all over it!</em></p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>By utilizing a recipe of modern tools and features, we can effectively identify, measure, visualize and address web page performance. This is important in accommodating Google’s mobile-first indexing. Key metrics documented by Google to measure performance, such as “<a target="_blank" href="https://developers.google.com/web/tools/lighthouse/audits/time-to-interactive">Time to Interactive</a>”, can help us pinpoint opportunities for improvement.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ GraphQL in Laravel done right: how to set up Lighthouse in a simple blog ]]>
                </title>
                <description>
                    <![CDATA[ By Oliver Nybroe Recently a new package has revolutionized the creation of a GraphQL API in Laravel. This package makes it so simple and easy to set up a GraphQL server, that it gives you the same feeling you had the first time you worked with Larave... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/graphql-in-laravel-done-right-9cf123d5601b/</link>
                <guid isPermaLink="false">66c34bea465d1b2f886ba3c7</guid>
                
                    <category>
                        <![CDATA[ GraphQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Laravel ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Lighthouse ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 01 May 2018 09:17:09 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*y_uXqbzjq767fB9TrY1vzw.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Oliver Nybroe</p>
<p>Recently a new package has revolutionized the creation of a GraphQL API in Laravel. This package makes it so simple and easy to set up a GraphQL server, that it gives you the same feeling you had the first time you worked with Laravel, “<em>What magic is this!</em>”. This package is, of course, <a target="_blank" href="https://lighthouse-php.netlify.com/">Lighthouse</a>.</p>
<p>In this article, I will cover how to set up Lighthouse with a simple blog example. I will assume that you already are familiar with the basics of GraphQL. The example will let you get and create articles via GraphQL. Lighthouse uses a schema approach. You define your API by creating a GraphQL schema, then use directives to add bindings with Laravel.</p>
<h3 id="heading-installment">Installment</h3>
<p>For getting started, simply add the package via composer and publish the config file. (The package <code>laravel-graphql-playground</code> is a GraphQL browser client which is optional.)</p>
<pre><code>$ composer <span class="hljs-built_in">require</span> nuwave/lighthouse$ php artisan vendor:publish --provider=<span class="hljs-string">"Nuwave\Lighthouse\Providers\LighthouseServiceProvider"</span>$ composer <span class="hljs-built_in">require</span> mll-lab/laravel-graphql-playground$ php artisan vendor:publish --provider=<span class="hljs-string">"MLL\GraphQLPlayground\GraphQLPlaygroundServiceProvider"</span>
</code></pre><h3 id="heading-creating-the-schema">Creating the schema</h3>
<p>Now for the interesting part: when setting up this package, we just have to create the following file <code>routes/graphql/schema.graphql</code>. This file is the one containing our whole schema for the graphql server.</p>
<p>To get started we will add a simple endpoint for getting all posts in our database. For doing this we first need to create our Article type in the schema file.</p>
<pre><code>...type Article {    <span class="hljs-attr">id</span>: ID!    title: <span class="hljs-built_in">String</span>!    body: <span class="hljs-built_in">String</span>!    author: User!}
</code></pre><h4 id="heading-defining-the-schema-query">Defining the schema query</h4>
<p>We now have two types, a type for articles and one for users, so we can get the author of the post. However we still don’t have any endpoints for the articles, so let’s add one in the schema file.</p>
<pre><code>type Query {  ...  articles: [Article]! @paginate(type: <span class="hljs-string">"paginator"</span> model: <span class="hljs-string">"Article"</span>)}
</code></pre><p>Now some more magic is happening. We are adding a custom directive called <code>paginate</code>. This directive adds pagination for the given model supplied (in this case Article). We are also saying it should use the type <code>paginator</code> which will result in it making a pagination-compatible type for us.</p>
<p>For browsing the endpoints, let’s open up the GraphQL client we installed by going to <code>your-url.test/graphql-playground</code>. In the schema, we can now see that a new type called <code>ArticlePaginator</code> is added. The endpoint <code>articles</code> is returning an instance of the <code>ArticlePaginator</code>.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*IAcFIeIGTk-9qMrdh0i0ng.png" alt="Image" width="800" height="541" loading="lazy">
<em>Screenshot from graphql-playground</em></p>
<h4 id="heading-running-the-query">Running the query</h4>
<p>So let’s create a simple query to get 10 articles with their title and the name of the author.</p>
<pre><code>query {  articles(count: <span class="hljs-number">10</span>) {    data {      title      author {        name      }    }  }}
</code></pre><p>When we run this query, it results in an error saying that it was not able to find a class called <code>Article</code>. This makes sense as we haven’t created the model yet. This debug message is only visible because we are not running in a production environment.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*QxpBku6o7YILTd7ruavSpA.png" alt="Image" width="800" height="357" loading="lazy">
<em>Screenshot from graphql-playground showing error of no Article class</em></p>
<h3 id="heading-creating-our-model-and-migrations">Creating our model and migrations</h3>
<p>So let’s create our models and migrations. By default, Lighthouse looks for models inside <code>app/models</code>. To make it easier we will add the Article model in here. We do not have to move the User model as in the schema file, the namespace for User has been typed directly.</p>
<pre><code>$ php artisan make:model Models\\Article -m
</code></pre><p>Then update the migration and the models:</p>
<h4 id="heading-querying-the-articles">Querying the articles</h4>
<p>Now that our models and migrations are set up, let’s migrate the database and check if it still fails.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*q5g3oVVj0N-2hl6xS2DBYg.png" alt="Image" width="800" height="218" loading="lazy">
<em>Screenshot from graphql-playground showing no result</em></p>
<p>So we can see now that the endpoint works, but we have no data in the database. We will add some manually and then later tackle how to do this through GraphQL.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*8Ud6YZtAsMbj0ArK5v71Hw.png" alt="Image" width="800" height="448" loading="lazy">
<em>Screenshot from graphql-playground showing articles</em></p>
<p>Great! We are now able to fetch articles through GraphQL. Let’s also add support for getting the articles from a user instead. For doing this we have to change our GraphQL <code>user</code> type to have a relationship to articles.</p>
<pre><code>...type User {  <span class="hljs-attr">id</span>: ID!  name: <span class="hljs-built_in">String</span>!  email: <span class="hljs-built_in">String</span>!  created_at: DateTime!  updated_at: DateTime!  articles: [Article] @hasMany(relation:<span class="hljs-string">"articles"</span> type:<span class="hljs-string">"paginator"</span>)}
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/1*gBXB_T_1jbQ1arC76nPbyw.png" alt="Image" width="800" height="407" loading="lazy">
<em>Screenshot from graphql-playground showing articles from user</em></p>
<p>As this is GraphQL, we could keep chaining it. So we can get the author now from the article and then the articles from that author and so on (even though that would be rather pointless).</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*JrfHjTerwsuD6tLxD_cpnw.png" alt="Image" width="800" height="592" loading="lazy">
<em>Screenshot from graphql-playground showing pointless query</em></p>
<h3 id="heading-creating-a-mutator">Creating a mutator</h3>
<p>Now let’s add a mutator for creating a new article. This endpoint will also need authentication. Of course, we need to be a user in the system before we can create a new article. To do this we will use Laravel’s middleware <code>auth:api</code>. Remove all the previous mutations, as we do not need them, and add the following:</p>
<pre><code>type Mutation @group(middleware: [<span class="hljs-string">"auth:api"</span>]) {    createArticle(title: <span class="hljs-built_in">String</span>!, body: <span class="hljs-built_in">String</span>!): Article        @create(model: <span class="hljs-string">"Article"</span>)        @inject(context: <span class="hljs-string">"user.id"</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">"author_id"</span>)}
</code></pre><h4 id="heading-authenticating-the-mutator">Authenticating the mutator</h4>
<p>To use the <code>auth:api</code> middleware, we will need to set up a <code>Guard</code>. For this example, we will just use the <code>TokenGuard</code>. For using the token guard, we need to add a field to the user called <code>api_token</code>, and then the value there is your token.</p>
<pre><code>Schema::create(<span class="hljs-string">'users'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">Blueprint $table</span>) </span>{    $table-&gt;increments(<span class="hljs-string">'id'</span>);    $table-&gt;string(<span class="hljs-string">'name'</span>);    $table-&gt;string(<span class="hljs-string">'email'</span>)-&gt;unique();    $table-&gt;timestamp(<span class="hljs-string">'email_verified_at'</span>)-&gt;nullable();    $table-&gt;string(<span class="hljs-string">'password'</span>);    $table-&gt;string(<span class="hljs-string">'api_token'</span>); <span class="hljs-comment">// The new API token field    $table-&gt;rememberToken();    $table-&gt;timestamps();});</span>
</code></pre><p>Now we manually add the token in the database and set it to <code>secret</code> (you can create your own UI for setting the token or use <a target="_blank" href="https://laravel.com/docs/5.8/passport">Laravel Passport</a>). We then add this token to our request, so we are authenticated.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*MZJI3CzdGJn_UvWdXgWg_g.png" alt="Image" width="800" height="291" loading="lazy">
<em>Screenshot from graphql-playground showing headers</em></p>
<h4 id="heading-using-the-mutator">Using the mutator</h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*HsC1fl7a8hNDkHBHAWPaGQ.png" alt="Image" width="800" height="291" loading="lazy">
<em>Screenshot from graphql-playground showing mutation</em></p>
<p>We now have a new article, and we can see that the author who made it was our authenticated user. So now we have a really simple GraphQL API up and running, but with support for getting our articles and creating them!</p>
<p>Hope you enjoyed this post, and if you would like to know more visit <a target="_blank" href="https://lighthouse-php.com/">Lighthouse documentation</a>. You can also find the example created above on <a target="_blank" href="https://github.com/olivernybroe/lighthouse-intro-article">Github</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
