Svelte version: 4.2.0
rollup-plugin-svelte version: 7.1.6
GitHub repository: https://github.com/JustinyAhin/twentytwenty
During my time as a Senior Frontend Engineer at WebDevStudios, we were walking on a lot of headless WordPress projects with custom PHP WordPress themes.
This blog post is a summary of the approach we used, and more generally, a guide on how to embed Svelte apps inside monolithic PHP apps.
Why adding Svelte to my PHP codebase?
You might be wondering:
Why would I add Svelte to my PHP codebase? I can do everything with PHP.
What are the benefits of adding Svelte to my PHP codebase?
These are all legitimate questions. Let's try to answer them.
First, from my experience teams / people who go to using Svelte inside PHP codebases have one (or all) of these motivations:
For example, implementing complex interactions like drag-and-drop, infinite scroll, or live filtering/searching using vanilla PHP/JS often involves a lot of imperative DOM manipulation and "state juggling" between HTML, JS, and PHP.
With Svelte, the same features can be built in a declarative in a fraction of the code.
State management with global stores/contexts, custom events, lifecycle hooks, etc. also becomes much simpler compared to passing data back and forth between PHP controller logic. This makes it easier to build encapsulated, reusable components with managed internal state.
So for teams that need richer interactivity and state management, adding Svelte components can provide a big productivity boost compared to staying within PHP/JS. The components handle the complex UI code internally, while exposing a simple interface to the rest of the PHP app.
Practical example: building an interactive and filterable blog posts search component inside a PHP WordPress theme
Now that you've seen why you might want to add Svelte to your PHP codebase, let's see how to do it in practice. For this example, we will build a blog posts search component that will be embedded inside a PHP WordPress theme.
The idea is to be able to:
Fetch blog posts from the WordPress REST API inside the Svelte component
Filter the blog posts by category
Filter the blog posts by search query
Here is a demo video of the final result:
You can also check the theme code on GitHub here:
For this example, I'm going to use a "classic" (or PHP) WordPress theme, Twenty Twenty.
In order to not mess up with the theme architecture, I've created a new custom page template named "Svelte Posts Search".
Initially, it's just a replicate of the default
singular.php of Twenty Twenty that I'll later on update with my custom Svelte component code.
I'm also going to use TypeScript as much as possible (in my Svelte components).
I like and highly recommend using Svelte with TypeScript. The experience is really worth it, and the benefits in terms of developer experience and code maintainability are high.
I wrote a blog post about why I like using TypeScript with Svelte and SvelteKit here.
Let's start by installing the needed dependencies:
Now, we can go ahead and create our Rollup configuration file:
Note that here we are using the
.mjs extension for the Rollup file. This is because our
package.json doesn't contain a
"type": "module" .
Here is what's happening in the config:
We define the entry point of our Svelte app.
We define the output format
And we add the necessary plugins
Another nice addition to the project would be a minimal
tsconfig.json file for proper TypeScript support.
We are now ready to start writing Svelte code inside our WordPress theme.
Our first Svelte component
Svelte entry point
As you saw above, our Svelte code is going to be located in the
svelte folder at the root directory. Inside this folder, we have a
main.ts entry point.
What's happening here is quite simple. We are importing an
App.svelte component (we'll create this in the next step), and exporting the component, with the target being an element with the id
Add the target for the Svelte application in the template
This is actually an HTML element that we need to create in the PHP template (the custom WordPress template we created earlier), and on which the Svelte application is going to be hooked.
Here is the full code for the PHP template. Notice that we are creating an empty
div element with the
We can now update the theme
function.php to include the script.
Ideally, I would have done that in a WordPress child theme, but, for the sake of keeping this article simple, I will add it directly to the main theme functions.php.
Here, we are updating the initial
twentytwenty_register_scripts() function to enqueue the script, and then, we are using the
Create the Svelte component
The last step in the process is to create the
Quite simple right? Just a
h1 tag with a red font color and a
Fetching data from the WordPress REST API
The first step in creating our blog posts search component is to fetch the blog posts from the WordPress REST API. This is quite simple if you look at the documentation of the WordPress REST API.
Since we are using the browser fetch API, we need to make sure our component is mounted before fetching the data. This is why we are using the
onMount lifecycle hook. Doing that help us in two ways:
We can wrap the
onMountcallback in an
asyncfunction and use the
awaitkeyword to wait for the response.
We avoid potentials errors that could happen if we try to fetch the data before the component is mounted. See https://www.okupter.com/blog/sveltekit-document-is-not-defined and https://www.okupter.com/blog/sveltekit-window-is-not-defined for more details on this.
Once we have the data, we can use it in our component.
With this code, we are looping over the
filteredPosts array and displaying the title and the excerpt of each post.
Searching and filtering the posts
The next step is to add the search and filter functionality to our component. This is also quite simple with Svelte. We need a search input field, and we need to filter the posts array based on what's being typed.
Now, since we will make many operations on the
posts array, it's a good idea to create another variable that will be reactive to
posts and on which we will perform the filtering operations; while preserving the initial posts array.
A lot of things are happening here, but let's break it down:
The search input field is bound to the
searchPostsfunction on the
Every time this event is fired, we get the value of the input field, and we filter the
postsarray based on this value.
This will automatically update the markup and display the filtered posts.
Now, this implementation is very simple and works well since the data we are filtering on is already local. In case we need to fetch the data from an external API, we might need to use a more advanced technique like debouncing.
Filtering by category
Now, let's tackle the category filtering. This is a bit more complex than the search filtering because we need to fetch the categories from the WordPress REST API, and then, we need to filter the posts based on the selected category.
Here are the utilities functions that I've used to handle different parts of this:
getCategoryData()is a function that fetches a category from the WordPress REST API based on its ID.
getUniqueCategoriesFromPosts()returns an array of unique categories from an array of posts.
getCategoryCountInPosts()returns the number of posts that belong to a specific category.
Notices that here, although I could have directly used the posts array for the last two functions, I'm still passing it as an argument.
This is because I want to make sure that the functions are pure and don't mutate the posts array if they are used somewhere else in the component.
Also, this will make things easier in the future if we need to use these functions in another component.
Let's take a look at the markup for the filter:
Let's break down again what we are doing here:
We created a reactive
checkedCategoriesIdsarray that will hold the IDs of the selected categories.
We are using the
checkedCategoriesIdsarray to filter the
postsarray and display only the posts that belong to the selected categories. In case no category is selected, we display all the posts.
In the markup, we loop over the unique categories and display them as checkboxes. We also display the number of posts that belong to each category.
All the checkboxes are bound to the
checkedCategoriesIdsarray thanks to Svelte
And that's it! We now have a fully functional blog posts search component that we can embed inside our PHP WordPress theme.
In this post, we explored how to embed interactive Svelte components into a PHP codebase, using a WordPress theme as a practical example.
The key takeaways are:
For development, you can use a bundler like Rollup to watch your Svelte code and output browser-ready JS bundles.
Svelte components can fetch data from PHP APIs and integrate tightly with the backend, while keeping complex UI code encapsulated.
Features like declarative bindings, reactivity, and stores make it simple to build interactive interfaces that would require much more imperative code with PHP/JS.
Svelte is a great way to progressively modernize a PHP app, by gradually replacing PHP view code with reusable components.
Overall, adding Svelte allows you to leverage the benefits of a modern web framework incrementally, without needing to rewrite your entire app.
So if you have a PHP app and are looking to enhance the frontend with more interactivity and cleaner code, give Svelte a try! Start small, and you'll soon find places where it can really improve your development experience.