How to: embed a Svelte app within a PHP application, with Live Reload
Tags: svelte, php, tutorial, javascript
Published: 2020-06-26 18:52:32

Woah it's my first DEV article! 

Alright, so at my day job I inherited a system built on PHP. The DOM is almost completely rendered in PHP which annoys the hell out of me -- I've been dreaming sweet thoughts of Svelte. 

Wanting to make the switch, I often thought about redoing the whole system using ``fetch()`` requests in Svelte with a request-response scheme in PHP, but there's so much code that a Big Bang-style switch isn't feasible. Therefore, I needed to plant a seed that would eventually grow into something large and beautiful (perhaps a tea tree, or a napa cabbage).

So this morning I decided fuck it, it's time to put Svelte's clean little hands on some PHP-rendered DOM. And spoiler: it's pretty painless.

## Slap in Svelte

You've first got to choose a sub-project to use Svelte on within your existing PHP project.

Navigate to that directory of your existing project in the terminal and drop in our old friend: 

```bash
 > npx degit sveltejs/template svelte
 > cd svelte
 > npm install
```
Here's what my project directory looks like:

!['svelte' project folder below a folder containing 'index.php'](https://dev-to-uploads.s3.amazonaws.com/i/yrzg7z3zun9qidujcw2a.png)

Now let's tie 'em together! Pop into ``index.php``, and add a point of entry. I chose:

```php
<div id="svelte-app"></div>
```
On the Svelte end, match this entry point as your target in ``main.js``:

```js
import App from './App.svelte';

const app = new App({
  target: document.getElementById('svelte-app'),
  props: {
    name: 'world',
  },
});

export default app;
```

Now we essentially have to recreate the core parts of
``svelte/public/index.html``.

We're going to link the Svelte-generated script and stylesheets. This part can be done two ways depending on your existing PHP project. If you have direct access to the ``html head``, then just copy and paste the ``link`` and ``script`` elements from the ``head`` of ``index.html`` to the PHP file's ``head``, with path adjustments to reach the same files they reference.

In my case, I don't have a direct access method to augment scripts/stylesheets to the ``head`` in this PHP project. While I could make a method for that, I kinda just felt like doing it in Javascript. So I added this into the PHP file:

```php
<script>
    const svelte_script = document.createElement('script');
    svelte_script.type = 'text/javascript';
    svelte_script.defer = true;
    svelte_script.src = '../svelte/public/build/bundle.js';
    document.head.appendChild(svelte_script);

    const svelte_global_stylesheet = document.createElement('link');
    svelte_global_stylesheet.rel = 'stylesheet';
    svelte_global_stylesheet.href = '../svelte/public/global.css';
    document.head.appendChild(svelte_global_stylesheet);

    const svelte_compiled_stylesheet = document.createElement('link');
    svelte_compiled_stylesheet.rel = 'stylesheet';
    svelte_compiled_stylesheet.href = '../svelte/public/build/bundle.css';
    document.head.appendChild(svelte_compiled_stylesheet);
</script>
```

Do whichever floats your pontoon, until someone argues below that the Javascript way is perhaps less efficient and makes us all feel bad for doing something that feels cool.

Now this will work if you do ``npm run build`` from the ``svelte`` folder with MAMP or whatever Apache server you have running for the PHP part, but dammit we want live-reload and automation!

## Live Reload

This is the perfect point to add live-reload to your PHP server if you haven't already. If you're using VSCode, add [Live Server](https://github.com/ziishaned/livereload-vscode) and its [browser extension](https://github.com/ritwickdey/live-server-web-extension). 

Configure the browser extension with the virtual host name set in, say, MAMP as the actual server address. Then the server that this plugin runs, usually http://127.0.0.1:5500/:

![Live Server browser extension visual](https://dev-to-uploads.s3.amazonaws.com/i/aj3zqjqkipuf190e12pv.png)

Follow the plugin's guide, hit Go Live in index.php and you should be PHP-live-reloading. But maybe wait to test this until after the next step so to avoid some Node server-Apache server fighting if you've got Svelte's localhost running too.

We only need Rollup in Svelte to be responsible for watching Svelte file changes and compiling those changes. To make this happen, we can delete the following lines from the ``rollup.config.js``:

```js
// In dev mode, call `npm run start` once
// the bundle has been generated
!production && serve(),
```

Now, with your terminal still in the ``svelte`` directory, you can run the familiar

```bash
> npm run dev
```
Now Rollup will notice changes to your Svelte files, and auto-recompile like normal. Live Server will then notice a change to the compiled Svelte files referenced in your PHP application and reload your PHP page in the browser automatically!

You can get rid of ``favicon.png`` and ``index.html`` from the Svelte ``public`` folder, too.

Look at that!

![Svelte app embedded in a PHP app!](https://dev-to-uploads.s3.amazonaws.com/i/grs0732c1haice3k8vf2.png)

There's a whole number of ways to pass data between your PHP backend and Svelte interface, so I might turn this into a series the more I dive into the possibilities!