2

I have a legacy PHP app which I would like to slowly migrate to Vue. The PHP app renders a bunch of HTML and javascript files in quite a tangled fashion, i.e.

foo.js.php
...
<script src="mysite.com/some_js_file.js" />
...
const a = '<?=$variable_from_php?>';

so in the end, the browser obviously doesn't know how the js files are constructed, but can run them. What I'd like to do is from the outer layer Vue app, request the index page for a certain sub-section of the legacy app, and render that to a Vue node, as a micro-frontend of sorts. When I request each index, it will of course, contain a header with numerous other imports (scripts/styles) that that micro-frontend needs to function. So, two parts to this question: 1) what would be the best (or maybe least terrible) way to do this in Vue. Using v-html? iframe? (please say no iframes) And 2) will there be any showstopper security problems with this approach (since I'm basically saying fetch all the JS in the header and run it). Let me know if this question makes sense. Thanks!

6
  • 1
    It's maybe possible to use H-include or web components (like micro-frontends.org)? Commented May 7, 2021 at 14:08
  • Are you trying to render dynamically generated HTML from PHP as a Vue template? Or do you want to have new Vue content next to the existing PHP generated content? Commented May 10, 2021 at 21:39
  • @ssc-hrep3 The first one, dynamically generated HTML from PHP. However as far as a migration is concerned, I want to essentially just blindly set a Vue component's content to be this HTML, and then not bother with it any more, since it can entirely manage itself. Commented May 11, 2021 at 11:42
  • 1
    There's no good resolution for this. Scripts aren't handled by v-html, innerHTML, or similar. Their elements should be created explicitly with document.createElement("script"). This is supported by jQuery html out of the box, use it if necessary. Even if scripts are handled, they won't be evaluated in the same order as in original page because they are loaded asynchronously this way. And even if it's workable, Vue app shouldn't be SPA because you won't be able to do a proper clean up between pages, there will be bugs and memory leaks. Commented May 12, 2021 at 9:14
  • 1
    The security is determined by legacy app. The result cannot be less vurnerable than it but can be more vulnerable, depending on how new app can be exploited with these hacks. iframe is the only straightforward way here, both in terms of security and common sense. Commented May 12, 2021 at 9:19

2 Answers 2

0

Maybe you need like to : a module php or component as template.php(php server)

    export const templateOfAdvanceTemplatePage = `
  <div class="content edit-page management">
    <md-card class="page-card">
     <?php echo "My Component" ?>
    </md-card>
  </div>

And from node server

     import * as url from "url";

var templateOfAdvanceTemplatePage = url.parse("http://www.website.com/template.php");
    
    export default {
      template: templateOfAdvanceTemplatePage,
      ...
    }

for more information import vue here, and php as javascript file here

Sign up to request clarification or add additional context in comments.

1 Comment

0

Vue.js can be used in two separate ways: For more complex applications you would use a build process and pre-compile the templates from the source, which are usually Single File Components SFC; *.vue files. The templates would then become render functions and no HTML is ending up in the output assets. There is, however, another way of defining Vue components. You can define them inline with the runtime-only bundle of Vue. For migrations and smaller applications this approach would be advised. You would need to include the compiler. See also the Vue documentation about that topic Vue v2 and Vue v3). If you are importing Vue as a module and are missing the compiler, see here.

If you want to render dynamically generated HTML from PHP as a Vue template, you would need the second approach. Keep in mind that, with this approach, you would always need to have the generated PHP output to be in sync with the Vue components. And you would need to fully trust the HTML, you are generating with PHP, otherwise you will risk injections.

There is, however, still another problem: You need the generated PHP output HTML as a string within JavaScript and it should not be interpreted by the browser (ideally) or removed again from the DOM. So, you need to decide (based on your project) how you want to generate the HTML so that it can be read in as a JavaScript string. Here are some approaches:

  1. Generate the HTML directly into the page. Then, define which element you want to target, get the HTML with .innerHTML and delete the node from HTML (drawback: you will render the HTML twice, might produce short visual glitches).
  2. Fetch the HTML via XHR from a separate page. You will directly have the HTML as a string in the response (see e.g. fetch).
  3. Render <script type="text/x-template" id="static-html-content"></script> around the generated HTML content. Then, you do not need the HTML as string and you can directly use the id as reference (use template: '#static-html-content'). See the documentation of X-Templates in Vue.

Then, you can use the runtime-only version of Vue and define your components. Here is a live example:

const Counter = {
  // retrieve and add your template string here
  template: `
  <div class="counter">
    This is a counter: {{ counter }}
    <button @click="counter++">Increase Counter</button>
  </div>
  `,
  data: function() {
    return {
      counter: 0
    }
  }
};

const App = {
  components: { Counter },
  template: `
    <div class="app">
      This is the app component.
      <hr />
      <counter />
    </div>
  `
};

new Vue({
  el: '#element',
  template: '<App />',
  components: { App }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="element"></div>


Another approach would be to just render the HTML string within a component with the v-html attribute. The main drawback of this solution is, however, that the content is then not reactive. You cannot change your internal component data and expect the template to react to the changes. Therefore, you are missing out on the main benefits of Vue, but you are not restricted to a template which matches your components internal structure.


A similar question was also posed in the Vue forum: link

1 Comment

This is a good explanation regarding server rendered templates but it doesn't address the main point of the question, how scripts in these templates can be handled.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.