iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
⚡

Blazing Fast WordPress Development Environment with wp-env and Vite

に公開

Ever since I discovered the speed of Vite, I've been hooked on its development experience. I've put together a WordPress development environment using Vite, and I'd like to share it. Please note that this is tailored to my personal development workflow and may not be suitable for every development scenario.

Here is the repository:
https://github.com/Crayfisher-zari/my-best-wp-env

By enabling Vite's HMR (Hot Module Replacement) during development, it should provide a lightning-fast WordPress development experience.

Prerequisites and Concept

This development environment is based on the following prerequisites and concepts:

  1. Assumes development of traditional PHP-based classic themes. I'm not sure if it can be applied to new block theme development.
  2. Assumes a macOS environment. (It should work on Windows too, but since the NPM scripts include the rm command, please replace it as needed.)
  3. Assumes a workflow where you create static HTML before moving to WordPress development, but it can also be used for direct WordPress development.
  4. Aiming for long-term usability, the configuration is kept as simple as possible, avoiding third-party plugins as much as possible.
  5. Uses Sass (SCSS) and TypeScript.
  6. I want to keep the inside of the theme files as clean as possible.
  7. Consideration is also given to reducing environment differences between developers in a multi-person team.

If you're using Vite only for WordPress theme development, you could just set up the Vite environment within the theme files. However, there are times when the workflow involves creating static HTML first and then moving to WordPress development. This setup is designed to handle that. (Also, I personally don't want to include too many development source files within the theme files that are ultimately uploaded.)

Required Environment

This configuration requires the following to be pre-installed:

  • Node.js
  • Docker

High-level Overview

This development environment builds a WordPress environment on Docker using wp-env and starts a local development server with Vite. By referencing Sass and TypeScript files hosted on the Vite local server, it provides a fast development experience.

The folder structure is as follows:

└src
  └assets
    └images
    └js
    └style
  └pubilc
    └images
└wordpress
  └wordpress
    └plugins
    └themes
    └uploads
└package.json
└vite.config.ts

The basic workflow is to create static HTML in the src folder, then build it and move to WordPress development once completed. However, since CSS and JavaScript continue to change even after the static HTML is finished, I designed this to avoid the need for manual rebuilding every time a change is made.

Simple Mechanism Explanation

I've made it possible to switch Vite configurations between static development and WordPress development.

▼vite.config.ts (Excerpt)

const root = resolve(__dirname, "src");

// Input settings for WordPress builds. Since HTML files are not needed for WordPress, only scss and ts are targeted for building.
const inputsForWordPress = {
  style: resolve(root, "/assets/style/style.scss"),
  // Dynamically retrieve files @see https://rollupjs.org/configuration-options/#input
  ...Object.fromEntries(
    globSync("src/assets/js/*.ts").map((file) => [
      relative(
        "src/assets/js",
        file.slice(0, file.length - extname(file).length),
      ),
      fileURLToPath(new URL(file, import.meta.url)),
    ]),
  ),
};

// Input settings for static development. For static assets, build scss, ts, etc., via html files.
const inputsForStatic = {
  style: resolve(root, "/assets/style/style.scss"),
  ...Object.fromEntries(
    globSync("src/**/*.html").map((file) => [
      relative("src", file.slice(0, file.length - extname(file).length)),
      fileURLToPath(new URL(file, import.meta.url)),
    ]),
  ),
};

export default defineConfig(({ mode }) => ({
  build: {
    rollupOptions: {
      input: mode === "wp" ? inputsForWordPress : inputsForStatic,
    },
  },
}));

During static development, Vite loads CSS and the .html files in the src folder. For WordPress builds, HTML files are unnecessary, so it loads CSS and .ts files directly. These are switched via the --mode argument in NPM scripts. If you're developing directly in WordPress without static development, you can just set the input in rollupOptions to inputsForWordPress without any conditional logic.

I've also applied some clever logic to the header section of index.php on the WordPress side.

▼index.php header section

<?php 
  if(WP_DEBUG){
    $root = "http://localhost:5173";
    $css_ext = "scss";
    $js_ext = "ts";
    echo '<script type="module" src="http://localhost:5173/@vite/client"></script>';
  }else{
    $root = get_template_directory_uri();
    $css_ext = "css";
    $js_ext = "js";
  } 
?>
<link rel="stylesheet" href="<?php echo $root;?>/assets/style/style.<?php echo $css_ext?>">
<script src="<?php echo $root;?>/assets/js/script.<?php echo $js_ext?>" type="module"></script>

