WordPress & Vue.js with Webpack and Hot Reload

What this is about

We recently worked on projects that needed an integration in WordPress. We decided to try Webpack and use the Vue CLI to create a plugin and also a frontend app. Although we are still mixing PHP and use the typical WordPress functionalities.

Today we want to show you our workflow how to develop and include a Vue.js App with Webpack into WordPress while using Docker. For that we will create a simple plugin with a simple admin page that loads the Vue app. In the beginning we were only able to achieve a live reload instead of a hot reload. We got this fixed and are now very happy with the workflow, mixing good old WordPress with amazing Vue :)

Outline

  • Setup WordPress with Docker

Setup WordPress with Docker

We are working on Linux / Mac. Make sure you have Docker and Docker Compose installed. For Windows Users you need at least Windows 10 Pro with the Hyper-V Manager installed. Instruction for Hyper-V can be found here.

This is not needed but we structure our WordPress projects like this. Create a new directory for your project.

root/
docker-compose.yml
www/
wp-config.php
...
// Rest of WordPress installation

Download and install WordPress. And unzip its content into the www directory. We have a oneliner for you. Inside the root directory type:

wget https://wordpress.org/latest.zip && unzip latest.zip && mv wordpress www && rm latest.zip

Copy this into the docker-compose.yml in the root directory:

version: "3"services:
www:
image: wordpress
ports:
- "8001:80"
environment:
WORDPRESS_DB_NAME: wordpress
WORDPRESS_DB_USER: root
WORDPRESS_DB_PASSWORD: root
volumes:
- ./www:/var/www/html/
links:
- db:mysql
networks:
- default
db:
image: mysql:5.7.22
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- persistent:/var/lib/mysql
networks:
- default
phpmyadmin:
image: phpmyadmin/phpmyadmin
links:
- db:db
ports:
- 8000:80
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
persistent:

This creates a database container with mySQL and phpMyAdmin and also uses a WordPress prepared container that maps the www directory to the containers /var/www/html directory. The environment variables will be automatically set in the wp-config.php file inside the www directory.

Note that links: db:mysql is helpful to easily link the www container with the db container under the alias mysql.

Startup the containers by running (a download will start):

docker-compose up -d

You should now be able to visit your WordPress website at http://localhost:8001 and phpMyAdmin at http://localhost:8000

Follow the installation instructions for WordPress. For development purposes you can choose root as username and password.

When finished try to login to WordPress at http://localhost:8001/wp-admin

Create a simple WordPress Plugin

There are many tutorials out there how to create a plugin. We will create a dead simple plugin for this tutorial.

Go to the www/wp-content/plugins directory and create a new directory called vue-plugin. Inside this directory create a new file called vue-plugin.php. Add this on top of the file:

<?php/*
Plugin Name: Vue Hot Reload Plugin
Description: Vue Hot Reloading inside of WordPress.
Version: 1.0.0
*/

This is the plugin header. WordPress uses it to show information about the plugin on the Plugins page in the Dashboard. Visit the Plugins page now and you should see this:

Plugin Page

You can already activate the plugin if you want although we still need to add some code to add functionality to the plugin. Add this additional code to your vue-plugin.php:

class VuePlugin {
public function __construct() {
$this->register_hooks();
}
private function register_hooks() {
// Register hook to add a menu to the admin page
add_action('admin_menu', [ $this, 'add_admin_menu' ]);
}
public function add_admin_menu() {
add_menu_page(
'Vue Plugin Example',
'Vue Plugin',
'manage_options',
'vue-plugin',
[ $this, 'load_vue_plugin_page' ],
'dashicons-smiley',
4
);
}
public function load_vue_plugin_page() {
// For a better overview we load page templates separately
require_once 'templates/vue-plugin-admin.php';
}
}new VuePlugin();

This initializes a new class that adds an admin menu in the dashboard. The add_menu_page calls the load_vue_plugin_page function which requires another PHP file that represents the template of the admin page.

Create a new directory inside your plugin directory called templates. Inside of this directory create a file called vue-plugin-admin.php and add this code to it.

<div class="wrap">
<h1><?= get_admin_page_title() ?></h1>
<div id="app"></div>
</div>

Your structure should look like this:

Plugin Structure

If you refresh the page now you should see a new menu entry called Vue Plugin. When you click on it you should see this:

