Vue 3 with TypeScript – Setup A New Project with the Vue-Cli

Vue Logo

To setup the project, you will use the terminal and the vue-cli. These steps are the same as a Vue 2 app, but at the end with use vue add vue-next to upgrade to Vue 3 and make a few changes to some of the files to complete the upgrade.

If you do not have this installed on your computer yet, you can install it globally using npm:

npm install -g @vue/cli

Create Project Wizard

To create our project, do:

vue create my-vue3-app

Next it will ask you if you want to choose a default preset or manually select individual features. Use the arrow key to move up/down choose Manually select features by pressing the enter key:

Vue CLI v4.4.6
? Please pick a preset: 
  default (babel, eslint) 
❯ Manually select features 

Now move up/down with arrows and use the space-bar to check/uncheck the features you want. For this project select TypeScript, Router, Vuex, CSS Pre-processors, Linter / Formatter, Unit Testing only then hit the Enter key::

Vue CLI v4.4.6
? Please pick a preset: Manually select features
? Check the features needed for your project: 
 ◯ Babel
 ◉ TypeScript
 ◯ Progressive Web App (PWA) Support
 ◉ Router
 ◉ Vuex
 ◉ CSS Pre-processors
 ◉ Linter / Formatter
❯◉ Unit Testing
 ◯ E2E Testing

It will then ask you a series of questions. Make the following choices:

? Use class-style component syntax? (Y/n) n
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? (y/N) N
? Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n) n
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): 
  Sass/SCSS (with dart-sass) 
❯ Sass/SCSS (with node-sass) 
  Less 
  Stylus 
? Pick a linter / formatter config: (Use arrow keys)
❯ ESLint with error prevention only 
  ESLint + Airbnb config 
  ESLint + Standard config 
  ESLint + Prettier 
  TSLint (deprecated)
? Pick additional lint features: (Press <space> to select, <a> to toggle all, <i> to invert selection)
❯◉ Lint on save
 ◯ Lint and fix on commit
? Pick a unit testing solution: (Use arrow keys)
❯ Mocha + Chai 
  Jest
? Where do you prefer placing config for Babel, ESLint, etc.? (Use arrow keys)
❯ In dedicated config files 
  In package.json
? Save this as a preset for future projects? (y/N) N

NOTE: It might also ask you at this point if you want to use yarn or npm as your package manager. If so, please choose npm.

The vue-cli will now create the project, install all the required NPM packages, create the configuration files, and stub some preliminary code (Home and About views, a simple HelloWorld component, Vuex store, etc)

At the end it should display a message similar to this:

🎉  Successfully created project my-vue3-app.
👉  Get started with the following commands:

 $ cd my-vue3-app
 $ npm run serve

The first command will navigate to the current sub-directory called my-vue3-app, the second will serve the app with the vue-cli-service. You’ll see a message similar to this displayed:

 DONE  Compiled successfully in 2415ms                                                                         10:48:46 AM

Type checking in progress...

  App running at:
  - Local:   http://localhost:8080/ 
  - Network: http://192.168.1.7:8080/

  Note that the development build is not optimized.
  To create a production build, run npm run build.

No type errors found
Version: typescript 3.9.7
Time: 2537ms

From the web browser, navigate to the http://localhost:8080/ address and you’ll see application home page rendered:

This image has an empty alt attribute; its file name is 1*AleQBckYNXTYjRky8BSMfw.png

Now stop the app from running by typing CTRL+C in the terminal.

Now let’s make it a Vue 3 app with this command:

> vue add vue-next

It should display something like this once it is done:

✔  Successfully invoked generator for plugin: vue-cli-plugin-vue-next
 vue-next  Installed vuex 4.0.
 vue-next  Documentation available at https://github.com/vuejs/vuex/tree/4.0
 vue-next  Installed vue-router 4.0.
 vue-next  Documentation available at https://github.com/vuejs/vue-router-next
 vue-next  Installed @vue/test-utils 2.0.
 vue-next  Documentation available at https://github.com/vuejs/vue-test-utils-next

Open the package.json file and verify that the vue, vue-router, vuex packages have been update to the latest version (version3 for Vue, and 4 for vue-router and vuex. Note that they might still be in alpha or beta). The “dependencies” section should look similar to this:

"dependencies": {
    "vue": "^3.0.0-beta.1",
    "vue-router": "^4.0.0-alpha.6",
    "vuex": "^4.0.0-alpha.1"
  }

Open the src/main.ts file and verify that it has been upgraded to use the new Vue 3 way of instantiating the app:

import { createApp } from 'vue';
import App from './App.vue'
import router from './router'
import store from './store'

createApp(App)
  .use(router)
  .use(store)
  .mount('#app')

Unfortunately, it won’t automatically update all the files so perform the following additional steps to update some of the files.

Replace the <script> section content of the src/components/HelloWorld.vue with this:

<script lang="ts">
  export default {
    name: 'HelloWorld',
    props: {
      msg: String,
    },
    setup() {
      return {
      }
    }
  }
</script>

Replace the src/store/index.ts code with this:

import { createStore, Store } from 'vuex'

export default createStore({
  state: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})

For the src/router/index.ts file, it might not update the code copletely as expected. Just in case, replace it with this code:

import { RouteRecordRaw, createRouter, createWebHashHistory } from 'vue-router';
import Home from '../views/Home.vue'

const routes: Array<RouteRecordRaw> = [
{
  path: '/',
  name: 'Home',
  component: Home
},
{
  path: '/about',
  name: 'About',
  // route level code-splitting
  // this generates a separate chunk (about.[hash].js) for this route
  // which is lazy-loaded when the route is visited.
  component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
}
]

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

export default router

Finally, we have to also update the typescript shim declaration files. Since in this project we do not use tsx, just delete the src/shims-tsx.d.ts file.

For the src/shims-vue.d.ts, it might have updated it as expected, otherwise replace it with this:

declare module '*.vue' {
  import { defineComponent } from "vue";
  const Component: ReturnType<typeof defineComponent>;
  export default Component;
}

Finally, also delete the tests/unit/example.spec.ts file.

Now try to run the app again with:

> npm run serve

In the browser, navigate to http://localhost:8080/ again and verify the app is rendering without errors.

What We Learned

  • How to create the basic plumbing for a Vue 3 app using the vue-cli and vue add vue-next
  • How to serve the app using the vue-cli service through the command npm run serve

Originally published at http://www.scalingvue.com on August 8, 2020.