<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: David Broadlick</title>
    <description>The latest articles on Forem by David Broadlick (@dbroadlick).</description>
    <link>https://forem.com/dbroadlick</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F427805%2F8af069de-fc23-4c9c-a7b8-26754e7da7d6.jpg</url>
      <title>Forem: David Broadlick</title>
      <link>https://forem.com/dbroadlick</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/dbroadlick"/>
    <language>en</language>
    <item>
      <title>Integrating Nuxt Into a Build Pipeline</title>
      <dc:creator>David Broadlick</dc:creator>
      <pubDate>Thu, 09 Jul 2020 14:00:55 +0000</pubDate>
      <link>https://forem.com/dbroadlick/integrating-nuxt-into-a-build-pipeline-i5l</link>
      <guid>https://forem.com/dbroadlick/integrating-nuxt-into-a-build-pipeline-i5l</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://formcake.com/blog/using-nuxt-in-a-build-pipeline" rel="noopener noreferrer"&gt;Formcake’s blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We are huge fans of &lt;a href="https://nuxtjs.org/" rel="noopener noreferrer"&gt;Nuxt&lt;/a&gt; at &lt;a href="https://nuxtjs.org/" rel="noopener noreferrer"&gt;Formcake&lt;/a&gt;. It's everything developers like about Vue, having a solid and easy to understand feature set, but applied to the complicated world of Server Side Rendering and static generation. There is one aspect to Nuxt however that is a bit confusing and hard to grapple with for beginners. In this blog post we will go into how to effectively integrate Nuxt into a build pipeline.&lt;/p&gt;

&lt;p&gt;For those who have not used Nuxt, here is a very high level description. Nuxt is a project in the Vue ecosystem that makes it very simple to create Vue based apps that run as a SSR application using node or as a static website. Configuring SSR and static site generation correctly with a javascript framework are notoriously hard problems to roll on your own and Nuxt makes creating a Vue based app insanely simple for the hobbiest or the enterprise user.&lt;/p&gt;

&lt;p&gt;In this article we are going to focus on integrating a Nuxt application that generates all of it's pages before deploying to a static site hosting platform. If you follow our blog at all, then you may have also caught onto the fact that we are huge fans of static sites and the JAMStack paradigm. One of the many benefits that we love about static websites is that each build of your site is like a health check of the entire site. If you have ever maintained a large website then you may have had the experience of stumbling upon a broken page from time to time. This is far less likely to happen with a static site generated with the correct build configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example Nuxt Project
&lt;/h2&gt;

&lt;p&gt;To help illustrate this guide I created a simple &lt;a href="https://github.com/Formcake/nuxt-blog" rel="noopener noreferrer"&gt;boilerplate Nuxt project&lt;/a&gt;. This is nothing more than a &lt;a href="https://nuxtjs.org/guide/installation/#using-code-create-nuxt-app-code-" rel="noopener noreferrer"&gt;npx installed version&lt;/a&gt; of Nuxt with just a few changes. I also went ahead and hooked this project up to &lt;a href="https://www.netlify.com/" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt; in order to get a simple build process for deployment. Any build process would work the same way whether it be &lt;a href="https://github.com/features/actions" rel="noopener noreferrer"&gt;Github Actions&lt;/a&gt; or &lt;a href="https://aws.amazon.com/codepipeline/" rel="noopener noreferrer"&gt;AWS Codepipeline&lt;/a&gt;. You can find the Netlify site for this project &lt;a href="https://example-nuxt-blog.netlify.app/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Setup
&lt;/h3&gt;

&lt;p&gt;In order to have something to build I first created a "blog" page type that expects a title path in Nuxt within the pages directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pages
  /blog
    _title.vue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The idea behind having a blog page content type is that I now have something to build that would theoretically come from an api or a flat file system. This source of data may not always be configured properly and if it is not, then we want our build to fail.&lt;/p&gt;

