Understanding the NUXT framework:

1) Start from the background

With the popularity of the Internet in various fields and industries, major industries are striving for more exposure of their own brands or products, SEO has become a rigorous problem that the front-end field must consider.

With the popularization of SPA architecture, the disadvantages of SPA are gradually highlighted. SPA(single page) architecture is known for its drawbacks, such as search engine optimization and slow first screen.

At this point, each major framework, are considering their own “server rendering” scheme. So, after React launched Next, Vue launched nuxT.

The first time I saw the professional name “NUxT” was from the “server rendering” guide on the VUE website:


So what is NUXT? Take a look at how baidu’s search engine introduces nuxT:

Nuxt.js is a lightweight application framework based on Vue. It can be used to create server-side rendering (SSR) applications, and can also act as a static site engine to generate static site applications, with elegant code structure layering and hot loading features.

In simple terms, it is based on the existing common application framework (such as Vue or React), through the abstract organization of the client/server infrastructure, the application UI rendering.

2) Start from the official website

Let’s learn more from nuxT’s official website:

Ok, English is a little confused, translate:

Finally, the Chinese version can understand a little, describe personal understanding:

* 1) Nuxt comes with modules.

How do you understand modules here? It will be introduced below the article. There’s a little bit of a discrepancy here with the conventional front-end understanding. For a normal front end, you only need to think about the client. Nuxt is, after all, a server-side framework, so there are some methods that must consider the client side, as well as the server side. Such as web requests, such as style generation. So modules are created to address the commonality between two clients.

Currently the official modules provide 100+ modules, we can also customize modules for development.Copy the code

* 2) High-performance

From the simple text of the introduction, is to make use of vue. js and Node.js advantages of both good and efficient performance.

* 3) pleasant

Why Is NUxT enjoyable? In my opinion, vue developers switch to NUxT, since most development is similar to VUe-CLI, we just need to learn the differences. You don’t need to expend too much energy to relearn. Learn a few nuXT features and you’ll be “happy” to develop right out of the box.

3) Start from the source code

At this point, we should know a little bit about what NUXT is. But what exactly does it consist of?

Let’s continue to understand nuxT from a source code point of view:


Source code analysis, limited ability, if there is a description of the wrong point out


First, from the node_modules/nuxt/ directory, we can simply see that the nuxt body, the scaffolding points to @nuxt/cli, and the packaging process points to @nuxt/ Builder:

Node_modules /@nuxt: node_modules/@nuxt:

From the catalogue we can simply guess:

  • The entire collaborative process is in the CLI directory
  • Webpack and Core directories, you can guess about the compilation process.
  • Nuxt package code generation process, mainly in cli, Builder, generator and other directories.
  • It also matches some common methods, such as Components,utils, etc.
  • The front-end module is mainly in VUE-APP.
  • The server module is mainly in the server.

We can verify whether the guess server and client are correct according to @nuxt/ CLI.

Check out the @nuxt/ Builder code:

The whole packaging process is shown in the code above, where the text of the Vue code is obtained, which the author locates in the template, which is from vueApp. Const vueApp = require(‘@nuxt/vue-app’); . As we can see, the client-side code mainly comes from vue-app. Let’s move on and see what vue-app is. Let’s look at vue-app source code:

Json, we can see that the client uses the usual vue + VUe-Router + vuex + VUe-template-compiler + other toolkits. This is basically the same as vue-CLI 3.0. Of course, intermediate routing and so on, nuXT handles its secondary encapsulation, including adjustments to directory methods and so on. This proves why most of the code is the same as vue-CLI 3.0.

Continue to trace the server (@nuxt/server) :

Combined with:

const connect = require('connect');
const connect__default = /*#__PURE__*/_interopDefaultLegacy(connect);
Copy the code

From there, we can trace that the Nuxt server uses the Connect framework (and, presumably, the NuxT-KOA version), combined with nuxtMiddleware, renderAndGetWindow, etc., to form the Nuxt server.

Let’s take a look at how the page is rendered, i.e. how the server renders HTML to the client:

It can be analyzed from the screenshot above:

this.renderer = new vueRenderer.VueRenderer(this.serverContext);

