Nuxt.js

To be short(er) and precise, Nuxt.js can be defined as a free, open-source web application framework that is based on Webpack, Babel.js, Vue.js, and Node.js. The framework is often referred to as a “meta-framework” for universal applications, with the term universal meaning the possibility of creating JavaScript web views with the Vue.js single file component system and the ability to function both as in-browser SPA views (single page application) and as server-rendered web views which can be rehydrated to full SPA functionality.

Apart from that, the framework also enables users to view contents or parts of content fully server pre-rendered and served in a static site generation manner.

This approach ensures reduced interactivity time and better SEO when compared to traditional SPAs because the full content of the page is served by the server before any client-side JS-action can be executed.

To be more precise, Nuxt.js can enable developers to maintain both the positives that come from traditional server-side rendered pages and the advanced user interface of Single Page Apps, not to mention the improved interactivity they often provide.

What the Nuxt.js framework does best is simplifying the app setup and configuration enabling them to develop the UI portions of the app faster and more streamlined, like they would in a Vue.js single file application.

Getting started: The basics

This progressive framework is based on Vue.js official libraries (vue, vue-router, veux) and the above-mentioned development tools (Babel, PostCSS, webpack) to set the tone for a great development experience enabling professionals to create performant and powerful applications.

Basically, it enables developers to create three distinctive app types, depending on the intended purpose.


1. Static generated pages (or pre-rendering)

These applications need no API requests to fetch page content, meaning that most of the content is already included in the HML file itself. A good example of a static site is a product landing page or a portfolio website.


2. Single page application

Generally speaking most JavaScript frameworks (such as Emberjs, Vue, Angular, React for example) are single-page applications with content that's dramatically populated with fast transitions. Most of the single-page apps make good use of HTML5 history API or location Hash for routing purposes.


3. Server-side rendered apps or SSRs

The process of server-side rendering is a technique that developers use for fetching and displaying client-side data on the server to send a totally rendered “end product” (i.e. page) to the client.

Nuxt.js, SPAs, and SEO

Developers oftentimes tend to worry too much about the SEO of their single-page apps and their overall performance on search engines (think blogs, portfolios, landing pages, product websites on Google, for example). At the same time, developers also tend to worry about how complex the build of a server-side rendered app can or might be.

Development experts often build SPAs using JS frameworks, even though these single-page applications perform dynamic content populations on pages during loads. This means, when Google crawls the site in question, the cornerstone content of the site is still missing most of the time. This major flaw can be solved – partly – by pre-rendering the content. This is where server-side rendering and SSR apps come into the picture, and Vue developers can build such apps with Nuxt.js.

Your first Nuxt.js application

Generally, there are two trains of thought when you start building a Nuxt.js app.

You either use the scaffolding tool “create-nuxt-app.” or opt for starting from scratch. In this particular example, we will focus on the first method.

So, to get started, you should already have npx installed. Now, open your terminal and enter the command:

                    
    $ npx create-nuxt-app nuxt-tutorial-app
                    
                

Or, you can also go with:

                    
    $ yarn create nuxt-app nuxt-tutorial-app
                    
                

As you can see, we've named the projectnuxt-tutorial-app however, you can give your app any other name you might prefer.

Once you're done with this, it's time to look at our configuring options, to see what you might need for your development project.

Once you're done with that, just run the following command:

                    
    $ cd nuxt-tutorial-app
    $ npm run dev
                    
                

At this point, your app should be running on http://localhost:3000 and should be ready for development.





nuxt.js illustration

About the Nuxt folder structure

If you scaffold the application as we showed above, the framework creates different folders and files which you will use to get the work done. This might be a bit uncomfortable for newcomers to Nuxt.js and might throw them off balance a bit, so it's best to take a more thorough look at these folders and get to know them before we go any further.