&lt;p&gt;The next thing I did was build a mock api endpoint as a simple javascript file that exports an object located within the mock-api directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mock-api
  /blog-pages.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The data within the endpoint simply contains an array of "blog posts" with each post being represented as an object. Each post only contains two keys, a "route" and a "title". The "route" is used to match which post is tied to which page and the "title" is simply the title of the blog post. A real blog api would also contain a post description, the content for the post, and maybe an image for the header but this data works well enough to get my point across. You may notice that the last blog post does not contain the title of the post. This is where we are going to hang our deployment failure on when it comes time to build the site since this should be considered required information for rendering a blog page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;route&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;how-to-use-nuxt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;How To Use Nuxt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;route&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nuxt-performance&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Getting The Most Out Of Nuxt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;route&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nuxt-vs-next&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A Comparison of Nuxt vs Next&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;route&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nuxt-ssr-guide&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the blog post page, pages/blog/_title.vue, we simply query our mock posts api, match up the route using the array find method, check to make sure the title exists, and return the page data to the component if it does. If the post does not contain the title then we throw an error. In our example a post page simply renders the &lt;a href="https://example-nuxt-blog.netlify.app/blog/how-to-use-nuxt/" rel="noopener noreferrer"&gt;title&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;mockApi&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;~/mock-api/blog-pages.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;asyncData &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pageData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mockApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;route&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;pageData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Blog API call for &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; did not return required blog information`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;pageData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Build Process
&lt;/h3&gt;

&lt;p&gt;By default Nuxt provides great production build commands. It generates pages that are well optimized and has some nice logs that can help with debugging when things go wrong. The problem however is that a Nuxt build will not return a non zero exit code when its fails to build a page. Let's take a closer look at the boilerplate &lt;code&gt;yarn generate&lt;/code&gt; command. The contents of this command are a combination of the nuxt build and nuxt export commands&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nuxt build --target static &amp;amp;&amp;amp; nuxt export
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The yarn command generate first builds the project for static and then exports the build into the dist directory within the root of the project. for those playing along, the only configuration you need to setup to get this project running within Netlify is setting which build command to run and which directory has the built site. As you can see in the screenshot below, our build command is set to the default Nuxt production build command &lt;code&gt;yarn generate&lt;/code&gt; and our publish directory is set to "dist".&lt;/p&gt;

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

&lt;p&gt;This setup works great until you have a build where a page fails to generate. This could happen for any number of reasons. Perhaps your CMS or Database is missing a field like in our example or perhaps a request simply timed out. The screen capture below further illustrates the issue with using Nuxt's default production build. The page /blog/nuxt-ssr-guide failed to build as we expect, but the build succeeded!&lt;/p&gt;

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

&lt;p&gt;In order to make production builds properly fail, we must add the &lt;code&gt;--fail-on-error&lt;/code&gt; flag to the &lt;code&gt;nuxt export&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nuxt build --target static &amp;amp;&amp;amp; nuxt export --fail-on-error
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This single flag fix gives us the build result we expect. The screen capture below shows that after changing the build command within Netlify to &lt;code&gt;yarn generate-prod&lt;/code&gt;, we now have a build that fails properly.&lt;/p&gt;

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

&lt;p&gt;And there you have it, a one flag fix to a potentially very serious problem if ignored.&lt;/p&gt;

&lt;h2&gt;
  
  
  Notes
&lt;/h2&gt;

&lt;p&gt;Until very recently the &lt;code&gt;nuxt generate&lt;/code&gt; command was the standard way to build a production version of a static Nuxt site. This just changed in 2.13 on June 18th 2020. The documentation currently states that a combination of &lt;code&gt;nuxt build&lt;/code&gt; and &lt;code&gt;nuxt export&lt;/code&gt; should be used for any version of Nuxt &amp;gt;= 2.13. I still like having a convenient generate command and so I created the &lt;code&gt;yarn generate&lt;/code&gt; and &lt;code&gt;yarn generate-prod&lt;/code&gt; commands myself within the package.json file. Feel free to organize your production build commands however you like within your Nuxt project but just know that these are not boilerplate.&lt;/p&gt;

&lt;p&gt;I would also probably not use this exact setup for generating pages in a Nuxt project but I wanted to show this process with the use of the asyncData method. I would most likely do all of the generation logic within the nuxt.config.js and pass the page's route along with it's data to the generate option.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>vue</category>
      <category>nuxt</category>
    </item>
  </channel>
</rss>