It is rendered in vueRenderer to the corresponding instance while the Connect life cycle is still ready. So what is the vueRenderer? Let’s move on:

const vueRenderer = require(‘@nuxt/vue-renderer’);

And from that, we can analyze that actuallyNuxt server rendering is the use of vue-server-renderer package, rendering to the corresponding instance.

Vue-server-renderer, I believe some of you have been exposed to it. If you want to use VUE to write their own SSR will basically use it.

Can check the website: ssr.vuejs.org/guide/struc…

The legend on the official website can help us understand it well:

Vue-server-renderer will identify our original SPA architecture app.js, and distinguish the corresponding content from client or server according to life cycle, etc. Through Webpack, Generate server.bundle.js and client.bundkle.js respectively.

At this point, if the browser visits, first go to the Node layer, execute server.bundle.js, and then generate the corresponding HTML output to the browser. At this point, continue to execute client.bundle.js to execute the corresponding client code.

At this point, we can look at nuxT’s client composition, server composition, and how the server is rendered to the client.

Nuxt framework analysis

Knowing that nuXT is above, let’s continue to analyze the characteristics of NUXT.

This chapter is mainly compared with VUE-CLI 3.0 as a reference.

1) Menu/directory structure

The directory structure is similar to vuE-CLI 3.0, with one in the root directory and one in the SRC secondary directory.

Because NUXT requires two clients to be considered, the directory structure is more similar to a server-side framework such as KOA or Express.

Here are two examples of new projects:

Here are some common similarities and differences:


The name of the vue-cli nuxt
page src/views pages 
component src/components components 
vuex src/store       store 
Static resource src/static      static 
Common methods src/${js}       plugins 
routing SRC /${custom} /              
layout / layout 
The middle layer /               middleware 
The configuration file vue.config.js   nuxt.config.js 

2) context

Take a look at the context on the website:

Context provides additional objects/PARAMS from Nuxt to Vue’s corporate components and provides areas like asyncData, FETCH, plugins, Middleware, and nuxtServerInit in the particular Nuxt lifecycle.

From the official website: nuxtjs.org/docs/intern…

So this extra object, what information comes with it? What does it do?

Nuxt needs to consider both the server and the client, so the original method of embedding the front-end into the JS prototype instance is no longer applicable. The server needs to consider the problem of data transmission with the client. Context objects provided by NUXT quickly help the server to obtain corresponding data, such as App, Store, Router, env, etc., to achieve the purpose of data communication between the two clients.

Refer to the above links for all the objects provided. Including app, Store, route, Params, Query, env, isDev, isHMR, etc.

Store, Route, Params, Query, etc.

Contains root Vue instance options for all plug-ins. For example, when using i18n, you can access $i18n via context.app.i18n.

This is the same as this on the client side. To get the Vue instance on the SPA page, just use this object. On the server side, you need to use the APP provided by NUXT to obtain the corresponding instance.

App here is not the same as this on the page. It is available only after a specific lifecycle declaration. If you need to inject early, use the plugins mechanism to inject early.

3) layout/layout

Layout can be a bit confusing for someone new to NuxT, since vuE-CLI doesn’t have one.

It’s actually pretty easy to understand. Vue-cli supports nesting of child and parent routes, and nuxT layout can be easily understood as vue-CLI’s outermost nesting. Because nuXT routes are automatically generated.

Nuxt introduces Layout, which allows you to configure Layout :layoutName on the corresponding page to achieve quick nesting. It’s very convenient.

www.nuxtjs.cn/guide/views…

With the help of the view Layout image from the official website, we can see that the HTML Page is the outermost layer, followed by the Layout, which is embedded in our Page Page.

Mention HTML, NUXT also supports the layout of the outer HTML editor, may refer to: www.nuxtjs.cn/guide/views…

4) Router/router

Vue-cli and NUXT routing, both in principle and practice, is quite different. After all, one is a server-side route and the other is a pure front-end route.


Router Difference 1: Different names

Here only the name is inconsistent, the usage is the same, no longer described.

2) <router-view /> Switch to <nuxt />Copy the code