Assets: this is your folder for un-compiled files such as your font tiles, images, JS files, LESS, and SASS. Create a styles folder and an accompanying main.css file and copy and paste the following:

                    
        a {
              text-decoration: none;
              color: inherit;
              cursor: pointer;
        }
        .header {
              width: 100%;
              max-width: 500px;
              margin-left: auto;
              margin-right: auto;
              height: 60px;
              top: 0;
              position: sticky;
              background-color: #fff;
              display: flex;
              justify-content: space-between;
              align-items: center;
        }
        .logo {
              width: 40%;
              max-width: 200px;
              height: 40px;
        }
        .logo .NuxtLogo {
              max-width: 30px;
              margin-left: 10px;
              max-height: 40px;
        }
        .nav {
              width: 60%;
              height: 40px;
              display: flex;
              justify-content: space-between;
              padding-right: 10px;
              max-width: 300px;
        }
        .nav__link {
              width: 80px;
              display: flex;
              align-items: center;
              border-radius: 4px;
              justify-content: center;
              height: 100%;
              border: 1px solid #00c58e;
              cursor: pointer;
        }
        .nav__link:active {
              background-color: #00c58e;
              border: 1px solid #00c58e;
              color: #fff;
              box-shadow: 5px 3px 5px 2px #3f41468c;
        }
        .home {
              padding-top: 30px;
        }
        .home__heading {
              text-align: center;
        }
        .directories {
              display: flex;
              box-sizing: border-box;
              padding: 10px;
              max-width: 1000px;
              margin: 0 auto;
              flex-wrap: wrap;
              justify-content: center;
        }
        @media (min-width: 768px) {
        .directories {
              justify-content: space-between;
        }
        }
        .directory__container {
              width: 100%;
              max-width: 220px;
              cursor: pointer;
              border-radius: 4px;
              border: 1px solid #00c58e;
              display: flex;
              height: 60px;
              margin: 10px 5px;
              margin-right: 0;
              justify-content: center;
              align-items: center;
        }
        .directory__name {
              text-align: center;
        }
        .directory {
              width: 100%;
              margin: 50px auto;
              max-width: 450px;
              border-radius: 4px;
              border: 1px solid #00c58e;
              box-sizing: border-box;
              padding: 10px 0;
        }
        .directory__info {
              padding-left: 10px;
              line-height: 22px;
              padding-right: 10px;
        }
                    
                

These will be the styles you will use across your example app. As you can see, there are several styles (for example, for navigation and other aspects) that will be plugged into the app, as the process progresses.

Components: all those developers who already worked with Vue.js this folder should be familiar since it contains reusable components which you can create here. And to get things off the ground, let's create your first one and name it, for example, navBar.vue. In our example we also want the navigation bar of the project to display the link to the about and home pages along with the site logo which will be added later on. We want to create a bar that will be visible across the entire application and will also incorporate some of the styles we've already discussed above:

                    
    <template>
        <header class="header">
            <div class="logo">
            <nuxt-link to="/">
            <Logo />
            </nuxt-link>
            </div>
            <nav class="nav">
            <div class="nav__link">
            <nuxt-link to="/">Home</nuxt-link>
            </div>
            <div class="nav__link">
            <nuxt-link to="/About">About</nuxt-link>
            </div>
            </nav>
        </header>
    </template>
    <script>
        import Logo from "@/components/Logo";
        export default {
                  name: "nav-bar",
                  components: {
                    Logo
                }
            };
    </script>
    <style>
    </style>
                    
                

What you see in the template section is what will the user see. As you can see, the logo is contained in the header element along with the nav links.

Layout: here's the place where you store application layouts. They can come especially handy if you find yourself building an app that needs at least two or more different layouts. For example, one for guests, one for admins, and one for authenticated users. So, to create different layouts, open the default.vue file while adding the navBar component to the layout.

                    
    <template>
        <div>
            <Nav />
            <nuxt />
        </div>
    </template>
    <script>
        import Nav from "~/components/navBar.vue";
        export default {
                  components: {
                    Nav
                  }
                };
    </script>
                    
                

As you can see, we also added the Nav component inside the container of the layout making sure it will always appear at the top after importing it in the specific file and declaring it. Following the Nav component is <nuxt />, which tells the framework where it should render all its routes.

Middleware: this is the folder responsible for housing JS files that are essential before rendering a page. It was created for files like Vue.js navigation guard.

Pages: another folder that Vue.js developers should already be familiar with. Every *.vue file in it is created as an application route enabling them to run both as routers and views at the same time.

Plugins: this is the folder where you store those files that should be running before mounting the Vue.js root application.

