Raul Cano logo

How to set up Vite in a WordPress theme - 21/10/2024

A step-by-step tutorial for integrating Vite as a modern build tool in WordPress

Compiler vs Bundler

Let’s briefly figure out some doubts I had between the difference of a compiler and a bundler. In the past we were using Babel and Webpack, with Babel you can compile your JavaScript code and Webpack will bundle it into a single file or multiple files. But now I’m using Vite as a bundler and compiler, since it covers both functionalities and it’s faster than Webpack.

Compiler

A JavaScript compiler allows you to write code using the latest version of JavaScript (ECMAScript 6) and it will transform or compile it to a version that is compatible with most browsers.

It’s primarily configured with a file or in your build tool (Vite, Rollup, Gulp, etc.).

Example of a code written in modern JavaScript ES6:

const greet = (name) => {
  console.log(`Hello, ${name}!`);
};

After it compiles the code, it will look like this (ES5):

var greet = function(name) {
  console.log('Hello, ' + name + '!');
};

Bundler

The purpose of a bundler is to group or bundle all your assets (JavaScript, CSS, etc.) into a single file or multiple files that can be loaded by the browser.

It’s primarily configured with a file or in your build tool (Vite, Webpack, Rollup, etc.).

Setting up Vite in WordPress

Creating the package.json file

You can simply run npm init -y to create a package.json file with default values.

Add the devDependencies in your package.json

npm install --save-dev vite sass

Or you can add them to devDependencies in your package.json file.

  "devDependencies": {
    "vite": "^5.4.9",
    "sass": "^1.80.3",
  }

Then run npm install to install the dependencies.

If you are using VSC you can also install the extension Version Lens to see or update the versions of your dependencies.

Add the scripts in your package.json

  "scripts": {
    "start": "vite build --watch",
    "dev": "vite",
    "build": "vite build"
  }

Create the vite.config.mjs file

Inside the root of your project, create a vite.config.mjs file and add the following code:

//vite.config.mjs
import { defineConfig } from 'vite';

export default defineConfig({
  // Vite configuration options
});

In the configuration file, you can define various options for your project, like the root directory and build options.

The root directory is where your JavaScript files are located, and the build options define the output directory and the input files.

Fill the entry and output variables in Vite

Change the paths according to your project. In Vite, you don’t explicitly define entry and output paths like in Webpack. Instead, you set the root and build options.

//vite.config.mjs
import { defineConfig } from 'vite';
import { resolve } from 'path';

// Get the main.js where all your JavaScript files are imported
const JS_FILE = resolve('src/scripts/main.js')

// Define where the compiled and minified JavaScript files will be saved
const BUILD_DIR = resolve(__dirname, 'dist');

export default defineConfig({
  build: {
    assetsDir: '', // Will save the compiled JavaScript files in the root of the dist folder
    manifest: true, // Generate manifest.json file (for caching)
    emptyOutDir: true, // Empty the dist folder before building
    outDir: BUILD_DIR,
    rollupOptions: {
      input: JS_FILE,
    },
  },
});

With this configuration, Vite will compile and bundle your JavaScript files into the dist directory. But not the CSS.

Folder structure with JavaScript files

At this point we should have something like this:

mytheme/
├── dist/
│   ├── main-AD2AS.js
│   └── .vite/
│       └── manifest.json
├── src/
│   └── scripts/
│       ├── main.js
│       ├── woo/
│       └── components/
├── node_modules/
├── package.json
├── package-lock.json
├── functions.php
├── vite.config.mjs
└── style.css

Enqueue JavaScript in functions.php

<?php
// ... other code
add_action('wp_enqueue_scripts', function(){
    $manifestPath = get_theme_file_path('dist/.vite/manifest.json');
    
    // Check if the manifest file exists and is readable before using it
    if (file_exists($manifestPath)) {
        $manifest = json_decode(file_get_contents($manifestPath), true);
        
        // Check if the file is in the manifest before enqueuing
        if (isset($manifest['src/scripts/main.js'])) {
            wp_enqueue_script('mytheme', get_theme_file_uri('dist/' . $manifest['src/scripts/main.js']['file']));
        }
    }
});
?>

Building the CSS

For this part we don’t need to touch the vite.config.mjs file any more. We just need to add the CSS files to the main.js file.

// src/scripts/main.js

/**
 * Main JS file for Cartify Child
 * 
 * Import the main css file
 * Import all the JavaScript files that are needed for the theme.
 */

// Import the main CSS file
import '../styles/main.scss'

// Build the main JS file
// ... other js files imports

In our case we need to create the main.scss file in the src/styles/ directory. There you will add or import all the other CSS files that you need.

Folder structure with CSS files

mytheme/
├── dist/
│   ├── main-something.js
│   └── .vite/
│       └── manifest.json
├── src/
│   ├── scripts/
│   │   ├── main.js
│   │   ├── woo/
│   │   └── components/
│   └── styles/
│       ├── main.scss
│       └── general/
├── node_modules/
├── package.json
├── package-lock.json
├── functions.php
├── vite.config.mjs
└── style.css

Enqueue CSS in functions.php

And as we did with the JavaScript files, we need to enqueue the CSS file in the functions.php file. We just need to update the previous code to enqueue the CSS file.

add_action('wp_enqueue_scripts', function(){
    $manifestPath = get_theme_file_path('dist/.vite/manifest.json');
    
    // Check if the manifest file exists and is readable before using it
    if (file_exists($manifestPath)) {
        $manifest = json_decode(file_get_contents($manifestPath), true);
        
        // Check if the file is in the manifest before enqueuing
        if (isset($manifest['src/scripts/main.js'])) {
            wp_enqueue_script('mytheme', get_theme_file_uri('dist/' . $manifest['src/scripts/main.js']['file']));
            // Enqueue the CSS file
            wp_enqueue_style('mytheme', get_theme_file_uri('dist/' . $manifest['src/scripts/main.js']['css'][0]));
        }
    }
});

My .vite/manifest.json file

Just for your curiosity, this is how my manifest.json file looks like:

{
  "src/scripts/main.js": {
    "file": "main-BL027S3L.js",
    "name": "main",
    "src": "src/scripts/main.js",
    "isEntry": true,
    "css": [
      "main-BLUr3EH8.css"
    ]
  }
}

Running Vite

Now you can run Vite with the following command:

npm run start

Conclusion

This is how you can set up Vite in a WordPress theme. It’s a bit different from Webpack, but it’s faster and easier to configure. You can also use Vite for many other projects.