Router Difference 2: Automatically generated

First, nuxT routes can be automatically generated, which is somewhat different from traditional VUE-CLI.

Of course, you can also use nuxt.config.js to customize:

router: { extendRoutes(routes, resolve) { routes.push({ name: 'test-jia', path: '/test/jia', component: path.resolve(__dirname, '.. /pages/test/jia.vue'), }) } }Copy the code

Of course, if you also want to take over the overall support:

      router: {
        extendRoutes(routes, resolve) {
           return [{
            name: 'test-jia',
            path: '/test/jia',
            component: path.resolve(__dirname, '../pages/test/jia.vue'),
          }]
        }
      }
Copy the code

Router difference 3: Routing hooks

Nuxt routing is more complex than VUE-CLI. Nuxt requires plugin or middleware to guard routes globally. May refer to:

    plugins: [
        { src: '@/plugins/router.js', ssr: false}
    ],

    export default ({ app, store, $axios }) => {
        app.router.beforeEach((to, from, next) => {
            next()
        })
    }
Copy the code

Router differences 4: Different principles and properties

One is “front-end routing” and the other is “back-end routing”. The principles of the two are different. You can search for the difference between Front-end Route and Back-end Route.

Here is a brief description of the characteristics of both:

Back-end routing:

Personal understanding: more like a page-level application, each page exists independently.

  • 1. Share the burden of the browser, HTML and data stitching is done by the server.
  • Support SEO.
  • 3. A blank screen is more likely to appear when the page is large.
  • 4. In this mode, the front and back ends are not separated.
  • 5. Comply with the browser’s forward and backward mechanism standards, can effectively use the cache.

Front-end routing:

More like an application-level program that can be loaded and run independently of the browser.

  • 1. There is no server pressure (except bandwidth), and all loading execution is performed on the client.
  • 2. No SEO support
  • 3. Relatively good user experience
  • 4. The forward and backward mechanisms of the browser are reexecuted to reduce cache usage.
  • 5. The rolling position cannot be recorded.

Router difference 5: Different listening modes

Global listening:

Vue-cli has its own route hook function, but NUxt did not find the official route hook function. Plugins are required to complete global hooks.

Find a finished product case: www.zhaima.tech/post/nuxt.j…

Page listening:

Vue-cli page listening, directly watch the router page can be. Nuxt can’t be done with watch. Nuxt has its own watchQuery that listens for route parameter changes.

It’s worth noting that WatchQuery has a big caveat that it needs to return before it can actually do this. Second, the WatchQuery’s this object will change if plugin injection is used.


5) AXIos/network request

At this time, the network request needs to consider two clients, so the original AXIOS needs to be processed and compatible on the server side.

The good news is that @nuxtjs/axios is officially available, and we only need to use it on modules configuration.

    modules: [ "@nuxtjs/axios"]
Copy the code

At this point, Axios may also have a problem in that it needs to initiate a request from an instance, but at this point you don’t have one. To do this, use plugins:

    export default function(context, inject) {
        context.$axios.onRequest((config) => {
            ...
        });
    }
Copy the code

6) Plugins/plugins

In a traditional SPA page, the order of execution is to generate the instance first, and then execute the corresponding JS. If you want to obtain the corresponding instance, it is very simple to directly js, or import vue form ‘vue’ into the interface.

However, in SSR, the server and client cannot use the same instance at the same time. After all, there are still differences between server and client.

This would be a pain point if we wrote our own SSR framework. Nuxt took care of that for us and introduced plugins. So that in the server life cycle, also can obtain the corresponding instance.

Plugins are JavaScript plug-ins that need to be run before the root vue.js application can be instantiated

It is worth noting that SSR: false will be used in asyncData when plugins are configured.

Or mode: ‘client’ | | ‘server’ control terminal.

7) Middleware/middle layer

Simple understanding: The middleware that houses the application

This is a concept that many Node users have, whether it’s KOA or Express, who have their own middleware mechanism. Middleware is used to give preference to the middle layer before entering a page or method (as discussed in the lifecycle below). If the conditions are not met, an intermediate method is used to control what to do.

