Sherri Flemings

Software Swiss Army Knife • Textile Hobbyist • Gamer • Foodie •

Modern WordPress theme workflow

I recently set up a WordPress theme for a project that made use of the beta version of Sage which makes use of Laravel Blade. This project only required a few PHP pages with the bulk of functionality coded using my frontend framework of choice, Vue.js. If you have no need for backend functionality I'd recommend skipping Sage and just hook Vue into your theme's index.php file. 

Install Sage

I followed the installation instructions for Sage 9 (still in beta at the time of this writing).

wp-content/themes$ composer create-project roots/sage your-theme-name dev-master

Install Node Dependencies

Before I installed the node dependencies I made a bunch of changes to the package.json Sage creates. I struggled a bit trying to get the build scripts to work properly and the learning curve was a bit steep with multiple build files and configs so I reverted to Laravel Mix to build my frontend dependencies since it's a tool I already know very well and use in most of my other web projects (Laravel and non-Laravel projects).

I found it easiest to select all the packages listed in package.json devDependencies and delete rather than sort through which packages to keep and remove. Then I installed these (most of these were already listed by Sage):

Note: I use the --no-optional flag due to an issue I was experiencing where builds failed if it had fsevents as an optional dependency.

themeroot$ npm install --no-optional --save-dev eslint eslint-loader eslint-plugin-import laravel-mix rimraf stylelint stylelint-config-standard stylelint-webpack-plugin

Next I added my VueJS dependency.

themeroot$ npm install --no-optional --save vue

Configure Laravel Mix

Copy the default mix file into your theme root:

themeroot$ cp -r node_modules/laravel-mix/setup/webpack.mix.js ./


let mix = require('laravel-mix');

const rootPath = path.join(__dirname, '..');
const themeRoot = 'app/themes/modern-theme';
const resources = 'resources';
const assets = `${resources}/assets`;
const dist = 'dist';


    output: {
        publicPath: `${themeRoot}/${dist}/`,
        // chunkFilename: 'manager/' + template + "/[name].js"
        vue: {
            esModule: true
        extractVueStyles: true, // Extract .vue component styling to file, rather than inline.
        //   globalVueStyles: file, // Variables file to be imported in every component.
    .js(`${assets}/scripts/main.js`, `${dist}/scripts/`)
    .extract(['vue', 'jquery'])
    .sass(`${assets}/styles/main.scss`, `${dist}/styles/`)
    .copyDirectory(`${assets}/images`, `${dist}/images`)
    .copyDirectory(`${assets}/fonts`, `${dist}/fonts`);

if (mix.inProduction()) {
    // Hash and version files in production.
    mix.version(); // need to add cb to theme's php page
else {
    // Source maps when not in production.

Update Build Scripts

Since I'm not using the Sage build scripts I updated package.json to call Laravel Mix to build my assets. By default Laravel Mix minifies and optimizes js and css for production builds.


"scripts": {
    "dev": "NODE_ENV=development webpack --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch": "NODE_ENV=development webpack --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch:poll": "NODE_ENV=development webpack --watch --watch-poll --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "production": "NODE_ENV=production webpack --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"

Remove Build Files

# remove files replaced by Laravel Mix
rm -rf resources/assets/build
rm -rf resources/assets/scripts/routes
rm resources/assets/scripts/util
rm resources/assets/customizer.js
rm resources/assets/config.json

Create a Vue App

As a quick test to make sure everything is wired up properly you can edit resources/views/index.blade.php to create a Vue app.


  <div id="app">
  {{ message }}


import Vue from 'vue';

const app = new Vue({
  el: '#app',
  data: { message: 'Hello Vue!' }

It's a work in progress but hopefully this can help you get started if you want to create a Sage theme with Vue.js. If I get some extra time I'll try to set up some vanilla boilerplate to a public repo. Currently my project is part of a private git repo with assets that belong to a client.

comments powered by Disqus