3

I'm attempting to use Vue at my company. Currently we are not using any Javascript Build tools like Webpack. That means no Babel, (Babel-Standalone also not an option). No Babel means no Template Literals (``), which makes defining Components in purely Javascript files a pain (Internet Explorer does not support Template Literals, and to define Templates in Javascript in clean multiline code, you need Template Literals, and we need IE support). My team has agreed to move towards Laravel and Vue in the near future, but we are working through a server migration and code update before we will be able to properly use Vue.

So I thought I would try to mimic the .vue layout as much as possible. First I create the component in a PHP or HTML file, defining the template in an X-Template along with the Vue component instantiation and styling. In my PHP controller/class/etc. I require the file and it renders in the DOM. This solution works but I have a couple questions.

  • Are there any unforeseen issues?
  • Is there a way to include the content of these .php/HTML files as Sources rather than being rendered in the DOM?

Example

// MyComponent.php or MyComponent.html

<script type="text/x-template" id="my-component-template">
    // component template definition
</script>

<script>
    Vue.component('myComponent', {
        template: '#my-component-template',
        // component vue data/methods/etc
    });
</script>

<style>
    // component styling
</style>

-

// MyPhpClass.php

public function includeComponents() {
    include('path/to/MyComponent.php');
}

-

I've researched quite a bit on using Vue without bundlers. Here's a few of the helpful threads.

jarrodized
  • 31
  • 2
  • 1
    1. Some features require Webpack .vue format loader, scoped styles come to mind. 2. This requires Vue SSR, i.e. Node.js web server that evaluates JS code and renders it to HTML output, you can use external prerendering service. – Estus Flask Jan 22 '20 at 20:41
  • If you are using Vue3, take a look at https://github.com/FranckFreiburger/vue3-sfc-loader it has a better support of external libraries – Franck Freiburger Dec 08 '20 at 07:49

2 Answers2

1

The approach you have taken will work fine but lacks of course the simplicity and functionality given when working in *.vue files in webpack. I recently had a similar use case come up to me in a personal project and to that end I solved it in PHP with a few composer dependencies.

I am linking to the repository here on GitHub.

The included class exposes a render function that accepts an array of file paths to however many *.vue files you wish to parse. It will process them and convert them to batched <script> and <style> tags. The generated script code should be IE 9+ compliant. There are also getScripts and getStyles functions to retrieve the codes directly if you wanted to pipe them into a external source file for loading through HTML.

Primary differences between your approach center around the handling of functional templates and scoped styles, both of which are supported in this solution. There is also a bit of additional overhead incurred which in my case was acceptable, but could possibly be mitigated through the use of those two additional methods above and caching the results.

A basic use case could be something like:

<?php
    $vueFiles = glob(__DIR__ . '/vue-components/*.vue');
    // Output scripts before browser gets to custom elements
    // because IE crashes if it's not registered first
    VueLoader::render($vueFiles, '#vue-app');
?>

<div id="vue-app">
    <my-custom-component></my-custom-component>
</div>
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
0

I have run into this problem as well and concluded: Vue does not provide us a convenient way of packing multiple components inside html. If it did, our php problem would not exist, we could just concatenate some vue files and get on with our business.

What if you could write something like this:

<template component="my-component">
  <div>
    <!-- template html here -->
  </div>
  <style scoped>
    <!-- style here -->
  </style>
  <script>
    // vue component definition here.
    export default {
      data(){ 
        return {
          variable: 'my value'
        }
      }
    }
  </script>
</template>

Now the entire component is contained within a template element. These template elements can be extracted and rebuild on the client.

To spare you the trouble of having to reinvent this wheel, you may use vue-blocks. It's a layer on top of Vue/VueRouter that extracts these components from the available html and registers them.

Joshua Angnoe
  • 1,010
  • 4
  • 11