DEV Community

Cover image for How To Install Vue 3 in Laravel 8 From Scratch
Suresh Ramani
Suresh Ramani

Posted on • Originally published at techvblogs.com

How To Install Vue 3 in Laravel 8 From Scratch

What is Vue.js?

Vue is a progressive framework for building user interfaces. Unlike other monolithic frameworks, Vue is designed from the ground up to be incrementally adoptable. The core library is focused on the view layer only and is easy to pick up and integrate with other libraries or existing projects. Vue.js is a popular front-end framework for building Single Page Apps. It provides structure and abstraction. We can also create a server-side rendering application using Vue.js, It's helpful for SEO (Search Engine Optimization).

In older versions of Laravel, Vue was set up automatically with every new installation. However, in newer versions, you have to set it up yourself.

Luckily, the laravel/ui the package provides an easy way to set up Vue in your Laravel application.

A step-by-step guide to installing, mounting, and displaying Vue 3 components in a base Laravel 8 install.

Step 1: Install Laravel Project

First, open Terminal and run the following command to create a fresh laravel project:

composer create-project --prefer-dist laravel/laravel laravel-vue3
Enter fullscreen mode Exit fullscreen mode

or, if you have installed the Laravel Installer as a global composer dependency:

laravel new laravel-vue3
Enter fullscreen mode Exit fullscreen mode

Step 2: Install Vue & Dependencies

First, we'll want to install Vue 3 and our dev dependencies:

npm install --save vue@next && npm install --save-dev vue-loader@next
Enter fullscreen mode Exit fullscreen mode

Step 3: Prepare Mix for Vue

Let's go to our webpack.mix.js file and add a .vue() method chain. Our mix file should now look something like this:

const mix = require('laravel-mix');

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel applications. By default, we are compiling the CSS
 | file for the application as well as bundling up all the JS files.
 |
 */

mix.js('resources/js/app.js', 'public/js')
    .vue()
    .postCss('resources/css/app.css', 'public/css', [
        //
    ]);
Enter fullscreen mode Exit fullscreen mode

Step 4: Create your Vue 3 component

Next, let's go ahead and create our Vue 3 component. In the spirit of adventure, let's use the new composition API. Create a file /resources/js/components/Welcome.vue as so:

<template>
    <h1>{{ title }}</h1>
</template>
<script>
export default {
    setup: () => ({
        title: 'How To Install Vue 3 in Laravel 8 From Scratch'
    })
}
</script>
Enter fullscreen mode Exit fullscreen mode

Step 5: Import Vue to the Laravel javascript file

First, we are not going to import Vue, we are going to import a named export from Vue 3 called createApp.

import { createApp } from 'vue'
Enter fullscreen mode Exit fullscreen mode

let's import our Welcome component and create the Vue app.

import HelloWorld from './components/Welcome.vue';

const app = createApp({});
Enter fullscreen mode Exit fullscreen mode

Finally, our app.js the file will look something like this:

require('./bootstrap')

import { createApp } from 'vue'
import HelloWorld from './components/Welcome'

const app = createApp({})

app.component('hello-world', HelloWorld)

app.mount('#app')
Enter fullscreen mode Exit fullscreen mode

Step 6: Prepare Blade for Vue

