Translator: Purification

The original link

Generic (also called isomorphic) JavaScript has become a common term in the JavaScript community. The generic JavaScript term is used to describe JavaScript code that can be executed on the client or server side.

Other articles by the author

  • Fetching Data from a Third-Party API with Vue.js and Axios

  • Quick Tip: How to Sort an Array of Objects in JavaScript

Many modern JavaScript frameworks, such as vue.js, aim to build single-page applications (spAs). The advantage of a single page APP is that it improves the user experience, making the web faster and smoother like an APP, even if updated. Although single-page applications have many advantages, the first screen rendering is slow due to multiple dependencies, and seo optimization is also a headache.

Server-side rendering means that the page is rendered on the server in advance, and when the browser requests the server, it returns the rendered HTML page.

Building server-side rendering JavaScript programs is somewhat boring and requires a lot of basic configuration before you can start coding. Thus, nuxt.js was created to solve the vue.js server rendering problem.

Summary Nuxt. Js

In short, nuxt.js is a framework that helps vue.js do server-side rendering easily. Nuxt.js presets various configurations required for server rendering, such as asynchronous data, middleware, and routing. It’s what Angular Universal is to Angular, next-js is to React.

As stated in the Nuxt.js documentation, nuxt.js lets developers focus on UI rendering of pages by abstracting the client/server infrastructure.

Static file generator

An important feature of nuxt.js is to generate static sites through the generate command. Similar to the popular static generation tool Jekyll.

Nuxt.js internal dependencies

In addition to vue.js 2.0, nuxt.js integrates the following modules: vue-Router, vuE-meta, and Vuex (introduced only when using the Vuex state tree configuration item). This has the advantage of eliminating the need to manually configure dependencies and the need to configure the same libraries on both the client and server sides. Nuxt.js still has a total size of 28KB min+gzip (31KB if Vuex is used) with the above dependencies.

In addition, Nuxt.js uses Webpack along with vue-Loader and Babel-Loader to handle automated build work of code (such as packaging, code layering, compression, and so on).

The working principle of

Here’s what happens when you visit a page built on nuxt.js:

  1. When the user accesses the application, if the nuxtServerInit Action is defined in the Store, nuxt.js will call it to update the store.

  2. Next, any middleware that you rely on to access the page will be loaded. Nuxt first loads the globally dependent middleware from the file nuxt.config.js, then detects the corresponding layout file for each corresponding page, and finally, detects the middleware that the sub-components of the layout file depend on. This is the loading order of middleware.

  3. Route verification is performed if the route to be accessed is a dynamic route with a corresponding validate() method for the route.

  4. After that, nuxt.js calls asyncData() and fetch() methods to load asynchronous data before rendering the page. The asyncData() method is used to fetch data asynchronously and render the data back to the page on the server. Fetch () fills the data into store before rendering the page.

  5. The last step is to render all the data to the page.

The following illustration illustrates how nuxt.js applies a complete server request to render.

Create a static web site using nuxt.js

Let’s create a simple static blog based on nuxt.js. Our sent request returns mock JSON data.

To complete the following examples, you need to know the basics of vue.js. If you’re a newbie, you can check out Jack Franklin’s Getting Started Guide for vue.js 2.0. At the same time, I will use the ES6 grammar, you can review ES6 grammar reference www.sitepoint.com/tag/es6/.

Our final Demo looks like this:

The code in this article can refer to GitHub, and the demo address is as follows.

Basic configuration

The easiest way to get started with Nuxt.js is to use the scaffolding developed by the Nuxt.js team itself. We can use vue-CLI to quickly create our project (SSR-blog) :

`vue init nuxt/starter ssr-blog`

Copy the code

Tip: If you have not installed vue-cli, please install vue-cli by NPM install -g vue-cli command first.

After that, we’ll install the project’s dependencies:

cd ssr-blog
npm install

Copy the code

Now we start the program:

`npm run dev`

Copy the code

If launched correctly, you can visit http://localhost:3000, showing the initial page of the nuxt.js template. You can also verify that everything displayed on the page is rendered by the server by looking at the page source code.

Here, we simply configure nuxt.config.js, including the following options:

// ./nuxt.config.js module.exports = { /* * Headers of the page */ head: { titleTemplate: '%s | Awesome JS SSR Blog', // ... link: [ // ... { rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/bulma/0.4.2/css/bulma.min.css'}}], / /... }Copy the code

In the configuration file above, we use the title variable of the titleTemplate field to specify the title of the article and fill the titleTemplate with the %s placeholder replaced by the title variable value before rendering.

At the same time, I also used the CSS framework, Bulma, to preset some styles. Configure items through link.

Nuxt.js uses vue-meta to update our HTML headers information. So, we can look at the meta specific configuration items, optimize the page HTML information.

Now, we can complete the page and functionality of the blog in a few steps.

The use of Layouts

First, we’ll define a common basic layout for all of our pages. Our main nuxt.js layout is updated by changing our layouts/default.vue file:

<! -- ./layouts/default.vue --> <template> <div> <! -- navigation --> <nav class=""nav has-shadow""> <div class=""container""> <div class=""nav-left""> <nuxt-link to=""/"" class=""nav-item""> Awesome JS SSR Blog! </nuxt-link> <nuxt-link active-class=""is-active"" to=""/"" class=""nav-item is-tab"" exact>Home</nuxt-link> <nuxt-link active-class=""is-active"" to=""/about"" class=""nav-item is-tab"" exact>About</nuxt-link> </div> </div> </nav> <! -- /navigation --> <! -- displays the page component --> <nuxt/> </div> </template>Copy the code

In our generic layout, we just add navigation bars to the page, and we further customize specific page modules with Components. You can check out [component-nuxt-link](nuxtjs.org/api/compone… Learn more.

Component is very important when creating a layout. It determines what elements to display on a specific page.

Of course, Component can do a lot more, such as defining generic components and error pages, but our blog is simple and doesn’t need that functionality. We strongly recommend reading Nuxt.js documentation on Views, you can learn more about nuxt.js features in this article.

Simple pages and routing

The nuxt.js page organizes the directory structure as a single file component. Nuxt.js automatically finds every.vue file in the directory and adds it to the page.

Create a Blog homepage

We can modify the home page by modifying the index.vue file, which is created with nuxt.js as follows:

<! -- ./pages/index.vue --> <template> <div> <section class=""hero is-medium is-primary is-bold""> <div class=""hero-body""> <div class=""container""> <h1 class=""title""> Welcome to the JavaScript SSR Blog. </h1> <h2 class=""subtitle""> Hope you find something you like. </h2> </div> </div> </section> </div> </template> <script> export default { head: { title: 'Home' } } </script>Copy the code

As mentioned earlier, the topic is automatically populated into the file before rendering.

We can now refresh the page to see the changes to the home page.

Create the About page

Nuxt.js also has an excellent feature that listens for changes to files in folders, so you don’t need to restart to apply the update when the file changes.

Let’s add a simple about. Vue page:

<! -- ./pages/about.vue --> <template> <div class=""main-content""> <div class=""container""> <h2 class=""title is-2"">About this website.</h2> <p>Curabitur accumsan turpis pharetra <strong>augue tincidunt</strong> blandit. Quisque condimentum maximus mi, sit amet commodo arcu rutrum id. Proin pretium urna vel cursus venenatis. Suspendisse potenti. Etiam mattis sem rhoncus lacus dapibus facilisis. Donec at dignissim dui. Ut et neque nisl.</p> <br> <h4 class=""title is-4"">What we hope to achieve:</h4> <ul> <li>In fermentum leo eu lectus mollis, quis dictum mi aliquet.</li> <li>Morbi eu nulla lobortis, lobortis est in, fringilla felis.</li> <li>Aliquam nec felis in sapien venenatis viverra fermentum nec lectus.</li> <li>Ut non enim metus.</li> </ul> </div> </div> </template> <script> export default { head: { title: 'About' } } </script>Copy the code

Now we visit http://localhost:3000/about to see the about page, without having to restart, is very convenient.

Display a list of articles on the home page

Our home page is displayed without content, so next we’ll add the blog list component to index.vue.

First, we need to save the JSON-formatted article in the service root. The file can be downloaded from here, or you can copy the following JSON to the root folder posts.json:

[ { ""id"": 4, ""title"": ""Building universal JS apps with Nuxt.js"", ""summary"": ""Get introduced to Nuxt.js, and build great SSR Apps with Vue.js."", ""content"": ""<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>"", ""author"": ""Jane Doe"", ""published"": ""08:00 - 07/06/2017"" }, { ""id"": 3, ""title"": ""Great SSR Use cases"", ""summary"": ""See simple and rich server rendered JavaScript apps."", ""content"": ""<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>"", ""author"": ""Jane Doe"", ""published"": ""17:00 - 06/06/2017"" }, { ""id"": 2, ""title"": ""SSR in Vue.js"", ""summary"": ""Learn about SSR in Vue.js, and where Nuxt.js can make it all faster."", ""content"": ""<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur  sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>"", ""author"": ""Jane Doe"", ""published"": ""13:00 - 06/06/2017"" }, { ""id"": 1, ""title"": ""Introduction to SSR"", ""summary"": ""Learn about SSR in JavaScript and how it can be super cool."", ""content"": ""<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor. Excepteur sint  occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>"", ""author"": ""John Doe"", ""published"": ""11:00 - 06/06/2017"" } ]Copy the code

Tip: Ideally, we should get the article data from the API. Contentful, for example, is a CMS backend service.

Components are stored in the Components folder. We can create the following components:

<! -- ./components/Posts.vue --> <template> <section class=""main-content""> <div class=""container""> <h1 class=""title has-text-centered""> Recent Posts. </h1> <div class=""columns is-multiline""> <div class=""column is-half"" v-for=""post  in posts""> <div class=""card""> <header class=""card-header""> <p class=""card-header-title""> {{ post.title }} </p> </header> <div class=""card-content""> <div class=""content""> {{ post.summary }} <br> <small> by <strong>{{ post.author}}</strong> \\ {{ post.published }} </small> </div> </div> <footer class=""card-footer""> <nuxt-link :to=""`/post/${post.id}`"" class=""card-footer-item""> Read More </nuxt-link> </footer> </div> </div> </div> </div> </section> </template> <script> import posts from '~/posts.json' export default { name: 'posts', data () { return { posts } } } </script>Copy the code

We introduced JSON files to act as asynchronous data, looped through the list with the V-for instruction, and fetched the properties we needed to populate the component template display.

Tip: the ~ symbol is an alias for /. You can check out this documentation for more details.

Next, we add component to the home page:

<!-- ./pages/index.vue -->
<template>
<div>
    <!-- ... -->
    <posts />
</div>
</template>

<script>
import Posts from '~components/Posts.vue'

export default {
  components: {
    Posts
  },
  // ...
}
</script>

Copy the code

Adding a Dynamic Route

Now let’s configure dynamic routing for the article page, using /post/1 as an example:

To do this, we add the POST folder to the Pages directory as follows:

├ ─ 07.088 (1Copy the code

Our program generates the corresponding dynamic route:

router: {
  routes: [
    // ...
    {
      name: 'post-id',
      path: '/post/:id',
      component: 'pages/post/_id/index.vue'
    }
  ]
}

Copy the code

Update single release file:

<! -- ./pages/post/_id/index.vue --> <template> <div class=""main-content""> <div class=""container""> <h2 class=""title is-2"">{{ post.title }}</h2> <div v-html=""post.content""></div> <br> <h4 class=""title is-5 is-marginless"">by <strong>{{ post.author }}</strong> at <strong>{{ post.published }}</strong></h4> </div> </div> </template> <script> // import posts saved JSON data import posts from '~/posts.json' export default { validate ({ params }) { return /^\d+$/.test(params.id) }, asyncData ({ params }, callback) { let post = posts.find(post => post.id === parseInt(params.id)) if (post) { callback(null, { post }) } else { callback({ statusCode: 404, message: 'Post not found' }) } }, head () { return { title: this.post.title, meta: [ { hid: 'description', name: 'description', content: this.post.summary } ] } } } </script>Copy the code

Nuxt.js simplifies the development process by adding common methods. Let’s see how we can use it in a single file application.

  • Route verification The route verification method validate can be used to verify routes. If our validation route parameter validates the number, if the validation fails, it will automatically redirect to the 404 page. If it returns “false”,Nuxt. Js will automatically load the 404 error page. For more, check out this document.

  • The asyncData method is used to fetch data and render the page on the server and return it to the browser. It can return data in a number of ways. We can return data in a number of ways. In the example in this article, we use a callback function to return to the page. We use a callback function to return the route of the same post “ID” attribute “ID” parameter. You can see different ways to use this function (here)(nuxtjs.org/guide/async…

  • As we saw earlier, we use the head method to set the page header. At this point, we change the title of the page and add the page information to the specific page.

Now we can visit our blog again to see all the lines and pages working properly, and view the HTML generated by the page source code. We have a server-side JavaScript application rendering capability.

Generating static files

Next, we’ll generate an HTML static file for the program.

We need to make a small change to nuxt.js, which ignores dynamic routing by default. To generate the dynamic routing file, we need to modify./nuxt.config.js.

We use the callback function to return the list of future dynamic routes:

// ./nuxt.config.js

module.exports = {
  // ...
  generate: {
    routes(callback) {
      const posts = require('./posts.json')
      let routes = posts.map(post => `/post/${post.id}`)
      callback(null, routes)
    }
  }
}

Copy the code

If you want to see the full configuration of Generate, refer to this document.

Run the following command to generate all pages:

`npm run generate`

Copy the code

Nuxt places all generated pages in the dist folder.

Deploy using Firebase Hosting

As a final step, we recommend using Firebase Hosting to deploy your project so that users can visit our website in seconds.

If you haven’t used Firebase before, install the Firebase CLI first:

`npm install -g firebase-tools`

Copy the code

Next, we initialize the site, specifying the dist folder as a public directory, and when prompted:

`firebase init`

Copy the code

We can use the following command to deploy:

`firebase deploy`

Copy the code

This way, we can visit.firebaseapp.com to view our web page. For the official Demo, visit nuxt-ssR-blog.firebaseapp.com/.

Conclusion

conclusion

In this article, you learned how to build server-side rendered JavaScript applications using nuxt.js with vue.js. We also learned how to use its generate command to generate a static file for our page, and we can deploy it using a static Hosting tool like Firebase Hosting.

The nuxt. js framework is so excellent that it has become the official recommended SSR framework of vue.js. I expect nuxt.js to be used in more SSR projects, using more nuxt.js features.

What do you think of vue.js SSR framework nuxt.js, and what do you think of generic JavaScrpt technology? Leave it in the comments section.