Since "WP_DEBUG": true is set in .wp-env.json, during development, $root points to the SCSS and TypeScript files on Vite's localhost:5173. It also loads the HMR script, so source changes are immediately reflected on the WordPress screen.

In non-development modes, it references the built CSS and JavaScript files within the theme folder. If you want to check the built files during development, you can change the if-statement to if(false). Changing the value in .wp-env.json isn't recommended as Docker treats it as a different container. While WP_DEBUG is unlikely to be true in a production environment, it's a good idea to remove this logic before final delivery just in case.

Synchronizing WordPress Content with Other Developers

When developing with WordPress, you may want to keep articles, pages, and other settings created within WordPress in sync across developers. While this can be achieved by setting up a shared WordPress site on a restricted server, it involves the overhead of uploading files every time.

To allow for some level of synchronization, this setup synchronizes content by sharing WordPress backup files between developers.

You can export a backup file using the wp-contents export command in the NPM Scripts and import it using the wp-contents import command. By managing this backup file in Git or similar, you can synchronize WordPress content among developers. Since it is a single backup file, it does not support diff management and is not suitable for frequent updates (if a conflict occurs, you can only adopt one of the files).

Usage

Here is a brief explanation of how to use it, excerpted from the repository's README.

During Static Production

When creating static HTML, running the dev command in the NPM Scripts will start a local server at localhost:5173. Please keep this port number fixed, as it is also referenced during WordPress development. (If you change it, you will also need to update the WordPress side.)

Static HTML is basically created within the src folder. For CSS and JavaScript, you can reference .scss and .ts files directly, and Vite will handle them correctly.

▼HTML header section

<link rel="stylesheet" href="/assets/style/style.scss" />
<script src="/assets/js/script.ts" type="module"></script>

Then, just proceed with developing the HTML, CSS, and JavaScript as usual.

During WordPress Theme Development

First, please start Docker. Similar to static production, run the dev command in the NPM Scripts, and then execute the wp-start command. The initial startup will take some time as it downloads various resources. Once wp-start is running, you will be able to access localhost:8888. This is your local WordPress environment.

During development, CSS and JavaScript reference files from the Vite local server, so you can continue to work on the files in the src folder just as you did during static production. When finished, stop the Docker container using wp-stop.

Storage and Loading of Images (Important)

Please follow the rules below to ensure that image paths, etc., are correctly resolved both during development and after the build.

Store images loaded via img tags in src/public/images, and store images loaded via CSS or JS in src/assets/images/.

Folder structure

└src
  └assets
    └images
      └background.png
      └js.png
  └pubilc
    └images
      └static.png

In Vite, the public folder is treated as the root, so images can be loaded using a path like /images/static.png.

▼HTML

<img src="/images/static.png" alt="" width="300" height="300" />

When loading images in CSS, use a path starting with /assets instead of a relative path. This is also to allow Vite to resolve the path during the build.

▼CSS

background-image: url("/assets/images/background.png");

When loading image files in JS, use an import statement so that Vite can resolve the path during the build.

▼JS

import imgsrc from "/assets/images/js.png";
// Sample for loading an image from JS
const canvas = document.querySelector<HTMLCanvasElement>("#canvas");
const context = canvas!.getContext("2d");
const image = new Image(300, 300);
image.src = imgsrc;
image.addEventListener("load", () => {
  context?.drawImage(image, 0, 0, 300, 300);
})

When loading images with PHP during WordPress development, reference the images within the template folder. During the WordPress build, images from the public folder used in static production are output to the template folder. However, these are not updated dynamically, so you will need to rebuild or manually copy the images whenever they are changed.

<img src="<?php echo get_template_directory_uri();?>/images/static.png" alt="" width="300" height="300" />

By prefixing the src in the static asset HTML code with <?php echo get_template_directory_uri();?> as shown above, images can be loaded correctly.

About Static Asset Builds

To build static assets, run the build command in the NPM Scripts. The complete set of files will be output to the dist folder.

About WordPress Builds

To build CSS and JavaScript for WordPress, run the build for WP command in the NPM Scripts. The assets and images folders will be output inside wordpress/themes/TEMPLATE_NAME/. The assets folder contains the built CSS and JavaScript files, while the images folder contains the static images referenced from the HTML.

How to Log In to WordPress

Access http://localhost:8888/wp-admin/. You can log in with the ID admin and the password password. The language is set to English by default, so it's a good idea to change it to Japanese.

Conclusion

Linters and formatters are included; please adjust those settings to your preference. Also, no specific plugins are included, so please customize the environment according to the needs of your project.

I hope you find it useful.

Discussion