Now let us create an element that has that id. To do this, we can remove the standard markup found in our welcome.blade.php file and replace it with this:

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Laravel</title>

        <!-- Fonts -->
        <link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap" rel="stylesheet">

        <!-- Styles -->
        <style>
            /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}a{background-color:transparent}[hidden]{display:none}html{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}*,:after,:before{box-sizing:border-box;border:0 solid #e2e8f0}a{color:inherit;text-decoration:inherit}svg,video{display:block;vertical-align:middle}video{max-width:100%;height:auto}.bg-white{--bg-opacity:1;background-color:#fff;background-color:rgba(255,255,255,var(--bg-opacity))}.bg-gray-100{--bg-opacity:1;background-color:#f7fafc;background-color:rgba(247,250,252,var(--bg-opacity))}.border-gray-200{--border-opacity:1;border-color:#edf2f7;border-color:rgba(237,242,247,var(--border-opacity))}.border-t{border-top-width:1px}.flex{display:flex}.grid{display:grid}.hidden{display:none}.items-center{align-items:center}.justify-center{justify-content:center}.font-semibold{font-weight:600}.h-5{height:1.25rem}.h-8{height:2rem}.h-16{height:4rem}.text-sm{font-size:.875rem}.text-lg{font-size:1.125rem}.leading-7{line-height:1.75rem}.mx-auto{margin-left:auto;margin-right:auto}.ml-1{margin-left:.25rem}.mt-2{margin-top:.5rem}.mr-2{margin-right:.5rem}.ml-2{margin-left:.5rem}.mt-4{margin-top:1rem}.ml-4{margin-left:1rem}.mt-8{margin-top:2rem}.ml-12{margin-left:3rem}.-mt-px{margin-top:-1px}.max-w-6xl{max-width:72rem}.min-h-screen{min-height:100vh}.overflow-hidden{overflow:hidden}.p-6{padding:1.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.pt-8{padding-top:2rem}.fixed{position:fixed}.relative{position:relative}.top-0{top:0}.right-0{right:0}.shadow{box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06)}.text-center{text-align:center}.text-gray-200{--text-opacity:1;color:#edf2f7;color:rgba(237,242,247,var(--text-opacity))}.text-gray-300{--text-opacity:1;color:#e2e8f0;color:rgba(226,232,240,var(--text-opacity))}.text-gray-400{--text-opacity:1;color:#cbd5e0;color:rgba(203,213,224,var(--text-opacity))}.text-gray-500{--text-opacity:1;color:#a0aec0;color:rgba(160,174,192,var(--text-opacity))}.text-gray-600{--text-opacity:1;color:#718096;color:rgba(113,128,150,var(--text-opacity))}.text-gray-700{--text-opacity:1;color:#4a5568;color:rgba(74,85,104,var(--text-opacity))}.text-gray-900{--text-opacity:1;color:#1a202c;color:rgba(26,32,44,var(--text-opacity))}.underline{text-decoration:underline}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.w-5{width:1.25rem}.w-8{width:2rem}.w-auto{width:auto}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}@media (min-width:640px){.sm\:rounded-lg{border-radius:.5rem}.sm\:block{display:block}.sm\:items-center{align-items:center}.sm\:justify-start{justify-content:flex-start}.sm\:justify-between{justify-content:space-between}.sm\:h-20{height:5rem}.sm\:ml-0{margin-left:0}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:pt-0{padding-top:0}.sm\:text-left{text-align:left}.sm\:text-right{text-align:right}}@media (min-width:768px){.md\:border-t-0{border-top-width:0}.md\:border-l{border-left-width:1px}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width:1024px){.lg\:px-8{padding-left:2rem;padding-right:2rem}}@media (prefers-color-scheme:dark){.dark\:bg-gray-800{--bg-opacity:1;background-color:#2d3748;background-color:rgba(45,55,72,var(--bg-opacity))}.dark\:bg-gray-900{--bg-opacity:1;background-color:#1a202c;background-color:rgba(26,32,44,var(--bg-opacity))}.dark\:border-gray-700{--border-opacity:1;border-color:#4a5568;border-color:rgba(74,85,104,var(--border-opacity))}.dark\:text-white{--text-opacity:1;color:#fff;color:rgba(255,255,255,var(--text-opacity))}.dark\:text-gray-400{--text-opacity:1;color:#cbd5e0;color:rgba(203,213,224,var(--text-opacity))}.dark\:text-gray-500{--tw-text-opacity:1;color:#6b7280;color:rgba(107,114,128,var(--tw-text-opacity))}}
        </style>

        <style>
            body {
                font-family: 'Nunito', sans-serif;
            }
        </style>
    </head>
    <body class="antialiased">
        <div id="app">
            <div class="relative flex items-top justify-center min-h-screen bg-gray-100 sm:items-center py-4 sm:pt-0">
                <hello-world/>
            </div>
        </div>

        <script src="{{ mix('js/app.js') }}"></script>
    </body>
</html>
Enter fullscreen mode Exit fullscreen mode

As you can see, we have a div with the id app that will be replaced by our Vue app.

Below we have a script tag that references not the app.js we have in resources/js but within our public/js folder. This file is the end result of our webpack build process.

Step 7: Compile Javascript Assets

Lastly, we'll run

npm run watch
Enter fullscreen mode Exit fullscreen mode

Run php artisan serve and check http://localhost:8000

Thank you for reading this blog.

Top comments (1)

Collapse
 
raw_rahul_singh profile image
RAHUL RAWAT

I did the exact same thing on my pc but vue component is not loaded in the blade file also there is no error. What should I do?