Plugin Admin Page

That’s it for the plugin. We are ready to add Vue.js

If you are already familiar with Vue you will notice that we added

<div id="app"></div>

inside of the template page. This will be used as the entry point for our Vue App.

Add a Vue.js app via Vue CLI to the Plugin

Make sure you have the latest Vue CLI installed on your computer. If you don’t have the CLI installed you can install it via (further instructions here):

npm install -g @vue/cli
# OR
yarn global add @vue/cli

When the installation is finished create a new webpack vue project inside your plugin root directory by typing:

vue create vue

vue will be the name of the directory that will be created.

Setup your Vue Project with the settings you need except for the last part. It is important to put the config files into separate files. For a simple app we prefer these settings:

Vue CLI Setup

When the installation is finished your plugin directory structure should look like this:

Plugin Structure after Vue installation

Now comes the essential part of this whole story. You need to configure vue to generate output files that can be enqueued by WordPress. For this create a new file called vue.config.js inside your vue directory. Add this configuration to the file:

const devPort = 8081;module.exports = {
devServer: {
hot: true,
writeToDisk: true,
liveReload: false,
sockPort: devPort,
port: devPort,
headers: { "Access-Control-Allow-Origin": "*" }
},
publicPath:
process.env.NODE_ENV === "production"
? process.env.ASSET_PATH || "/"
: `http://localhost:${devPort}/`,
configureWebpack: {
output: {
filename: "app.js",
hotUpdateChunkFilename: "hot/hot-update.js",
hotUpdateMainFilename: "hot/hot-update.json"
},
optimization: {
splitChunks: false
}
},
filenameHashing: true,
css: {
extract: {
filename: "app.css"
}
}
};

This is a load of configuration and we gonna explain the most important things here step by step.

  1. devServer contains settings that will be used while running the app in development mode.

You can freely choose the port for the app (except Port 8000 and 8001 since those are taken by the Docker containers)

That is it for the setup of Vue. We will now enqueue the files into WordPress.

Link WordPress and the Webpack output

We need to touch our .php files again for this. Extend your VuePlugin class inside your vue-plugin.php with the following code:

class VuePlugin
{
public function __construct() {
$this->register_hooks();
}
private function register_hooks() {
...
add_action('admin_enqueue_scripts', [ $this, 'load_scripts' ]);
}
public function add_admin_menu() {
...
}
public function load_vue_plugin_page() {
wp_enqueue_style( 'backend-vue-style' );
wp_enqueue_script( 'backend-vue-script' );
...
}
public function load_scripts() {
$vueDirectory = join( DIRECTORY_SEPARATOR, [ plugin_dir_url(__FILE__), 'vue', 'dist' ] );
wp_register_style( 'backend-vue-style', $vueDirectory . '/app.css' );
wp_register_script( 'backend-vue-script', $vueDirectory . '/app.js', [], '1.0.0', true );
}
}new VuePlugin();

We add the action admin_enqueue_scripts which calls the load_scripts() function. Inside of this function we register our app.css and app.js file for use in WordPress. The load_vue_plugin_page() function enqueues those files when it is loaded inside the browser. We do this to prevent loading of app.css and app.js on every other page than our plugin admin page.

That’s it already it is time to try out Vue.

Running Vue and watch some hot reloading

With your docker containers already running go to your plugin admin page:

Plugin Admin Page Before

Now switch inside your vue directory and run the command npm run serve. The development server for vue will startup and a dist directory will be generated in vue/dist. You should find the app.js and the app.css along with some other files inside that directory. In your console you should see this:

Vue CLI Output

Reload your admin page and you should see this:

Plugin Admin Page After

Any changes to your files inside the vue directory (EXCEPT setting files) should trigger a hot reload or probably a live reload of the page.

Tips for deployment

To generate a production ready output of your app simply type:

npm run build

The dist directory will contain your production ready files. So: No need to change anything in WordPress :)

When deploying your app you probably don’t want to include all files generated by webpack. You actually only need to deploy the dist directory. We have a CI setup on Gitlab that cleans the directory except the dist and leaves only the app.js and app.css.

Thank you very much for following this story until here. We hope that we could enlight you a bit and open up a new possibility for you to develop modern plugins within WordPress.

You can find the whole code repository here.

Best regards and happy developing

The devs