It’s kind of like our “routing hook function”. But the front-end “routing hook function” loads the page already entered, while NUxT, while still on the server, interrupts.

The most typical scenarios include authentication, terminal judgment, and buried points.

In addition, the middleware in NUxT can be divided into global and layout middleware, layout anonymous Middleware, page anonymous Middleware, and page anonymous Middleware.

They are executed in the following order: Global (config) > Layout > Page (Page)

middleware/auth.js:

export default function ({ store, redirect }) { // If the user is not authenticated if (! store.state.authenticated) { return redirect('/login') } }Copy the code
  • Global case:

nuxt.config.js:

module.exports = {
    router: { middleware: ['auth'] }
}
Copy the code
  • Page real name case:
Export default {middleware: "auth"}Copy the code
  • Page anonymous case:
export default { middleware({ store, redirect }) { // If the user is not authenticated if (! store.state.authenticated) { return redirect('/login') } } }Copy the code

Reference: www.nuxtjs.cn/guide/routi…

8) modules/modules

Modules are featured on the official website above, as well as the advantages of being featured. Currently the official display is provided within 100+ modules.

What is a module? Modules are nuxt.js extensions that extend its core functionality and add unlimited integration. Modules are simply functions that are called sequentially when booting Nuxt. The framework waits for each module to complete before loading.

If plugins are the solution to our post-compile needs, modules is the solution to our pre-compile needs. For example, before starting a project, you want your project to support typescript, support proxy, support ESLint, etc.

In the past, you could refer to the need to consider how the client will introduce them. In an SEO framework, you need to think about how both the server and the client can introduce them and be compatible, and this process can be very complicated. Just the passing of this instance is enough for us to mess with.

Nuxtjs official Modules package each commonly used module, convenient for developers to use. We just need to configure and use them at development time. As it says on the official website: the module list directory contains JavaScript plug-ins to run before instantiating the root vue.js application. This is where you add Vue plug-ins and inject functions or constants. Each time you need to use it, you should create a file in AND add its path to IN to enhance your Nuxt project

Take a look at the official version of the typical module: Modules.nuxtjs.org/

Of course, NuxtJS modules can not only be used officially. We also allow customization during development and can even publish to NPM on the official website.

In this tutorial: zh.nuxtjs.org/docs/2.x/di…

9) Cookie/store

Common front-end storage methods, localStorage, sessionStorage, cookies, indexedDB, etc. But in nuxTJS, we’re not just thinking about the front-end browser. SessionStorage and localStorage, etc., his storage location, is browser. Therefore, unless currently cached, confirm that only the client is using, if once the server is using, the program will not be able to identify the corresponding store, the program will execute an exception.

In the practice of the framework, a lot of data needs to be shared between the server and the client, a typical case is the user token. Cookies seem to be the best solution right now.

  • Cookie-universal-nuxt can be used

      npm i --save cookie-universal-nuxt
    
      nuxt.config.js
      {
         modules: ['cookie-universal-nuxt']
      }
      
      app.$cookies.get('token')
      
    Copy the code

    In this scenario, cookies will be embedded in our this or app object. For reference: blog.csdn.net/weixin_3618…

  • Js-cookie can also be used

      npm i --save js-cookie
    
      import Cookies from 'js-cookie'
      Cookies.get('token');
    Copy the code

    In this scheme, using cookies requires manual introduction of cookies.

10) Proxy/cross-domain

Nuxt proxy is similar to vuE-CLI. You can configure the domain name of the proxy in the configuration file. It’s just that proxies need to think about server-side proxies.

The official has helped us to provide the module @nuxtjs/proxy, we can directly configure.

Modules: [" @ nuxtjs/proxy "]. proxy: { '/api/': { target: 'http://*********/', pathRewrite: { '^/api/': '' } }Copy the code

11) Content/content

This module is part of an extension of NuxtJS. This part is familiar to those who have been in contact with Vue Press.

How to quickly support Markdown, CSV, YAML, JSON(5), XML and other standard formats, content helps us encapsulate fast integration. We just need a quick introduction.

First, we introduce the corresponding content module in nuxt.config.js, and install the corresponding module first:

