DEV Community

Cover image for My WordPress Template 2024 made from Vite and TypeScript
Yuichi Nabeshima
Yuichi Nabeshima

Posted on

My WordPress Template 2024 made from Vite and TypeScript

Hi there😊
I'm Yuichi, a CCTB student and a Frontend developer.

I created new WordPress template for practical work.
It is assumed that making WordPress site from scratch.
I will share the template and its idea.

【Repository】: https://github.com/YuichiNabeshima/my-wordpress-template

Things I want to do on this template

  1. Do not use any JavaScript framework, keeping basic usage as WordPress.
  2. Do not use UI framework for handling various design.
  3. Each pages load CSS and JavaScript scripts as much as the page needs for reducing file size.
  4. I want to use Vite for bundling.
  5. I want to split JavaScript scripts as a file as each feature.

Directory structure

Main directories are these three.

  • public is put the static files like font or image.
  • src is put the codes needing build and compile, like CSS using post-css or TypeScript.
  • wp is put the production codes. When you deploy, you upload only this directory to production server. The assets of public and src will be output under the wp/assets/ after build command.
┣━ public ━ img/
┃        ┗━ fonts/
┃
┣━ src ━━━━ css/
┃        ┗━ ts/
┃
┣━ wp ━━━━━ assets/
┃        ┣━ index.php
┃        ┣━ front-page.php
┃        ┗━ ...
Enter fullscreen mode Exit fullscreen mode

Local environment

It uses wp-env for the local environment.
It is very easy to set up and no configuration.
We can check own site to http://localhost:8888 on web browser.

Strategy of entry point

JS and CSS should be loaded as much as necessary for the page in order to reduce the file size as much as possible.
In other words, it is assumed that every page has its own JS and CSS.
Of course, if you can share files between pages, do so (like common.js)
Each file put under the entry_point directory will be output under /wp/assets/ with the file name unchanged after build.

Image description

After build ...

Image description

You need to add the arguments of get_header() and get_footer() for loading the each builded file.

<?php
  get_header(null, [
    'css' => 'top',
  ]);
?>
Enter fullscreen mode Exit fullscreen mode
<?php
  get_footer(null, [
    'js' => 'top',
  ]);
?>
Enter fullscreen mode Exit fullscreen mode

Developing

Since I am using Vite, I want to use Vite's extremely fast development server.
Therefore, I have devised tags that load CSS and JS.

/wp/header.php

<?php
  if( WP_DEBUG && IS_DEV ):
?>
  <link rel="stylesheet" href="http://localhost:5173/src/css/entry_point/<?=$css?>.css">
<?php
  else:
?>
  <link rel="stylesheet" href="<?=get_stylesheet_directory_uri()?>/assets/css/<?=$css?>.css">
<?php
  endif;
Enter fullscreen mode Exit fullscreen mode

/wp/footer.php

<?php
  if( WP_DEBUG && IS_DEV ):
?>
  <script type="module" src="http://localhost:5173/@vite/client"></script>
  <script type="module" src="http://localhost:5173/src/ts/entry_point/<?=$js?>.ts"></script>
<?php
  else:
?>
  <script src="<?=get_stylesheet_directory_uri()?>/assets/js/<?=$js?>.js"></script>
<?php
  endif;
Enter fullscreen mode Exit fullscreen mode

During developing, we can benefit from Vite's development server by referencing http://localhost:5137.
When I start the Vite development server, what I see in my browser is http://localhost:8888.
http://localhost:5173 shows nothing

WP_DEBUG variable

The WP_DEBUG variable in if statement is set to true in wp-env.json, so even if you accidentally deploy with IS_DEBUG set to true, it will not enter debug mode.

IS_DEBUG variable

The IS_DEBUG variable is a global variable that you manually set in functions.php.
The default is true, so the local environment refers to the Vite's development server.
If you want to check the built JS and CSS in the local environment, please set it to false.

Styling

CSS concept

The reason of CSS is difficult is because the scope is always global.
Therefore, I want to propose that you don't have to make CSS commonly, put the CSS codes for each pages.
When the number of common CSS increases, in many cases, you will spend a lot of time searching for a class of common style somewhere when you add new page.

CSS directory structure

┣━ CSS ┯━ common ━━━━━┳━ reset.css
┃         ┃                          ┣━ base.css
┃          ┃                          ┗━ variable.css
┃          ┃
┃          ┣━ entry_point ┳━ top.css
┃      ┃                          ┗━ about.css
┃          ┣━ mixin ━━━━━━━━ media.css
┃          ┗━ page ━━━━━━━┳━ top.css
┃                                      ┗━ about.css
Enter fullscreen mode Exit fullscreen mode

As mentioned above CSS creates a single file dedicated to each page.
The CSS files under the entry_point gather all the CSS codes like below.

@import '../mixin/media.css';

@import '../common/reset.css';
@import '../common/variable.css';
@import '../common/base.css';