nuxt.config.js: This is the file you use to configure your app and is usually pre-populated based on the previous configuration you've done when creating the app. An ideal example of how such a file should like by default would be this:

                    
    export default {
      mode: 'universal',
      /*
      ** Headers of the page
      */
      head: {
        title: process.env.npm_package_name || '',
        meta: [
              { charset: 'utf-8' },
              { name: 'viewport', content: 'width=device-width, initial-scale=1' },
              { hid: 'description', name: 'description', content: process.env.npm_package_description || '' }
        ],
        link: [
              { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
        ]
      },
      /*
      ** Customize the progress-bar color
      */
          loading: { color: '#fff' },
      /*
      ** Global CSS
      */
          css: [
      ],
      /*
      ** Plugins to load before mounting the App
      */
          plugins: [
      ],
      /*
      ** Nuxt.js dev-modules
      */
          buildModules: [
      ],
      /*
      ** Nuxt.js modules
      */
          modules: [
      ],
      /*
      ** Build configuration
      */
          build: {
                /*
                ** You can extend webpack config here
                */
                extend (config, ctx) {
                }
      }
    }
                    
                

Each time you make a change to the file the app will restart to reflect said changes. As it can have a rather profound effect on your app, it's only smart to go over each of these properties to see what they mean.

Mode is the type of the app, which can be either SPA or universal. If you select the latter, you will be able to create an app that runs both client- and server-side.

You will have all your meta tags properties along with the favicon link in the Head tag.

Loading is your default Nuxt.js loader component.

Lastly, you also have css where you're expected to enter the link to your global CSS files to enable your app to take them into account when it mounts. Add the link to the css file and restart the app:

                    
    /*
    ** Global CSS
    */
        css: ["~/assets/styles/main.css"]
                    
                

Another one of the properties is Plugins. Here, you connect all the plugins in the folder for the app. It takes src objects that accept the file path to the plugin along with mode, which configures whether the app will treat said plugin as client- or server-side. Here's an example:

                    
    { src: '~/plugins/universal-plugin.js' }, // for server and client plugins
    { src: '~/plugins/client-side.js', mode: 'client' }, // for client only plugins
    { src: '~/plugins/server-side.js', mode: 'server' }, // for server side only plugins
                    
                

This is vital since you want to avoid any errors both on the client- and server-side, especially in cases where the plugin requires the localStorage command, which's not available server-side. If you are looking for more info about the nuxt.config.js file, you can always check out the official doc.

Routing system and pages

As already stated before, your pages folder is the one responsible for configuring your routes within your application. This means that your route name will depend on the name of the files in the folder. For example, if you happen to have an about.vue file in your pages folder, you will also have an /about route in your app. However, that's far from being all there is.


Basic routes

These are the routes that do not need any extra configuration for them to operate (think direct or contact routes). So, if you have something like this:

                    
    pages/
        --| me/
         -----| index.vue
         -----| about.vue
        --| work.vue
        --| contact.vue
        --| index.vue
        Nuxt will automatically create a router config such as this:
          routes: [
            {
              name: 'index',
              path: '/',
              component: 'pages/index.vue'
            },
            {
              name: 'work',
              path: '/work',
              component: 'pages/work'
            },
            {
              name: 'contact',
              path: '/contact',
              component: 'pages/contact'
            },
            {
              name: 'me',
              path: '/me',
              component: 'pages/me/index.vue'
            },
            {
              name: 'me-about',
              path: '/me/about',
              component: 'pages/me/about.vue'
            }
          ]
        }
                    
                

Now, these paths can be simply used to get to their tied components. There's no pages in the path, and Nuxt will handle the index.vue components as it should without any need for additional configuration.

Nested routes

If you wish to crate nested routes, you first need to add a new folder named “dashboard” within your “pages” folder and it should contain all the files you want to nest in it, like user.vue and setting.vue. To do this, just create a dashboard.vue file on the root of the pages.

                    
    pages/
         --| me/
         -----| index.vue
         -----| about.vue
         --| dashboard/
         -----| user.vue
         -----| settings.vue
         --| dashboard.vue
         --| work.vue
         --| contact.vue
         --| index.vue
                    
                