npm install @nuxt/content --save
Copy the code

Modify nuxt. Config. Js:

export default {
   modules: [ "@nuxt/content"],
}
Copy the code

At this point we can use the content functionality to complete the server rendering of the extension type, let’s take a typical MD file as an example.

Create a new file /content/ helloword.md:

This is an MD file. The MD file has been parsed successfullyCopy the code

At this point, we can quickly introduce the page in:

 <nuxt-content :document="doc" />

 async asyncData({ $content, params }) {
    const doc = await $content('helloWord').fetch();
    return {
      doc
    };
  },
Copy the code

At this point, the standard MD file display can be displayed:

It is worth mentioning that the official here also supports the function of obtaining the folder traversal file, and also supports the function of obtaining the internal properties of the file, such as obtaining the secondary title of the MD file.

It is also worth mentioning that obtaining files can be done via asyncData with fetch cycles. This distinction is introduced later in the life cycle.

Special note: it has been found in practice that the development mode is not automatically updated after the file is parsed. If hot update is required, special treatment is required.

12) Life/life cycle

Nuxt’s life cycle is a bit more complicated than vue SPA. Let’s take a look at the legend on the official website (link: nuxtjs.org/docs/concep…

Nuxtjs.org/docs/2.x/co…

Let’s look at the process on the server side:

Take a look at the process the client executes:

The specific execution process, I believe that the official screenshots have been very clear. Here are some important lifecycle explanations.

13) nuxtServerInit/Initialize store

Take a look at the explanation from the official website:

If nuxtServerInit defines an action in a Store and mode is universal, Nuxt calls it with context (only from the server side). This is useful when we have some data on the server that we want to feed directly to the client.

For example, suppose we have a session on the server side, we can access the connection through the user req.session.user. To add an authenticated user to our store, we update our store/index.js with the following.

From: nuxtjs.org/docs/direct…

The nuxT framework needs to fetch data from the server during initialization. In this case, the nuxtServerInit function can be used to assign values. As you can see from the lifecycle diagram above, nuxtServerInit is the first step of initialization.

For example, check whether the token takes effect on the server during page loading. For example, obtain user information in real time before the page is loaded. Wait, this is where nuxTServerInit comes in handy.

14) Created & with beforeCreated/page initialization

Created and beforeCreated, the two life cycles seem familiar, but are different from vue-CLI.

As you can see from the diagram above, this life cycle belongs to both the client and the server. What’s the difference here?

Let’s take a look at Experiment 1:

<template> <div> {{name}} </div> </template> <script> export default { name: "homeIndex", data() { return{ name: }}, created(){this.name = "this.name "; }}; </script>Copy the code

The page must display the name “xiaogang”, we check the render result:

This is the HTML returned that has been rendered. Now look at Experiment 2(with setTimeout added) :

<template> <div> {{name}} </div> </template> <script> export default { name: "homeIndex", data() { return{ name: "Xiao Ming,"}}, created () {setTimeout (() = > {enclosing name = "xiao gang"; }}}, 400); </script>Copy the code

At this point, the page display result is Xiaogang, but the HTML rendering result is Xiaoming.

Other macro tasks and micro tasks are not tested here. We can come to the conclusion that only synchronous code can achieve SEO effects by assigning values in the Created cycle. If asynchronous tasks are needed, Created cannot meet the requirements of rendering.

15) asyncData/server request

Created does not achieve SEO effect for asynchronous tasks. So if you need SEO rendering, how to deal with it? That’s why asyncData exists.

Take a look at the official website:

You may want to fetch and render data on the server side. Nuxt.js adds asyncData methods that allow you to retrieve data asynchronously before rendering components.


Thus, asyncData is almost a key lifecycle for NUXT server rendering. This life cycle belongs to the server, that is, before entering the client, the data display is requested and the HTML is stitched together and returned to the client.

Because it’s server-side rendering, we also need to be careful that we can’t get things that are client-side, like Window, document. Other objects, such as store, this, etc., also need to interact with the context described above.

There is also a big hole here, asyncData is only executed on the first screen, otherwise it is equivalent to creating or mounted on the client side to render the page.