@import '../page/top.css';
Enter fullscreen mode Exit fullscreen mode

The main styles of the page are put in the CSS file under page.

There are some things you really want to commonly, such as common layouts, headings, and buttons.
In that case, please make an appropriate file under the mixin directory and import it to entry_point.

┣━ mixinγ€€β”―γ€€button.css
┃       β”—γ€€layout.css
Enter fullscreen mode Exit fullscreen mode

/src/css/entry_point/top.css

@import '../mixin/media.css';
@import '../mixin/button.css'; // import here

@import '../common/reset.css';
@import '../common/variable.css';
@import '../common/base.css';

@import '../page/top.css';
Enter fullscreen mode Exit fullscreen mode

/src/css/page/top.css

.btn {
  @mixin btn;
}
Enter fullscreen mode Exit fullscreen mode

JS

I will explain how to add JS feature in this template.

JS directory structure

┣━ ts ┳━ entry_point/ ━━ top.ts
┃        ┣━ modules/ ━━━━━━ alert.ts
┃        ┗━ register_module.ts
Enter fullscreen mode Exit fullscreen mode

How to add JS feature

First, add the data-module attribute to a HTML tag, which is the starting point of the event firing.
The value of data-module is assigned the function name which you want to add as JS feature(this will be explained later).

<button
  class="btn"
  data-module="alert"
>alert</button>
Enter fullscreen mode Exit fullscreen mode

Next, create a ts file for the feature you want to add under /src/ts/modules/ and define the function in it, example is below.

/src/ts/modules/alert.ts

export function alert( el: HTMLElement ) {
  el.addEventListener('click', () => {
    alert('click button!');
  });
}
Enter fullscreen mode Exit fullscreen mode

The argument of the function will be passed the DOM which you assigned the data-module attribute before, so you can use the DOM for making feature, like add event.

Finally, register the created function in the file under entry_point

/src/ts/entry_point/top.ts

import { registerModule } from '../register_module';
import { alert } from '../modules/alert';

registerModule({
  alert,
});

Enter fullscreen mode Exit fullscreen mode

That's it! You can use JS feature you created.

Pass the value from html

If you want to pass variables from html, pass them in json format to the data-options attribute.
Anything other than json will result in an error.

/wp/front-page.php

  <button
    class="alert-btn"
    data-module="alert"
    data-options='{
      "alertText": "I am from earth."
    }'
  >
    Alert!
  </button>
Enter fullscreen mode Exit fullscreen mode

/src/ts/modules/alert.ts

type Opts = {
  alertText: string;
}

export function alert( el: HTMLElement, opts: Opts ) {
  const msg = opts.alertText;
  el.addEventListener('click', () => {
    alert(msg);
  });
}
Enter fullscreen mode Exit fullscreen mode

Responsive

If you want to only run the module when device is PC or Smart phone.
You can use data-only attribute, there are 2 options which pc or sp.

Display width

pc >= 768px

sp < 768px

  <button
    class="alert-btn"
    data-module="alert"
    data-options='{
      "alertText": "I am from earth."
    }'
    data-only="pc"
  >
    Alert PC only!
  </button>
Enter fullscreen mode Exit fullscreen mode

When you want to put multiple modules on a tag.

  <button
    class="alert-btn"
    data-module="alert another-alert"
    data-options='{
      "alert": {
        "alertText": "message"
      },
      "another-alert": {
        "afterText": "after message"
      }
    }'
    data-only='{
      "alert": "pc",
      "another-alert": "sp"
    }'
  >
    Multiple module
  </button>
Enter fullscreen mode Exit fullscreen mode

How was my new WordPress template? I would be happy if you could use it and give me feedback if you like!

I am looking for a job

As of July 2024, I am looking for a job.
My areas of expertise are React, TypeScript, Remix, Next, PHP, and WordPress.
I'm currently a student, so I'm looking for a part-time position where I can work up to 20 hours a week.
I'm looking for a full-time job starting next August.

Top comments (2)

Collapse
 
itsmikita profile image
Mikita Stankiewicz

I never really understood this kind of development where you have lots of tools running, compiling, optimizing just to change a freaking color or font, but merely you even get there with all this as it breaks all the time -- pardon my growl, but I've been working with wordpress 20 years like and the safest way is to keep at least file structure real -- you will safe so much nerves and time to solve the bugs in production (and you will get the bugs in production no matter how many tests you would run beforehand).

Collapse
 
yuichi_nabeshima_canada profile image
Yuichi Nabeshima • Edited

Thank you for your comments!
Your point is valid, for development, this template needs to start two development server which are localhost:8888 for PHP runtime environment and localhost:5173 for fast building on the Vite.
It looks super wired, however if developers want to achieve something I wrote at Things I want to do on this template, I believe this template is one of the best choices.

If you need clarification, please let me know, I'll be happy to add it to this article.

Thank you for your valuable feedback!