Foreword
If Nuxt.js is a framework that helps us build websites with Vuejs using the Server Side Rendering mechanism (Render data from server side. Using this method, when googlebot crawls to any link from the website, we can read the content from full website). When we build websites with Reactjs there is a corresponding framework that everyone may know is Next.js.
main content
1. Introduction to Next.js
What is the Universal Javascript App?
The Universal Javascript App is a web application written in javascript (formerly known as isomorphic), which runs both the server and the browser side in the same source code. Of course, there are some that only need to be run in the browser such as page transitions, animations, elements, or using the local storage of the browser, while some source code is related to the process layer. ) or server-specific activities such as session, authentication, etc.
Introducing Nextjs
Next.js is a compact framework built from React, Babel and Wepack created to help programmers create React web applications with SSR (Server Side Render). As you know with React.js, we are building a front-end application with React-managed UI, the weakness is client-side-render only, so SEO will be difficult (can fix server side with javascript handling like Prerender.io ), Next.js makes it very easy for us to have SSR.
2. Math problem
I have also done a number of projects with vuejs’ Nuxtjs, most projects have done SEO so the use of SSR (Server Side Rendering) for the web is really necessary. Recently I have learned about Nextjs and tried to use it, sometimes changed a bit =)). Ok, both frameworks use the SSR mechanism, no problem. I also read docs and started working on normal code but …
If you have ever used Nuxtjs, VueApp, ReactApp or Nextjs, you will see that they are all apps completely separate from Api, with their own routers. Nuxtjs has middleware support that implements Authorization of routers. Nuxtjs has middleware support for us already. You just need to create the middleware file:
1 2 3 4 | <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> context <span class="token punctuation">)</span> <span class="token punctuation">{</span> context <span class="token punctuation">.</span> userAgent <span class="token operator">=</span> process <span class="token punctuation">.</span> server <span class="token operator">?</span> context <span class="token punctuation">.</span> req <span class="token punctuation">.</span> headers <span class="token punctuation">[</span> <span class="token string">'user-agent'</span> <span class="token punctuation">]</span> <span class="token punctuation">:</span> navigator <span class="token punctuation">.</span> userAgent <span class="token punctuation">}</span> |
To use middleware, the declaration in page.vue is done.
1 2 3 4 5 6 7 8 | <span class="token operator"><</span> template <span class="token operator">></span> <span class="token comment">//</span> <span class="token operator"><</span> <span class="token operator">/</span> template <span class="token operator">></span> <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span> middleware <span class="token punctuation">:</span> <span class="token punctuation">[</span> <span class="token string">'user-agent'</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> |
At first I thought that Nuxtjs supported writing so easily, so was Nextjs, but I was wrong =)), searching, digging up the docs of Nextjs did not see any =)). Therefore, this article I want to introduce you a way to write middleware when you use Nextjs.
3. Settlement
Thought: I will use the context, React HOC and store redux to write middleware for the router page.
Install Nextjs:
1 2 | npx create-next-app |
Or
1 2 | <span class="token function">npm</span> <span class="token function">install</span> --save next react react-dom |
And add package.js as follows
1 2 3 4 5 6 7 8 | <span class="token punctuation">{</span> <span class="token property">"scripts"</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"dev"</span> <span class="token operator">:</span> <span class="token string">"next"</span> <span class="token punctuation">,</span> <span class="token property">"build"</span> <span class="token operator">:</span> <span class="token string">"next build"</span> <span class="token punctuation">,</span> <span class="token property">"start"</span> <span class="token operator">:</span> <span class="token string">"next start"</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
okie done =)) Continue
Create middleware / auth.js file Execute creating a HOC, use context to get auth store.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <span class="token keyword">import</span> React <span class="token keyword">from</span> <span class="token string">'react'</span> <span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> checkAuth <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'~/utils/auth'</span> <span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function">WithAuthSync</span> <span class="token operator">=</span> <span class="token punctuation">(</span> WrappedComponent <span class="token punctuation">,</span> role <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token keyword">class</span> <span class="token class-name">MiddlewareAuth</span> <span class="token keyword">extends</span> <span class="token class-name">React <span class="token punctuation">.</span> Component</span> <span class="token punctuation">{</span> <span class="token keyword">static</span> <span class="token keyword">async</span> <span class="token function">getInitialProps</span> <span class="token punctuation">(</span> ctx <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> store <span class="token punctuation">}</span> <span class="token operator">=</span> ctx <span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token operator">!</span> store <span class="token punctuation">.</span> <span class="token function">getState</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token keyword">get</span> <span class="token punctuation">(</span> <span class="token string">'auth'</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token keyword">get</span> <span class="token punctuation">(</span> <span class="token string">'loaded'</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> unsubscribe <span class="token punctuation">;</span> <span class="token keyword">await</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> resolve <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> unsubscribe <span class="token operator">=</span> store <span class="token punctuation">.</span> <span class="token function">subscribe</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> store <span class="token punctuation">.</span> <span class="token function">getState</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token keyword">get</span> <span class="token punctuation">(</span> <span class="token string">'auth'</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token keyword">get</span> <span class="token punctuation">(</span> <span class="token string">'loaded'</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">resolve</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">unsubscribe</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> token <span class="token operator">=</span> <span class="token function">checkAuth</span> <span class="token punctuation">(</span> store <span class="token punctuation">.</span> <span class="token function">getState</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token keyword">get</span> <span class="token punctuation">(</span> <span class="token string">'auth'</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> role <span class="token punctuation">,</span> ctx <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> componentProps <span class="token operator">=</span> WrappedComponent <span class="token punctuation">.</span> getInitialProps <span class="token operator">&&</span> <span class="token punctuation">(</span> <span class="token keyword">await</span> WrappedComponent <span class="token punctuation">.</span> <span class="token function">getInitialProps</span> <span class="token punctuation">(</span> ctx <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token operator">...</span> componentProps <span class="token punctuation">,</span> token <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">render</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span> WrappedComponent <span class="token punctuation">{</span> <span class="token operator">...</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> props <span class="token punctuation">}</span> <span class="token operator">/</span> <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> |
Create the file utills / auth.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <span class="token keyword">import</span> Router <span class="token keyword">from</span> <span class="token string">'next/router'</span> <span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function">checkAuth</span> <span class="token operator">=</span> <span class="token punctuation">(</span> auth <span class="token punctuation">,</span> role <span class="token punctuation">,</span> ctx <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> user <span class="token operator">=</span> auth <span class="token punctuation">.</span> <span class="token keyword">get</span> <span class="token punctuation">(</span> <span class="token string">'user'</span> <span class="token punctuation">)</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> role <span class="token operator">===</span> <span class="token string">'admin'</span> <span class="token operator">&&</span> <span class="token punctuation">(</span> user <span class="token punctuation">.</span> size <span class="token operator">===</span> <span class="token number">0</span> <span class="token operator">||</span> <span class="token operator">!</span> user <span class="token punctuation">.</span> <span class="token keyword">get</span> <span class="token punctuation">(</span> <span class="token string">'is_admin'</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> ctx <span class="token punctuation">.</span> req <span class="token punctuation">)</span> <span class="token punctuation">{</span> ctx <span class="token punctuation">.</span> res <span class="token punctuation">.</span> <span class="token function">writeHead</span> <span class="token punctuation">(</span> <span class="token number">302</span> <span class="token punctuation">,</span> <span class="token punctuation">{</span> Location <span class="token punctuation">:</span> <span class="token string">'/'</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> ctx <span class="token punctuation">.</span> res <span class="token punctuation">.</span> <span class="token function">end</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token operator">!</span> ctx <span class="token punctuation">.</span> isServer <span class="token punctuation">)</span> <span class="token punctuation">{</span> Router <span class="token punctuation">.</span> <span class="token function">push</span> <span class="token punctuation">(</span> <span class="token string">'/'</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> role <span class="token operator">===</span> <span class="token string">'user'</span> <span class="token operator">&&</span> user <span class="token punctuation">.</span> size <span class="token operator">===</span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> ctx <span class="token punctuation">.</span> req <span class="token punctuation">)</span> <span class="token punctuation">{</span> ctx <span class="token punctuation">.</span> res <span class="token punctuation">.</span> <span class="token function">writeHead</span> <span class="token punctuation">(</span> <span class="token number">302</span> <span class="token punctuation">,</span> <span class="token punctuation">{</span> Location <span class="token punctuation">:</span> <span class="token string">'/'</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> ctx <span class="token punctuation">.</span> res <span class="token punctuation">.</span> <span class="token function">end</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token operator">!</span> ctx <span class="token punctuation">.</span> isServer <span class="token punctuation">)</span> <span class="token punctuation">{</span> Router <span class="token punctuation">.</span> <span class="token function">push</span> <span class="token punctuation">(</span> <span class="token string">'/'</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Here after passing the auth store, role user, and context component, check:
- Server side: writeHead if the user does not have access
- Client side: Use Router push.
And use:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <span class="token comment">//admin page</span> <span class="token keyword">import</span> React <span class="token keyword">from</span> <span class="token string">'react'</span> <span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> WithAuthSync <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'~/middleware/auth'</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">Dashboard</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span> <span class="token operator"><</span> div <span class="token operator">></span> Dashboard <span class="token operator"><</span> <span class="token operator">/</span> div <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token function">WithAuthSync</span> <span class="token punctuation">(</span> Dashboard <span class="token punctuation">,</span> <span class="token string">'admin'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
1 2 3 4 5 6 7 8 9 10 11 12 13 | <span class="token comment">// user page</span> <span class="token keyword">import</span> React <span class="token keyword">from</span> <span class="token string">'react'</span> <span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> WithAuthSync <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'~/middleware/auth'</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">UserPage</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span> <span class="token operator"><</span> div <span class="token operator">></span> Homepage <span class="token operator"><</span> <span class="token operator">/</span> div <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token function">WithAuthSync</span> <span class="token punctuation">(</span> UserPage <span class="token punctuation">,</span> <span class="token string">'user'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
Quite simple is not it, now let’s open the site and test offline
Conclusion
Sure, after the article, you can create middleware for the website using Next.js, right? Hope to receive more comments.