WordPress & Vue.js with Webpack and Hot Reload

What this is about

Outline

Setup WordPress with Docker

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

<?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

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"
}
}
};

Link WordPress and the Webpack output

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

Plugin Admin Page Before
Vue CLI Output
Plugin Admin Page After

Tips for deployment

npm run build