Advanced Vue 3 Project Setup and Deployment

Project Scaffolding and Configuration

Creating the Project

To initiate a new Vue 3 project with TypeScript support, use the Vue CLI:

vue create my-vue-app

During the setup, select the following options:

  • Manually select features
  • Choose Vue version, Babel, TS, Router, Vuex, CSS Pre-processors, Linter
  • Vue.js version: 3.x
  • Use class-style component syntax? No
  • Use Babel alongside TypeScript? Yes
  • Use history mode for router? No
  • Pick a CSS pre-processor: Sass/SCSS
  • Pick a linter / formatter config: Prettier
  • Lint on save
  • Where to place config files: In dedicated config files
  • Save as preset? No
  • Package manager: NPM

Code Standards

.editorconfig

Define consistent coding styles across editors:

# http://editorconfig.org
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
max_line_length = off
trim_trailing_whitespace = false

Prettier

Install Prettier for code formatting:

npm i -D prettier

Create a .prettierrc configuration file:

{
  "useTabs": false,
  "tabWidth": 2,
  "printWidth": 80,
  "singleQuote": true,
  "trailingComma": "none",
  "semi": false
}

Create a .prettierignore file to exclude certain files:

/dist/*
.local
.output.js
/node_modules/**

**/*.svg
**/*.sh

/public/*

Add a script to your package.json:

{
  "scripts": {
    "prettier": "prettier --write ."
  }
}

ESLint

Install ESLint and integrate it with Prettier:

npm i -D eslint-plugin-prettier eslint-config-prettier

Configure ESLint in .eslintrc.js:

module.exports = {
  root: true,
  env: {
    node: true
  },
  extends: [
    'plugin:vue/vue3-essential',
    'eslint:recommended',
    '@vue/typescript/recommended',
    '@vue/prettier',
    '@vue/prettier/@typescript-eslint',
    'plugin:prettier/recommended'
  ],
  parserOptions: {
    ecmaVersion: 2020
  },
  rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    '@typescript-eslint/no-var-requires': 'off',
    '@typescript-eslint/no-explicit-any': 'off',
    '@typescript-eslint/explicit-module-boundary-types': 'off',
    '@typescript-eslint/no-non-null-assertion': 'off'
  }
}

Git Hooks with Husky

Set up Husky to run linting before commits:

npx husky-init && npm install

Configure the pre-commit hook in .husky/pre-commit:

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npm run lint

Commitizen

Standardize commit messages:

npm i -D commitizen
npx commitizen init cz-conventional-changelog --save-dev --save-exact

Add a script to your package.json:

{
  "scripts": {
    "commit": "cz"
  }
}

Commitizen will prompt you for the type, scope, and description of your changes.

Commitlint

Validate commit messages:

npm i -D @commitlint/config-conventional @commitlint/cli

Create a commitlint.config.js file:

module.exports = {
  extends: ['@commitlint/config-conventional']
}

Add a commit-msg hook:

npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1"

Project Structure

vue.config.js

Configure Vue CLI options:

const path = require('path')

module.exports = {
  outputDir: 'dist',
  publicPath: '/',
  configureWebpack: {
    resolve: {
      alias: {
        '@': path.resolve(__dirname, 'src'),
        components: '@/components'
      }
    }
  }
}

Vue Router

Install Vue Router:

npm i -S vue-router@next

Configure routes in src/router/index.ts:

import { createRouter, createWebHashHistory } from 'vue-router'
import type { RouteRecordRaw } from 'vue-router'

const routes: Array<routerecordraw> = [
  {
    path: '/',
    redirect: '/dashboard'
  },
  {
    path: '/dashboard',
    component: () => import('../views/Dashboard.vue')
  },
  {
    path: '/profile',
    component: () => import('../views/Profile.vue')
  }
]

const router = createRouter({
  history: createWebHashHistory(),
  routes
})

export default router</routerecordraw>

Vuex

Install Vuex:

npm i -S vuex@next

Set up the store in src/store/index.ts:

import { createStore, useStore as useVuexStore } from 'vuex'
import user, { IUserState } from './modules/user'

export interface IRootState {
  user: IUserState
}

export default createStore<irootstate>({
  modules: {
    user
  }
})

export function useStore() {
  return useVuexStore<irootstate>()
}</irootstate></irootstate>

Element Plus

Install Element Plus:

npm i -S element-plus

Import and use it in src/main.ts:

import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

const app = createApp(App)
app.use(ElementPlus)
app.mount('#app')

Axios

Install Axios:

npm i -S axios

Configure Axios in src/utils/request.ts:

import axios from 'axios'
import type { AxiosRequestConfig } from 'axios'
import Cookies from 'js-cookie'

const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API,
  timeout: 5000
})

service.interceptors.request.use(
  (config) => {
    const token = Cookies.get('token')
    if (token && config.headers) {
      config.headers.Authorization = `Bearer ${token}`
    }
    return config
  },
  (error) => {
    return Promise.reject(error)
  }
)

service.interceptors.response.use(
  (response) => {
    switch (response.data.code) {
      case 999:
        console.log('Error occurred')
        break
      default:
    }
    return response
  },
  (error) => {
    switch (error.response.status) {
      case 401:
        console.log('Unauthorized or token expired')
        break
      case 403:
        console.log('Access denied')
        break
      default:
    }
    return Promise.reject(error)
  }
)

interface IResponseBody<t any=""> {
  code: number
  data: T
  message: string
}

export default function <t any="">(
  config: AxiosRequestConfig
): Promise<iresponsebody>> {
  return service(config).then((res) => {
    return res.data
  })
}</iresponsebody></t></t>

Environment Variables

Vue CLI supports different environment files:

  • .env.development for dveelopment
  • .env.production for production
  • .env.staging for staging

Variables must start with VUE_APP_ to be injected into the code.

tsconfig.json

Configure TypeScript options:

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "strict": true,
    "jsx": "preserve",
    "importHelpers": true,
    "moduleResolution": "node",
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "sourceMap": true,
    "baseUrl": ".",
    "types": [
      "webpack-env"
    ],
    "paths": {
      "@/*": [
        "src/*"
      ]
    },
    "lib": [
      "esnext",
      "dom",
      "dom.iterable",
      "scripthost"
    ]
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
    "tests/**/*.ts",
    "tests/**/*.tsx"
  ],
  "exclude": [
    "node_modules"
  ]
}