In other words, asyncData can only be initialized on the first screen when the url is entered from the browser or the link is refreshed. If it is a jump to the current page, it is only client-loaded, not rendered.

AsyncData is a page-level life cycle and does not support component level.

16) Fetch/asynchronously fetch store

  • Introduction to the official website:

The FETCH method is used to populate the application’s store data before rendering the page, similar to the asyncData method except that it does not set the component’s data.

AsyncData can literally populate the page data, while a store needs to be populated by the fetch function. In fact, asyncData also supports store changes.

Note in particular that fetch is asynchronous.

Note in particular that asyncData is at the page level and FETCH is at the component level

What does that mean? Let’s take a look at the following test cases:

Create a new page index.vue:

<template> <div> <h-child></h-child> <h-child></h-child> </div> </template> <script> import hChild from "./components/child.vue"; export default { components: { hChild }, asyncData(){ console.log(`page.asyncData============`); }, fetch(){ console.log(`page.fetch============`); }}; </script>Copy the code

Create a new component /components/child.vue:

<script> export default { name: "homeIndex", data() { return{ name: "Xiao Ming,"}}, asyncData () {the console. The log (child. ` asyncData = = = = = = = = = = = = `); }, fetch(){ console.log(`child.fetch============`); }}; </script>Copy the code

At this point, look at the printed result of the page:

We can conclude from the above that asyncData only works on the page, while FETCH works on all components.

Reference: qa.1r1g.com/sf/ask/3447…

17) validate/verify

Take a look at the explanation from the official website:

Validate is called every time you navigate to a new route. It will be called once on the server side (on the first request to the Nuxt application) and when the client navigates to more routes. This method takes the context object as an argument.

The individual can be simply interpreted as intercepting the route hook function. We can verify routing parameters and so on here.

For example, the product details link must have an ID:

export default { validate({ query }) { return query.id; }}Copy the code

Nuxt slot point

Here is a list of the author in the actual process, encountered can ridicule a few points. Welcome to share solutions. Also welcome to add slot points.

1) Poor server rendering compatibility

Code requirements are higher. When the wrong code is executed, a traditional front-end framework simply throws an exception and cannot execute the logic below, and the page is not even affected. The server framework, if not handled well, will have the dreaded 500 pages etc.

2) Unable to obtain browser information

Traditional SPA projects can obtain real-time browser information because the requests are all on the client side. However, in NUXT, if the request comes from the server, there is no corresponding information.

3) Limitation of debugging window

Development practices have concluded that nuXT supports debugging of up to three Windows. When the fourth page is opened, the screen will remain blank.

4) High debugging delay

I wonder if there are any friends encountered, the same code in nuxt and VUe-CLI, the response speed is a whole beat slow?

5) Obtaining content files does not support hot update

During development, when the content mentioned above is retrieved, it is loaded only the first time. It will be retrieved directly from memory, which means that no debugging will take effect if the file is changed or even deleted.

6) The page listens to watchQuery

Watchquery needs to note that it needs to return in order to render in real time. Second, the WatchQuery’s this object will change if plugin injection is used.

7) asyncData only takes effect on the first screen

In the normal mind, asyncData should be triggered by each page. However, asyncData can only be initialized on the first screen when the url is entered from the browser or the link is refreshed. If it is a jump to the current page, it is only client-loaded, not rendered.

8) On demand

Like some third-party libraries, if you continue to use the all-import approach, the package size will greatly increase, so you need to consider how to optimize the problem. Introduction by need is a problem that needs attention.

Iv. Nuxt outlook

1) nuxt deployment

Nuxt deployment is slightly more complex than pure HTML deployment. I will share pM2 deployment and how to deploy NUXT on Docker.

2) nuxt refactoring

After watching nuxT, you might get the feeling that Vue-CLI can quickly switch to NUxT. However, in the process of reconstruction, there will be a lot of holes. It’s easy to migrate all at once. I am trying to use Qiankun to complete the transition and reconstruction. Demo will be shared later, please look forward to it.

3) nuxt 3

Nuxt 3 appears when you finish nuxT. Nuxt3 is a good option for vuE3 users.