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.

Outline

  • Setup WordPress with Docker
  • Create a simple WordPress Plugin
  • Add a Vue.js app via Vue CLI to the Plugin
  • Link WordPress and the Webpack output *UPDATE
  • Running Vue and watch some hot reloading
  • Tips for deployment

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.

root/
docker-compose.yml
www/
wp-config.php
...
// Rest of WordPress installation
wget https://wordpress.org/latest.zip && unzip latest.zip && mv wordpress www && rm latest.zip
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:
docker-compose up -d

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.

<?php/*
Plugin Name: Vue Hot Reload Plugin
Description: Vue Hot Reloading inside of WordPress.
Version: 1.0.0
*/
Plugin Page
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();
<div class="wrap">
<h1><?= get_admin_page_title() ?></h1>
<div id="app"></div>
</div>
Plugin Structure
Plugin Admin Page
<div id="app"></div>

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
vue create vue
Vue CLI Setup
Plugin Structure after Vue installation
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"
}
}
};
  1. writeToDisk ensures that even in development mode output files are generated to the filesystem. We will use this to enqueue the generated files into WordPress.
  2. sockPort and port need to be the same otherwise the hot reload module won’t find a connection for the HRM (Hot Reload) module.
  3. headers: { “Access-Control-Allow-Origin”: “*” } is needed since WordPress is hosted on localhost:8001 but our app (and the hot reloading) will run on localhost:8081. Don’t worry this setting is only applied during development and won’t affect production mode.
  4. publicPath this setting is very important as it ensures that vue can find all necessary files of your app. In development mode the app checks http://localhost:8081 which will serve all files and enables hot reload.
  5. filename: “app.js” and filename: “app.css” as well as hotUpdateChunkFilename: “hot/hot-update.js” and hotUpdateMainFilename: “hot/hot-update.json” are important to ensure that the output files generated from vue are always named the same to prevent enqueue errors by 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();

Running Vue and watch some hot reloading

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

Plugin Admin Page Before
Vue CLI Output
Plugin Admin Page After

Tips for deployment

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

npm run build

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store