6

All-in-one Symfony 5 + Vue.js + Vuetify web application

 3 years ago
source link: https://michael.bouvy.net/post/all-in-one-symfony-5-vuejs-web-application
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

All-in-one Symfony 5 + Vue.js + Vuetify web application

symfony vuejs vuetify
Published on 2021/06/07

Nowadays, with the rise of frontend frameworks as Angular, React and Vue.js, headless backends have become more and more popular.

However, creating and mainting two distinct code bases (frontend + backend / API) may quickly become a hassle.

Thanks to Symfony's Webpack Encore, bundling Vue.js inside a Symfony application becomes a breeze. It also provides serious advantages, for instance relying on Symfony's security layer for authentication and session management.

I'll explain step-by-step below how to get an all-in-one Symfony + Vue.js + Vuetify web application.

Install Symfony and requirements

Install Symfony binary (https://symfony.com/download) then:

# Create Symfony application in symfony-vuetify directory
$ symfony new --full symfony-vuetify

$ cd symfony-vuetify

# Install PHP dependencies
$ composer require symfony/webpack-encore-bundle

# Install JS dependencies
$ yarn install

Add the following line in webpack.config.js:

Encore

  ...

  // Enable Vue loader
  .enableVueLoader()

  ...

;
JavaScript

Run yarn dev, and install suggested packages:

$ yarn dev
yarn run v1.22.10
$ encore dev
Running webpack ...

  Error: Install vue & vue-loader & vue-template-compiler to use enableVueLoader()
    yarn add vue@^2.5 vue-loader@^15.9.5 vue-template-compiler --dev

# Install additional packages 
$ yarn add vue@^2.5 vue-loader@^15.9.5 vue-template-compiler --dev

Let's now add vue-router and Vuetify:

$ yarn add vue-router vuetify

Edit you assets/app.js with the following content:

import './styles/app.css';

// start the Stimulus application
import './bootstrap';

import Vue from 'vue'
import VueRouter from 'vue-router'

import vuetify from './plugins/vuetify'

import Home from './components/Home'

const routes = [
    { path: '/', component: Home, name: 'home' }
]

const router = new VueRouter({
    mode: 'history',
    base: '/app/',
    routes
})

Vue.use(VueRouter)

new Vue({
    router,
    vuetify
}).$mount('#app')
JavaScript

Create the Vuetify plugin in assets/plugins/vuetify.js:

import Vue from 'vue'
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css'

Vue.use(Vuetify)

const opts = {
    theme: {
        themes: {
            light: {
                primary: '#1565c0',
                secondary: '#64b5f6',
                accent: '#78002e',
                error: '#d50000',
            },
        }
    }
}

export default new Vuetify(opts)
JavaScript

Enable Encore's script and link tags in templates/base.html.twig:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>{% block title %}symfony-vuetify{% endblock %}</title>
        {% block stylesheets %}
            {{ encore_entry_link_tags('app') }}
            <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
            <link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css" rel="stylesheet">
        {% endblock %}

        {% block javascripts %}
            {{ encore_entry_script_tags('app') }}
        {% endblock %}
    </head>
    <body>
        {% block body %}{% endblock %}
    </body>
</html>
Markup

Create a VueController in src/Controller/VueController.php:

<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class VueController extends AbstractController
{
    /**
     * @Route("/app/{route}", requirements={"route"=".*"}, name="vue")
     */
    public function index(): Response
    {
        return $this->render('vue/index.html.twig', [
            'controller_name' => 'VueController',
        ]);
    }
}

And create the template in templates/vue/index.html.twig:

{% extends 'base.html.twig' %}

{% block body %}
<div id="app">
    <v-app v-cloak>
        <v-app-bar short app >Symfony + Vuetify</v-app-bar>
        <v-main>
            <v-container fluid>
                <router-view></router-view>
            </v-container>
        </v-main>
    </v-app>
</div>
{% endblock %}
Markup

Note the use of v-cloak directive, which allows us to hide the Vue.js application during load, with the help of a single CSS line in assets/styles/app.css:

[v-cloak] { display: none; }

Finally, create the Home Vue.js component referenced in our router, in assets/components/Issue.vue:

<template>
    <v-alert
      type="success"
    >{{ message }}</v-alert>
</template>

<script>
    export default {
        name: 'Home',
        props: {},
        data: () => ({
          message: 'Hello Symfony + Vue.js!',
        }),
    }
</script>
Markup

To be able to test your application locally without installing a database (ie. MySQL or PostgreSQL), uncomment the DATABASE_URL environment variable for SQLite in your .env file and comment-out the PostgreSQL one:

DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
# DATABASE_URL="mysql://db_user:[email protected]:3306/db_name?serverVersion=5.7"
# DATABASE_URL="postgresql://db_user:[email protected]:5432/db_name?serverVersion=13&charset=utf8"

Run yarn devsymfony server:start, and open http://localhost:8000/app:

You're all set, and can now create additional components in assets/components. Note that hot-reload unfortunately doesn't work with this setup: although yarn dev --watch will live-rebuild frontend assets, you'll need to refresh your Symfony application to view changes.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK