Integrating Vue Inside Yii2

Yii2 represents a very powerful framework based on PHP. It comes with several features that help you minimize your development time and deliver real products. Yii2 is a quick, secure and very reliable PHP framework that allows for an easy way of installation, high extensibility, testing support, caching support and many other factors that help developers to create robust projects quickly.

Srdjan Drakul
Fullstack Developer

However, even if we implement all of the cool features that Yii2 bring to the table, sometimes we can encounter problems such as slowness, particularly if the page has a lot of HTML rendered and requires a lot of interactivity with end users. When this happens, we should consider using some of the modern JavaScript frameworks.

Rewriting the entire application into a JS framework can be unacceptable for our clients in terms of finance, thus we have to find different approaches. One possible solution is to move the problematic parts of the page from server to our browser, and provide high speed of execution by serving that data only from API without re-rendering the entire page. One of the best JS frameworks that can accomplish this is Vue.

Vue is a progressive JS framework. This means that if you have an existing server side rendered application, you can plug Vue into just one part of your application which needs a richer and more interactive experience. Vue is lightweight and designed to be easy to integrate inside existing applications. In this blog post, we will discuss how to integrate Vue inside just one part of an existing Yii2 application.

To start off, let’s imagine that we are using a basic template of a Yii2 application and we want to replace the main container of the page with application served in Vue. In order to build Vue, we need to have Node and NPM installed. Node installation depends on the operating system you are running your application on.

The first thing is to cd into root folder of our application and initialize npm by running:

npm init

We will be prompted to enter some information regarding the project. This is not very important at the moment so we can simply stick with the default values for now. Upon successful creation of the package.json file we can add Vue package:

npm install --save vue

Since Vue application requires build file to run properly, we should find the tool that will serve this purpose. One of the most popular tools that takes your development assets and combines them into a bundle is called Webpack. In our case, Webpack will build all of our components into a single JS file which can be injected into Yii2 application assets. Let’s install it by executing the following command:

npm install --save-dev webpack webpack-cli

Along with Webpack, we must install webpack-cli, a tool used to run Webpack on the command line. Webpack and webpack-cli packages are needed for development purposes and because of this, we will append –save-dev flag during installation.

Once that’s done, create src folder inside Yii2 application root and put Vue entry point script along with App component. Entry point app.js script should look like this:

import Vue from 'vue';
import App from './App.vue';

new Vue({
  el: '#app',
  render: h => h(App)
})

The piece of code below will pull the main application component and render it into the DOM element with id “app”:

// App.vue
<template>
    <div>
        <h1>{{ text }}</h1>
    </div>
</template>

<script>
    export default {
        name: "App",
        data: function () {
            return {
                text: 'This part of application is rendered in Vue.'
            }
        }    
}
</script>

All packages needed for building up Vue code are exposed below:

npm install --save-dev vue-loader vue-template-compiler vue-style-loader css-loader style-loader

In the root of our project, we will create webpack.config.js file. This file will contain all configuration that is needed for Webpack.

// webpack.config.js
const path = require('path');
const webpack = require( 'webpack' );

const PATHS = {
    source: path.join(__dirname, 'src'),
    build: path.join(__dirname, 'web') 
};

const { VueLoaderPlugin } = require('vue-loader');

module.exports = (env, argv) => {
    let config = {
        production: argv.mode === 'production'
    };

    return {
        mode: 'development',
        entry: [
            './src/app.js'
        ],
        output: {
            path: PATHS.build,
            filename: config.production ? 'app.min.js' : 'app.js'
        },
        module: {
            rules: [
                {
                    test: /\.vue$/,
                    use: 'vue-loader'
                },
                {
                    test: /\.css$/,
                    loader: ['style-loader', 'css-loader']
                }
            ]
        },
        plugins: [
            new VueLoaderPlugin()
        ]
    };
};

Module section contains loaders needed for building code of Vue component. Bundled Vue application is almost ready - there are only two more scripts that need to be added inside package.json file in order to bundle it in development and production environments. We should update scripts sections of package.json file to the following:

"scripts": {
    "dev": "webpack --config webpack.config.js",
    "prod": "webpack --config webpack.config.js --optimize-minimize --mode production"
  }

Now that we have everything in place for building Vue application in js file, lets run “npm run dev“. This command will bundle up code and generate script for development purposes that can be included into the Yii2 application bundle. In my personal opinion, it is much cleaner to create a separate layout file layout.php and VueAssets.php asset bundle class and avoid inclusion of Vue bundle in other pages which don’t need it. Action that will render Vue container page is represented below along with other Yii2 based code needed for proper functioning of Vue app inside Yii2 project structure:

// VueAssets.php
class VueAssets extends yii\web\AssetBundle
{
    public $basePath = '@webroot';
    public $baseUrl = '@web';

    public function init()
    {
        parent::init();

        $this->js[] = YII_ENV === 'local' ? 'app.js' : 'app.min.js';
    }
}

// IndexController.php
public function actionVue()
{
	// set the specific layout for pages that will render vue
	$this->layout = 'vue_main';

	// override bundle configuration if needed
	Yii::$app->assetManager->bundles = [];

	// render page
	return $this->render('vue_page');
}

// vue_main.php
$bundle = VueAssets::register($this);

To see these steps in full implementation, please visit: https://github.com/srdjan92/yii2-vue-basic