This action should automatically generate a router with the following routes:

                    
    router: {
          routes: [
            {
              name: 'index',
              path: '/',
              component: 'pages/index.vue'
            },
            {
              name: 'work',
              path: '/work',
              component: 'pages/work'
            },
            {
              name: 'contact',
              path: '/contact',
              component: 'pages/contact'
            },

            {
              name: 'me',
              path: '/me',
              component: 'pages/me/index.vue'
            },
            {
              name: 'me-about',
              path: '/me/about',
              component: 'pages/me/about.vue'
            },
            {
              name: 'dashboard',
              path: '/dashboard',
              component: 'pages/dashboard.vue',
              children: [
                {
                  name: 'dashboard-user',
                  path: '/dashboard/user',
                  component: 'pages/dashboard/user.vue'
                },
                {
                  name: 'dashboard-settings',
                  path: '/dashboard/settings',
                  component: 'pages/dashboard/settings.vue'
                }
              ]
            }
          ]
    }
                    
                

Dynamic routes

These are the routes that need to be defined by a variable in order to be referred to as “dynamic”. The variable can usually be a name, number or ID retrieved from client data. This can be really great when you need to work with an API where the ID (id) will most likely be the id of the item from the database.

If you are using Nuxt.js, you should know that dynamic routes are defined by appending an _ to the folder or the file name in your pages folder. When you want to create a dynamic route with the “id” variable name, just name your file accordingly, and the framework will automatically generate the route for you:

                    
    pages/
        --| me/
        -----| index.vue
        -----| about.vue
        -----| _routeName
        -------| index.vue
        -------| info.vue
        --| dashboard/
        -----| user.vue
        -----| settings.vue
        --| dashboard.vue
        --| work.vue
        --| _id.vue
        --| contact.vue
        --| index.vue
                    
                

This will also crate a router file with the following route structure automatically:

                    
        {
          name: 'work',
          path: '/work',
          component: 'pages/work'
        },
        {
          name: 'contact',
          path: '/contact',
          component: 'pages/contact'
        },
        {
          name: 'id',
          path: '/:id',
          component: 'pages/_id.vue'
        }
        {
          name: 'me',
          path: '/me',
          component: 'pages/me/index.vue'
        },
        {
          name: 'me-about',
          path: '/me/about',
          component: 'pages/me/about.vue'
        },
        {
          name: 'me-routeName',
          path: '/me/:routeName',
          component: 'pages/me/_routeName/index.vue'
        },
        {
          name: 'me-routeName-info',
          path: '/me/:routeName/info',
          component: 'pages/me/route.vue'
        },
        {
          name: 'dashboard',
          path: '/dashboard',
          component: 'pages/dashboard.vue',
          children: [
            {
              name: 'dashboard-user',
              path: '/dashboard/user',
              component: 'pages/dashboard/user.vue'
            },
            {
              name: 'dashboard-settings',
              path: '/dashboard/settings',
              component: 'pages/dashboard/settings.vue'
            }
          ]
        }
      ]
    }
                    
                

So, not that we've discussed how route structure works in Nuxt.js, it's time to add a page and a route (about.vue). Just add the following code to it:

                    
    <template>
<section class="home">
<h1 class="home__heading">About Nuxtjs Directory Structure</h1>
<div class="directories">
<div class="directory__container" v-for="directory in directories" :key="directory.id">
<p class="directory__name">
<nuxt-link
            :to="{ name: 'id', params: { id: directory.id, dir: directory } }"
>{{ directory.name }}</nuxt-link>
</p>
</div>
</div>
</section>
</template>
<script>
export default {
  name: "about-nuxt",
  data() {
    return {
      directories: [
        {
          id: 0,
          name: "The Assets Directory",
          info:
            "By default, Nuxt uses vue-loader, file-loader and url-loader webpack loaders for strong assets serving.
You can also use the static directory for static assets. This folder is for un-compiled files such as images, font files,
SASS, LESS or JavaScript files" }, { id: 1, name: "The Components Directory", info: "The components directory contains your Vue.js Components. You can’t use asyncData in these components." }, { id: 2, name: "The Layouts Directory", info: "The layouts directory includes your application layouts. Layouts are used to change the look and feel of
your page (for example by including a sidebar). Layouts are a great help when you want to change the look and feel of your
Nuxt.js app. Whether you want to include a sidebar or having distinct layouts for mobile and desktop" }, { id: 3, name: "The Middleware Directory", info: "The middleware directory contains your Application Middleware. Middleware lets you define custom functions
that can be run before rendering either a page or a group of pages (layouts)." }, { id: 4, name: "The Pages Directory", info: "The pages directory contains your Application Views and Routes. The framework reads all the .vue files inside
this directory and creates the application router. Every Page component is a Vue component but Nuxt.js adds special
attributes and functions to make the development of your universal application as easy as possible" }, { id: 5, name: "The Plugins Directory", info: "The plugins directory contains your Javascript plugins that you want to run before instantiating the root Vue.js
Application. This is the place to register components globally and to inject functions or constants. Nuxt.js
allows you to define JavaScript plugins to be run before instantiating the root Vue.js Application. This is especially
helpful when using your own libraries or external modules." }, { id: 6, name: "The Static Directory", info: "The static directory is directly mapped to the server root (/static/robots.txt is accessible under
http://localhost:3000/robots.txt) and contains files that likely won’t be changed (e.g. the favicon). If you don’t want to
use Webpack assets from the assets directory, you can create and use the static directory (in your project root folder)." }, { id: 7, name: "The Store Directory", info: "The store directory contains your Vuex Store files. The Vuex Store comes with Nuxt.js out of the box but
is disabled by default. Creating an index.js file in this directory enables the store. Using a store to manage the state is
important for every big application. That’s why Nuxt.js implements Vuex in its core." } ] }; } }; </script> <style> </style>

So, going from the script section, create an array stored in the directories variable. Every one of these arrays should contain an object with the three parameters (id, name, and, info). This is the data the user will see when opening the page, with clickable names.

How to pull that off?

In the template section with the v-for to loop the array. This also makes it possible to get each item in the array. In the loop, simply use the nuxt-link to handle linking and passing the details (id, name and info) to each directory through the Nuxt router.

Also, with creating a _id.vue file, the framework would generate an automatic dynamic route that would take the id parameter from the given link and display certain info about any directory your user would like to click on the about page:

                    
    <template>
        <section class="directory">
        <h1 class="directory__name">{{ directory.name }}</h1>
        <p class="directory__info">{{ directory.info }}</p>
        </section>
        </template>
        <script>
        export default {
          name: "directory-info",
          data() {
            return {
              directory: this.$route.params.dir
            };
          }
        };
        </script>
        <style>
        </style>
                    
                

In the above example, we've created a page that will fetch data from the route parameter dir using the this.$route.params, which gets the same info and the name of the clicked directory, displaying to the user.

There's only one problem with this: when you refresh the page, the directory info can get lost and you can receive an error. You need Vuex Store to fix this.

Using Vuex Store

You can use two modes to access Vuex in Nuxt:


  • Classic or deprecated mode
  • Modules mode

Modules mode

When you create your app, Nuxt.js automatically generates a Store folder for you, and in Modules mode, Nuxt will treat every single file inside this folder as a module, but you would also need to create an index.js to activate Vuex store in your app:

                    
    export const state = () => ({

    })

    export const getters = {

    }

    export const mutations = {

    }

    export const actions = {

    }
                    
                

As you can see, we've set up the store for the file with the things that we might need. The state is here for storing data, for extra manipulation to our state, we have getters, and finally, we also have actions for committing mutations.

With Nuxt, you can also separate each core concept and store it into different files. This means that you can have store.js, getters.js, mutation.js, and action.js separately making maintainability a lot easier. To fix the directory disappearing problem fixed, you need to use the store, but first, you need to install Vuex persistby using either of the below commands:

                    
    $ npm install --save vuex-persist
    $ yarn add vuex-persist
                    
                

Once you've installed it, create an accompanying vuex-persist.js file in the plugins folder and add the following code:

                    
    import VuexPersistence from 'vuex-persist'

        export default ({
          store
        }) => {
          window.onNuxtReady(() => {
            new VuexPersistence({
              storage: window.localStorage
            }).plugin(store);
        });
        }
                    
                

Now, import the plugin from node-modules and configure it so it will save the store in localStorage. This plugin lets you choose other storage options as well, like sessionStorage so if you need more info, you can use the official documentation to explore every option.

Don't forget to add it to the nuxt.config.js file:

                    
    /*
       ** Plugins to load before mounting the App
       */
      plugins: [{
        src: '~/plugins/vuex-persist',
        mode: 'client'
      }],
                    
                

As you can see, we added a file path to the plugin and told Nuxt.js to only run this plugin on the client-side of the app. Now, you can set up to store in order to accept and store directory info.

                    
    export const state = () => ({
          directory: ''
        })
        export const getters = {
        }
        export const mutations = {
          saveInfo(state, payload) {
            state.directory = payload.directory
          }
        }
        export const actions = {
        }
                    
                

Add a directory state to the along with a mutation function (saveInfo) that modifies the value of the directory state to the store in anticipation of the data you'll be passing:

                    
    <template>
        <section class="home">
        <h1 class="home__heading">About Nuxtjs Directory Structure</h1>
        <div class="directories">
        <div
                class="directory__container"
                v-for="directory in directories"
                :key="directory.id"
                @click.prevent="storeDirectoryInfo(directory)"
        >
        <p class="directory__name">
        <nuxt-link
                    :to="{ name: 'id', params: { id: directory.id, dir: directory } }"
        >{{ directory.name }}</nuxt-link>
        </p>
        </div>
        </div>
        </section>
    </template>
    <script>
        export default {
          name: "about-nuxt",
          data() {
            return {
              directories: [
                //remains the same
              ]
            };
          },
          methods: {
            storeDirectoryInfo(dir) {
              this.$store.commit("saveInfo", {
                directory: dir
              });
            }
          }
        };
    </script>
    <style>
    </style>

                    
                

Now, add a click event to each directory container that passes the directory info as an argument to the storeDirectoryInfo. In this function, you dedicate the directory object to your store.

Lastly, go back to your _id.vue file and simply replace the directory variable with the data from the store:

                    
    <template>
        <section class="directory" v-if="directory">
        <h1 class="directory__name">{{ directory.name }}</h1>
        <p class="directory__info">{{ directory.info }}</p>
        </section>
    </template>
    <script>
        import { mapState } from "vuex";
        export default {
          name: "directory-info",
          computed: {
            ...mapState(["directory"])
          }
        };
    </script>
    <style>
    </style>
                    
                

Now, refactor the code to use the directory object directory from the store by importing.

Here, we refactor our code to use the directory object directly from our store first by importing mapState from Vuex:

                    
    import { mapState } from 'vuex';
                    
                

And instead if checking if this.$route.params.dir is undefined first before accessing the stored data, you can simply use the store simply by reading that data that's in it.

                    
    <script>
        import { mapState } from "vuex";
        export default {
          name: "directory-info",
          computed: {
            ...mapState(["directory"])
          }
        };
    </script>
                    
                

Lastly, you update your template to make sure it won't render while your directory is undefined:

                    
    <template>
        <section class="directory" v-if="directory">
            <h1 class="directory__name">{{ directory.name }}</h1>
            <p class="directory__info">{{ directory.info }}</p>
        </section>
    </template>
                    
                

Now, not matter how many times you refresh the app, the directory object won't get lost and you can easily access it with the …mapState(['stateVariable'])method.

Using Heroku for deployment

Now, it's time to deploy your new app for production. In this example, we'll be deploying the app to Heroku with GitHub. If you've not set up your repository for your app yet, now would be a good idea. Once you're done with that, just open Heroku, create a new application, enter a name, and connect it to GitHub.

Now, all you have to do is add the following configuration variables.

                    
    NPM_CONFIG_PRODUCTION=false
    HOST=0.0.0.0
    NODE_ENV=production
                    
                

After this, create a Procfile in the root folder of the app, and enter the following command:

                    
    web: nuxt start
                    
                

This will make run the nuxt start command and will also command Heroku to direct all the external HTTP traffic toward it.

Reasons to use Nuxt.js

It's often said that Vue.js developers can make great use of Nuxt.js, however, Vue experts might also wonder why they would need another framework to use a framework. In this section, we will discuss all the pros that come with using Nuxt.

As a “higher-level” framework on top of Vue, it simplifies the development of single or universal page Vue apps by abstracting away the server and client code details enabling developers to focus on, well, development. It's a flexible project base that hosts a lot of features in a little package.


  • Ease of use – probably one of the strongest points of Nuxt.js is that makes universal app building a faster process altogether. As you may know, Vue.js and a lot of other modern JS frameworks focus on SPA development, because they can be used to create snappy user interfaces, but they can sometimes take a long time to load in some cases, and they can cause SEO-related headaches as well, as Google often struggles to crawl them properly as there's no initial content on the page but is generated later. A universal page is already preloading the app on the web server and sends the already rendered HTML whenever a browser request is being made speeding up load times and improving SEO in the process. So, Nuxt efficiently tackles this problem by making code sharing between the server and the client extremely simple.
  • Static rendering of Vue apps – also a huge innovation, the related command (nuxt generate) creates an entirely static version of your site generating the HTML for every route putting it into a dedicated file. For example, if you have two different pages (routes) Nuxt will automatically generate two different HTML folders for you. This enables you to reap similar benefits as you would do with universal apps, with the difference being that you don't really need the server anymore as everything gets generated in the development phase.
  • Automatic code splitting – generate static versions of your site with Nuxt by using a special Webpackconfig. Each statically generated route while get a dedicated JS file too along with just the needed code to run. This feature can help a great deal with improving speed and keeping the size of the JS files small.
  • Setup with the Starter Template via the Command Line – you have a starter template that provides all the scaffolding you need to get started with any project sporting a solid folder structure.
  • Great project structure right off the bat – by default, Nuxt.js gives you a neat app structure that gives you a solid base for organizing your app in an understandable way without things getting crowded and tangled up as they might sometimes get with small Vue apps. You get the directories that we've already talked about (layouts, pages, components, etc.) that all enable you to organize your app's structure neatly.
  • Easy route transitions – Nuxt creates your routes in a fashion that also ads a <transition> element to each page making the creation of transitions between them easy.
  • Easy-to-write single file components – if you've used components in Vue projects, you know that in small apps, they can work fine, however, the way they are defined can cause difficulties especially in the case of larger projects. You can address this problem by using single-file components together with a .vue extension, but first, you have to use Babel and Webpack to set up the build process. With Nuxt, this becomes a lot easier as it is pre-configured with Webpack meaning, you can use .vue files out of the box.
  • Fast ES6/ES7 compilation – apart from coming with Webpack, Nuxt also comes pre-packed with Babel for compiling the latest JS versions into formats that ensure they will be running on older browsers as well.
  • Auto-updating server for easy development – no need to use the change-refresh-change-refresh process anymore as Nuxt sets you up with an auto-updating dev. Server. Nuxt uses the Webpack configuration checking for changes and compiling everything. Just run the npm run dev command inside a project and it will set up the development server.
  • The community – the Nuxt Community GitHub collection is an awesome resource for modules, starter kits, libraries, and a lot more to ensure you're not starting from scratch.

Finishing thoughts and the place of Nuxt in the Vue Vs Nuxt debate

By just taking a closer look at this article, you can see that the Nuxt.js framework offers quite a handful of benefits for front-end development, but for some of the most established development teams, the SEO improvement was the feature that tipped the scale in favor of Nuxt.

However, when you want to compare the two frameworks, it's necessary to say that these two frameworks handle logic quite differently. Vue is always running on the client-side while Nuxt is not. And this fact can serve as a source of several problems in some specific cases. For example, If you want to select a DOM element after the app has loaded, there's a chance that the app is running on the Node.js side and there are no DOM elements there. You will have the same problem when accessing the local storage of a browser. With Vue, these aren't problems as they are running on the client-side.

Nuxt.js also managed to receive criticism from experts in the past, stating that it's not entirely ready for enterprise-scale apps as it had poor typescript support and less-than-ideal server-side error handling.

Taking all this into consideration, first-time Nuxt.js developers will probably be a bit confused during the development of their first-ever Nuxt project, especially if they transitioned from a Vue.js background. However, mastering any new framework has its own learning curve and when you do, you can truly understand to power and capability of the Nuxt.js framework.


So, Nuxt.js or Vue.js?

Experts well-versed in both frameworks usually point out that to answer this question one has to understand the strengths and weaknesses of each. This way, they can choose to use one over the other based on the particular project at hand.

Nuxt, in general, offers better SEO, faster development, public management and share features with outstanding config options, automatic code-splitting with pre-rendered pages, and great meta tag methods. Most of these features are impossible (or extremely demanding) to achieve with Vue. For projects that call for such features, Nuxt is the go-to option.

However, if you find yourself working on an internal product, with expanded code coverage and managing, with no need for SEO performance, or you need a traditional client-side SPA with manual code logic then Vue.js should be your choice.

Hello. How can we help you?

back btn

Order our service

This field is required
Web design Web development Web application Internet marketing Copywriting Graphic design This field is required
This field is required

back btn

Join us!

This field is required
UI/UX designer Community Manager Front-end Developer Back-end Developer Graphic Designer Copywriter SEO This field is required
Upload CV/Portfolio
This field is required

back btn

We are here for you.

This field is required
This field is required