Getting started with Vue 3 composition API in typescript with Laravel Mix from scratch

Bijaya Prasad Kuikel
3 min readJun 28, 2021

Laravel is one of the most loved web frameworks by the developers. It makes development so easier and fun. VueJs is one of the most loved JavaScript and rapidly growing Web Framework. This article will cover steps on implement Vue 3 in TypeScript with Laravel Mix and Composition API from scratch.

Let’s get started:

Many developers love TypeScript. The reason is it simplifies JavaScript code, as it adds the readability and writability and makes easier to debug. It gives us all the benefits of the modern JavaScript (ES6 & beyond) also can help us to avoid painful bugs that developers commonly run into when writing JavaScript by type checking the code.

We can start by scaffolding a new laravel app using the command:

laravel new laravue3-ts

Let’s get into this directory and install the required dependencies:

yarn add vue@next vue-loader@next @vue/compiler-sfc

yarn add ts-loader typescript --dev

Now, let’s generate a tsconfig.json file in the root directory with the following contents on it. (Please refer to the official documentation https://v3.vuejs.org/guide/typescript-support.html#typescript-support.)

{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
// this enables stricter inference for data properties on `this`
"strict": true,
"jsx": "preserve",
"moduleResolution": "node"
}
}

Now, let’s generate shims-vue.d.ts file inside resources directory which stores the type defination for .vue files with the following content:

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

Now, we need to make changes on our webpack.mix.js file:

const mix = require("laravel-mix");mix.ts("resources/js/app.ts", "public/js").vue({ version: 3 });

Now, let’s add a few components insides resources/js/components directory:

  • Welcome.vue:
<template>
Hello {{ name }} welcome to my app.
<hr />
<counter></counter>
</template>
<script lang="ts">
import { defineComponent, ref } from "vue";
import Counter from "./Counter.vue";
export default defineComponent({
components: {
Counter,
},
setup() {
const name = ref<string>("Bijaya");
return {
name,
};
},
});
</script>
  • Counter.vue:
<template>
<button @click.prevent="decrement">-</button>
{{ count }}
<button @click.prevent="increment">+</button>
</template>
<script lang="ts">
import { defineComponent, ref } from "vue";
export default defineComponent({
name: "counter",
setup() {
const count = ref<number>(0);
const increment = ():number => {
return count.value++;
};
const decrement = ():number => {
return count.value--;
};
return {
count,
increment,
decrement,
};
},
});
</script>

Great, now that we have added the components, now lets rename the default resources/js/app.js to app.ts and update the contents to have following:

import { createApp } from "vue";
import Welcome from "./components/Welcome.vue";
const app = createApp({
components: {
Welcome,
},
}).mount("#app");

Finally, let’s update the resources/welcome.blade.php file with following contents:

<body>
<div id="app">
<welcome />
</div>
<script src="{{ asset('js/app.js') }}"></script>

</body>

We are rendering a welcome component in the blade file which will show the welcome message along with a counter component that we added.

Now we can compile all of the assets using command: yarn dev

Boot the laravel server: php artisan serve and then access: http://localhost:8000 which will render the following output:

Output as seen on the browser on accessing: http://localhost:8000

Please watch my video on youtube for detailed explanation:

--

--