Building a dynamic web app with Vuejs framework Nuxtjs + Express — Part1: Getting Started
Building a non-refresh web app with a desktop-like experience is not that hard, you just need a right tool.
Introduction
Vuejs is a great javascript framework, but building a full functionality web app is not easy. It lacks an architectural structure and its router generates a lot of boilerplate code. This is how Nuxtjs comes into play. NuxtJs is an easy to learn, progressive and high-performance framework that can be used for:
- Static content webpages: Create static pages easily. Share partials, footers, headers, and sidebars like a pro.
- Server-side rendering: Render your content on the server-side, SEO friendly, encapsulate business logic on the server-side.
- Single page application: Build a next-generation web application without page refreshing.
Installation
Nuxtjs installation page gives pretty well and details step by step to do this.
yarn create nuxt-app nuxtavocado
From the above options I chose: Yarn as package manager, Ant Design Vue as UI framework, Express as web server framework, axios + pwa + dotenv as nuxtjs modules and jest as test framework. You might choose the same to follow along this blog. When we get deeper I will also show alot of automate testing with jest from what I observe testing in nodejs app are rare and very basic, hopefully this blog will be a cornerstone for you to see the importance of unit test, integration test and lead to a agile development with nodejs particulary Express and Jest.
Then
cd nuxtavocado
yarn devError: listen EADDRINUSE: address already in use 127.0.0.1:3000
at Server.setupListenHandle [as _listen2] (net.js:1309:16)
at listenInCluster (net.js:1357:12)
at GetAddrInfoReqWrap.doListen [as callback] (net.js:1496:7)
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:69:10)
Emitted 'error' event on Server instance at:
at emitErrorNT (net.js:1336:8)
at processTicksAndRejections (internal/process/task_queues.js:84:21) {
code: 'EADDRINUSE',
errno: -48,
syscall: 'listen',
address: '127.0.0.1',
port: 3000
}
[nodemon] app crashed - waiting for file changes before starting...
Because Nuxtjs use port 3000 by default, I have rails app server running on port 3000, This causes Nuxtjs failed to start.
Now let’s starts to change the default port of Nuxtjs to 8000 for now
// nuxtjs.config.jsmodule.exports = {
mode: 'universal', /*
** Customer server config
*/
server: {
port: 8000
},
Let’s try to run again
> yarn dev
. . .READY Server listening on http://localhost:8000
Separate configurations from code
// .env
SERVER_PORT=8080
in nuxtjs.config.js
require('dotenv').config()module.exports = {
mode: 'universal',// srcDir: 'src',
// buildDir: 'functions/.nuxt',server: {
port: process.env.PORT || 8000
},
Now go ahead restart the server in the terminal
yarn dev...
ℹ Waiting for file changes 12:36:10READY Server listening on http://localhost:8080
git init .
git add .
git commit -m 'Finish the installation'
git remote add origin my_git_repo_address
git push origin master
Create a layout and Page
Common stylesheets for every page
under /assets create a folder stylesheets
/assets/stylesheets/main/reset.css
/assets/stylesheets/main/layout.css
/assets/stylesheets/main/animate.css
with the following content
/assets/stylesheets/main/reset.css
html, body, * {
padding: 0px;
margin: 0px;
}
/# /assets/stylesheets/main/layout.cs
.container {
min-height: 600px;
}
/assets/stylesheets/main/animate.css
.page-enter-active, .page-leave-active {
transition: opacity .5s;
}
.page-enter, .page-leave-to {
opacity: 0;
}.animate-logo {
animation: 3s appear;
margin: auto;
}@keyframes appear {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
Now create a plugin under the /plugins/ folder
// plugins/main-style.jsimport '~/assets/stylesheets/main/animate.css'
import '~/assets/stylesheets/main/reset.css'
import '~/assets/stylesheets/main/layout.css'
Now register the main-style.js plugin in the nuxt.config.js
...
plugins: [
'@/plugins/antd-ui',
'@/plugins/main-style'
],
Create our own logo
Copy your logo to assets/images/logo.png
under components open Logo.vue and modify with the following content
<template>
<nuxt-link to="/" class="animate-logo" style="border-radius: 6px;">
<img src="~/assets/images/logo.png" height="32">
</nuxt-link>
</template>
Modify our home page
Open to edit pages/index.vue
<template>
<div class="container">
Home
</div></template><script>
export default {
layout: 'default'
}
</script>
Modify the default layout
Open layouts/default.vue
<template>
<a-layout id="components-layout-demo-top-side">
<bmb-header /> <a-layout-content>
<nuxt />
</a-layout-content> <a-layout-footer style="text-align: center">
Ant Design ©2018 Created by Ant UED
</a-layout-footer>
</a-layout>
</template><script>
import BmbHeader from '@/components/Header'export default {
components: {
BmbHeader
}
}
</script>
Create our first component for Header in components/Header.vue
<template>
<a-layout-header class="manu-header" :style="{ position: 'fixed', zIndex: 1, width: '100%', background: '#fff' }">
<div class="menu-left">
<logo class="logo" />
<a-menu
theme="light"
mode="horizontal"
:style="{ lineHeight: '64px' }"
>
<a-menu-item key="1">
Item
</a-menu-item>
</a-menu>
</div><div>
<nuxt-link to="/login">
<a-button type="" shape="round" icon="key">
Sign In
</a-button>
</nuxt-link><nuxt-link to="/registration">
<a-button type="primary" shape="round" icon="user">
Sign Up
</a-button>
</nuxt-link>
</div>
</a-layout-header>
</template><script>
import Logo from '@/components/Logo'
export default {
components: {
Logo
}
}
</script><style scoped>
.menu-left {
display: flex;
justify-content: flex-start
}.manu-header{
justify-content: space-between;
display: flex;
}.svg-inline--fa.fa-w-20{
width: 16px;
}.svg-inline--fa fa-grin-hearts fa-w-16{
width: 16px
}.svg-inline--fa.fa-w-16 {
width: 16px;
}.ant-layout-header {
/* height: 64px;
padding: 0 50px;
line-height: 64px;
background: #001529; */height: 64px;
background: white;
box-shadow: 0 2px 4px #ddd;
position: relative;
z-index: 10;
max-width: 100%;
}
</style>
Now let’s restart our server with yarn dev
Now let commit our changes
git add .
git commit -m 'Custom layout and page with ant design'
git push origin master
Now we have our Nuxtjs app with custom layout and page using Ant design UI for Vuejs.
Autocorrect ESLint error Config in Nuxtjs
You might have problems with ESLint raising errors. ESLint is a tool to help identify and report js style guide for a maintainable, high-quality code with ease. However, it might be a bit tricky when you first start using it or you are working with a long js file. If you happen to copy code around it will be overwhelming to fix the errors raise the ESLint. Luckily ESLint is very flexible because it can be set to autocorrect and format your code beautifully. So below is how to configure it in Nuxtjs app:
In nuxt.config.js
...
build: {
/*
** You can extend webpack config here
*/
extend (config, ctx) {
if ( !(ctx.isDev && ctx.isClient)) {
console.log('Not Lint custom');
return
}
console.log('Lint custom')
let rule = {
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /(node_modules)/,
options: {
fix: true
}
}
config.module.rules.push(rule)
}
}
Now let’s start the server to apply config change.
Navigation Between Pages
We are going to create 2 pages for users to sign in and sign up.
pages/login.vue
pages/registration.vue
For pages/login.vue
<template>
<div>
<h1>
Login
</h1>
</div>
</template>
and pages/registration.vue
<template>
<div>
<h1>
Registration
</h1>
</div>
</template>
Now visit http://localhost:8080/registration
Let’s commit
git add .
git commit -m 'Add basic session pages'
git push origin master
Conclusion
Getting started with Nuxtjs is pretty easy and straightforward. Next, we will build a fully functional login page with the Express server-side framework communicating with an API server to handle the login to prove Nuxtjs for a dynamic web application. Next, I will show how to do authentication and unit test our logic with the jest framework.