shims-vue.d.ts

Declare Vue component types:

/* eslint-disable */
declare module '*.vue' {
  import type { DefineComponent } from 'vue'
  const component: DefineComponent<{}, {}, any>
  export default component
}

Advanced Vue 3 Concepts

Component Instance Types

Access child component instance types:

<template>
  <div>
    <child-component ref="childRef"></child-component>
    <el-button @click="decrementAge">Decrement</el-button>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue'
import ChildComponent from './ChildComponent.vue'

export default defineComponent({
  components: { ChildComponent },
  setup() {
    const childRef = ref()
    type ChildComponentType = InstanceType<typeof ChildComponent>

    const decrementAge = () => {
      const childInstance: ChildComponentType = childRef.value
      childInstance.person.age--
    }

    return {
      childRef,
      decrementAge
    }
  }
})
</script>

Props Typing

Define props with TypeScript:

<script lang="ts">
import { defineComponent, PropType } from 'vue'

interface IPerson {
  username: string
  age: number
}

export default defineComponent({
  props: {
    persons: {
      type: Array as PropType<IPerson[]>,
      required: true
    }
  },
  setup(props) {
    props.persons.forEach((item) => {
      console.log(item.username)
    })
  }
})
</script>

Using Props in <script setup>

Define props with defaults in the setup syntax:

<template>
  <div ref="chartRef" :style="{ width: width, height: height }"></div>
</template>

<script lang="ts" setup>
import * as echarts from 'echarts'
import { EChartsOption } from 'echarts'
import { ref, onMounted, withDefaults, defineProps } from 'vue'

const props = withDefaults(
  defineProps<{
    options: EChartsOption
    width?: string
    height?: string
  }>(),
  {
    width: '100%',
    height: '100%'
  }
)

const chartRef = ref<HTMLDivElement>()

onMounted(() => {
  const chart = echarts.init(chartRef.value!, 'light', {
    renderer: 'svg'
  })
  chart.setOption(props.options)
})
</script>

Browser Repaint and Reflow

Optimize for performance:

  • Use transform instead of position
  • Avoid table layouts
  • Use visibility: hidden instead of display: none
  • Minimize DOM manipulation

ECharts Rendering

Choose between Canvas and SVG:

  • Canvas: Suitable for large datasets and visual effects
  • SVG (Recommended): Lower memory usage, scales with out blurring

Exposing Properties and Methods

Expose component properties and methods to parent components:

<script lang="ts" setup>
import { defineExpose, ref } from 'vue'

const userData = ref({ name: 'John Doe', age: 30 })
const greet = () => {
  console.log('Hello!')
}

defineExpose({
  userData,
  greet
})
</script>

Project Packaging and Automated Deployment

Setting Up CentOS 7 with DNF

Install DNF package manager:

yum install epel-release -y
yum install dnf -y

Installing Java

Install Java 8:

dnf search java-1.8
dnf install java-1.8.0-openjdk.x86_64 -y

Installing Jenkins

Install Jenkins using RPM:

dnf install daemonize -y
rpm -ivh jenkins-2.332-1.1.noarch.rpm

Start and enible Jenkins:

systemctl start jenkins
systemctl enable jenkins

Installing Nginx

Install and start Nginx:

dnf install nginx -y
systemctl start nginx
systemctl enable nginx

Installing Git

Install Git:

dnf install git -y

Jenkins Configuration

Configure Jenkins for Node.js and deployment:

  1. Initialize Jenkins and install recommended plugins.
  2. Install the Node.js plugin and configure Node.js installations.
  3. Change the Jenkins user to root for file access permissions.
  4. Create a new freestyle project.
  5. Configure source code management (Git) and build triggers.
  6. Set up the build environment to provide Node.js and npm.
  7. Add a build step to execute a shell script.

Example shell script for deployment:

pwd
node -v
npm -v
npm install
npm run build
echo 'Build successful'
ls
rm -rf /usr/share/nginx/html/*
cp -rf ./dist/* /usr/share/nginx/html/

Example cron job for scheduled builds:

# Run every 30 minutes
H/30 * * * *

# Run every 2 hours
H H/2 * * *

# Run daily at 2 AM
H 2 * * *

Tags: Vue.js TypeScript ESLint Prettier Jenkins

Posted on Tue, 29 Sep 2026 16:55:17 +0000 by spider