Pre-rendering single vue components not routes - javascript

I have been looking for a few hours for something that could help my problem, but as of now, I havent found it.
The problem is:
I am working on an PHP/Latte server-side rendered website, where I have decided to implement Vue. However, since there is no possibility for me to change this website into an SPA, I need to just create micro components with Vue and use them inside the BE templates.
By that I mean that there is a .latte template, where I insert a <My_component /> element, which gets rendered client side.
Which is fine for some components, but others, like the main menu, product or something else important for SEO purposes, needs to be somehow pre-rendered for crawlers.
By now I have read 10+ articles and watched 4 videos on prerender-spa-plugin, which I am sure is a great solution for SPAs, but I dont think it would work for my case. Especially since I am not using Vue router.
Nuxt.js also seems like not what I want and would be a bit of an overkill in my case.
Basically I just need a webpack or Node based plugin, that would take .vue files, that I would need to be pre-rendered, and create (build) the static HTML for them. Which would be either automatically or by hand inserted into the .latte template.
Has anyone had any experience with this?

Related

Templating and Components with HTML

Is this achievable without a framework like Angular/React?
Problem I'm running into is I'm creating a blog and I want to minimize the amount of code I'm using and there's two things I'm looking at:
Changing text on each file
For example, for each blog page, they share the same features such as: header, footer, logo, etc.
However, imagine my blog has 100 posts and now I want to change the text of a link in the footer. This would be applied to every page and instead of going to each page and changing the footer manually, I'd like to be able to change it in one file (i.e. footer.html or footer.json) and it's applied to all the pages. I discovered handlebars.js and unless I'm mistaken, I could use this to achieve this problem I'm facing.
Minimizing page bloat
However, I would like to minimize the page even more. As far as I understand, using something like handlebars wouldn't allow me to shorten the amount of HTML code itself. I'd like to have one blog-post-template.html file and each time the user clicks a link to a post, it would use the blog-post-template.html file and the only thing that would change is the actual blog-post.
For example, in pseudocode for blog-post-template.html:
{header} (gets this from header.html)
{blog-post} (gets this from link attribute and searches for that blog-post-number in database)
{footer} (gets this from footer.html)
I'm pretty sure I know the Angular way of doing this through templating and components but since I decided to create this blog with vanilla JavaScript and possibly jQuery plugins, but I was wondering if this was achievable without using a framework like Angular since I've heard about Angular and SEO not getting along well with each other.
Or if it's more advisable to use a tool like Angular/React to create something like this in my example.
You don't need a JavaScript framework, but you will need to use JavaScript.
You can have your header and footer hard-coded as HTML as you say. But then you'll need a JavaScript function to run and grab the blog post from your headless CRM or database.
I'd just recommend using something like Next.js so you can have the nice tooling of a framework, and no SEO downsides.
If you'd like an SEO-friendly version of React, you could use Next.js or Gatsby. Angular, I think, has ahead-of-time compilation that might do the trick. Or you could check out the html template element
Cheers :)

Integrating Play Framework and Twirl Templates with Webpack and React

I am currently migrating a Play Framework application with a view composed entirely of Twirl templates into one with a view composed of a mix of Twirl and React. I have written a PlayRunHook to integrate Webpack with Play's build process, and the result is JavaScript bundles whose names match what I have hardcoded in the new barebones Twirl templates.
So things look like this:
#(title: String)(implicit session: Session, staticAssetResolver: StaticAssetResolver)
#main(title) {
<input type="hidden" name="pageTitle" id="pageTitle" value="#title">
<div id="content">
</div>
<script language="JavaScript" src="#staticAssetResolver.asset("dist/profile.bundle.js")"></script>
}
The React code in the bundle knows to mount at the "content" div and receives props provided in the template.
This all works well, but I would like to avoid hardcoding the bundle name so that I can benefit from asset fingerprinting. This means figuring out a way to more tightly couple Webpack with Play's build process so that Webpack's output can be incorporated into the Twirl templates.
I have researched plugins, but what would you suggest for integrating Webpack and Twirl in this way?
This is probably not what you want to hear - I too messed around with trying to figure out how to embed interactivity in Twirl... but in the ended I concluded it was a back idea to mix javascript and twirl, ended up doing this;
https://blog.usejournal.com/react-with-play-framework-2-6-x-a6e15c0b7bd
It could be that I'm simply not familiar enough with Twirl, but after wrestling for quite a while, I found that simply "changing worlds" into react, and having it talk to the backend via
fetch(/api/myRoute)
was quite productive. In conjunction with React Router I found myself very happy with the productivity, performance and outcome. I spent little time on "custom" build work, outside of copy and paste from that blog, so was able to concentrate on what I wanted.
I would also say that I am not skilful enough, and did not have time to start writing custom "RunHooks"... so that may also be the problem!
The above link worked well for me... with the only downside being that when changing routes one gets no tool support... so it is manual and risky to change a backend route or method signature. Probably not great for a big app... but for my small set of requirements was an effective strategy.

Using CSS/JS/jQuery Theme with Vue.js

I am currently writing a small static site, and I have decided to use Vue.js as I have used it in the past without major issues. This time, I have to use a pre-made template which is jQuery/Bootstrap based and most of the heavy lifting is done through JS.
I am trying to use the Porto template. I have been able to convert the basics (CSS, add the router, etc) but I am struggling with the JS side of things. From what I have been able to understand, the different "components" that come from the template are activated once the entire page has been loaded. The init script goes through the HTML DOM and "activates" them.
Usually this works fine, especially when using an old jQuery style approach, but due to Vue's lifecycle for components, the JS is not re-executed once a new component appears on the page, therefore making it look like it does not work.
The most logical approach would be to take each Porto component, and splitting it out into Vue components, with their own JS, etc. But this means that any update to the template would require a full rewrite, without forgetting the amount of work to create the first version.
Currently, I have tried wrapping the <script> imports in a component, and inserting it into the page. My idea was to then use the this.$forceUpdate() method to force a re-render, but it fails.
Any other ideas?

Independent VueJS components with webpack?

I made some SPA using vuejs-templates/webpack and that's ok. But now I am developing a website, almost everything is static, so there's no need to be a SPA. I already made the pure html/css layout.
Now I will make some pages with forms and dynamic content, I would like to use vue components inside these pages.
Tell me which of this ideas is the best or give me a better option:
Multiple entries in webpack: I don't know very well how to do it, but I guess I can create a webpack project by scratch and render multiple entries that I include in the pages I want.
Use browserify: I didn't want to do this, but sounds like a good option... I could use vueify to render *.vue components
Use Nuxt: I never tried, but seems a good option too, I could make a "SPA" with SSR.
Tell me if you have another idea.
Thank you
Don't rule out just referencing Vue as a script file. No bundle, no compilation step. You lose single file components, but you can get something very like them by using js template literals. If your needs are simple and you don't want to impact on the rest of the site, this could be a fine solution.

Very large single page application design problems

I am currently writing whats going to be a very, very large single page web/javascript application.
Technologies I am using are ASP.NET MVC4, jquery, knockout.js and amplify.js.
The problem I am having is that most if not all of the single page application examples are for smaller applications where having all of the script templates (be it jquery, handlbars, etc...) are all in the same file along with the rest of the html code. This is fine for smaller apps but the application I am building is an entire maintenance logistics application with many, many, many screens.
The approach I took so far is I have an outer shell (my main index.cshtml file) and I am using jquery's load() method to load or rather inject the particular file I need when a user makes a certain selection.
example:
function handleLoginClick(){
App.mainContentContainer.delegate('#btnLogin', 'click', function() {
App.loadModule('Home/ProductionControlMenu', App.MainMenuView.render());
});
}
here's the code for the App.loadModule function:
App.loadModule = function(path, callback){
App.mainContentContainer.load(App.siteRoot + path, callback);
};
All was going well until I needed to actually start interacting with the various form elements on the newly loaded screen. jquery can't seem to get a handle on them directly. I can't use .live() or .delegate() because they aren't events, they are textboxes and buttons and sometimes I need to change their css classes.
They only way I found is to get a handle on an element from the outer shell (something that wasn't loaded via .load() ) and use jquery's .find() method like so:
App.mainContentContainer.find('#btnLogin').addClass('disabled');
clearly I don't want to have to do something like this everytime I need to interact with or even retrieve values from a form element.
Does anybody have any ideas as to how I can create a maintainable very large single page application with potentially hundreds of .html files without having to have all that html code located in a single file and still get around this .load() issue I am having?
Any thoughts would be greatly appreciated. :-)
V/R
Chris
UPDATE
I thought I'd post an update and as to how things went and what worked. After much research I decided to go with Google's AngularJS Javascript framework. It simplified the ordeal exponentially and I would definitely, definitely advise all who are looking into making a large SPA to give it a look.
Links:
Main Site
http://angularjs.org/
Awesome free short videos on Angular:
http://www.egghead.io/
This is actually a very complicated question as it really gets down to the design of your architecture.
For large-scale single-page applications, it's best to use some sort of front-end MV* style framework such as backbone.js, which ties in to jQuery quite usefully. You should also think about using some sort of dependency management framework such as require.js in order to load your scripts and dependencies asynchronously, and even better -- use the AMD pattern in your application design to make your architecture modular and easier to manage.
As far as how this relates to your MVC4 project, you have some options:
Do you want to use MVC as a "service layer" of sorts, that simply returns JSON objects, allowing your front-end to do the markup/template creation (think handlebars.js), or
Do you want your MVC project to return partial views (HTML) as a response, where you leverage the Razor templating system and simply use the front end to display what comes back from the server?
Either way, you will have to devise a way to handle front-end events and navigation (backbone provides both of these things when coupled with jQuery). Even more complicated is the pattern you choose to notify one view of another view's activities (there are many ways to do this) -- a publish/subscribe pattern for example.
I hope I have helped a bit, I know I'm not fully answering the question, but the answer could get really long!
Lots of things are wrong with your approach. What I'd recommend is to watch some presentations on how people build Single Page Applications and what tooling is mostly used.
This seems like something reasonable: http://singlepageappbook.com/
You will at least want
some kind of modules system (I recommend AMD – http://requirejs.org)
an MV* framework (Backbone, Ember.js etc.)
DOM/AJAX Framework (jQuery, Mootools etc.). Some frameworks offer this and all of the above (Dojo, YUI, Sencha)
build solution (to have different environment in development / production)
Couple of good links:
http://nerds.airbnb.com/slides-and-video-from-spike-brehms-tech-talk
http://video.copenhagenjs.dk/video/3413395/simon-hjberg-swipely-building
http://backstage.soundcloud.com/2012/06/building-the-next-soundcloud/
http://www.youtube.com/watch?v=vXjVFPosQHw
If you don't need a complicated truly SOFEA Single Page App then I recommend you go the PJAX route.
Then you just write your app as a normal web 1.0 app with the performance benefits of a single page load. I urge you to consider this an option as it allows you to do most of your validation work server side.
The idea is very simple on every response your sending the whole page back minus the header and footer (which contains the javascript and css includes). DOM rendering time is incredible fast these days... whats not is a full page reload, So don't worry about the size of the HTML your returning back.
Also the "PJAX way" is much easier to cache, Google SEO friendly and is in fact what the new Basecamp does.
Note: Wanted this to be a comment not an answer but don't have enough exp to post comments ;(
[any corrections by community members welcome!]
Important points to consider for single page apps:
Lazy loading is vital as you don't want hundreds of js files loaded straight away as user first loads the page (very slow load time).
Good File organisation,- helps making changes easier, reduces complexity a bit and promotes reusable components. Makes testing of components easier.
Testing,- Since single page apps have a lot of javascript going on under the hood you would need a test framework for automatically testing components. This testing is on top of the tests you would use to confirm if certain user controls are rendered etc as you wouldn't want a viewless component making an ajax call to server when it shouldn't etc.
+1 for gryzzly's point about using a framework.
Sencha have a nice MVC like framework for their ExtJs product. They have data stores, ajax, lazy loading, class hierarchies and a lot more all bundled into the package. They have a good api page also to lookup object properties and methods (handy since there doesn't seem to be any intellisense for javascript :/ ). Their api page is; as far as I know, an example of a single page app. I know much of the stuff ExtJs does you can find an open source alternative but I like that it's just the one library and I don't have to download a couple of different frameworks to do various operations. [note: I have no affiliation to Sencha except for being a customer of theirs and like their stuff.]
Conclusion:
I'd say it would be quite difficult to manage a large single page app without using some client side framework; whether open source or not, and without using some architectural pattern like a client side MVC.
Single page apps I think are more complicated so your team would need to be quite handy at understanding the concept of a single page app and how to implement it. If you pull it off the site will be amazing in terms of user experience.
I would recommend to use Sammy.js and split various viewmodels in knockout to a separate url. And if you're using asp.net mvc 4, use partial views (user controls) so that you put all code in one file. And name all and split all js-code in a meaningful way, filename and namespace in js. That will help a lot in maintainability and your own sanity in the long run.
And use common sense!
The way I did it was to include javascript code related to the template along with the template itself. And then load the whole template+script thing using ajax. If you want to try this be warned that most browsers don't execute <script> tags injected into the page. Especially if done using innerHTML. As such you should eval the script tags yourself (alternatively you can use document.createElement to inject the script but this does not offer any additional advantages compared to eval since the browser will blindly execute the script anyway).
In my case, to make it easier to grab the html and script portions of the template I store my templates in XML files instead of plain old HTML. That way I can simply use .responseXML of the ajax request to parse the template. My template has the following basic structure:
<template options...>
<title>Optional</title>
<html><![CDATA[
Template body
]]></html>
<init><![CDATA[
// code that only needs to execute once
]]></init>
<script><![CDATA[
// code that needs to run every time
// the template loads
]]></script>
</template>
You also need to remember to configure your server to reply with the correct content type for you templates. Otherwise resultXML won't work. This is not the only way to implement this system of course. You could simply save your templates as HTML and then parse that HTML to extract scripts to execute.
The main bulk of your code, the functions, constructors, objects etc. can be included in a js file. The template script only need to call those functions to tell the rest of the page how to work with the template.
If you further separate your data from your template and only populate the template with data on the page or make a separate ajax request for JSON data then you can configure your server to make the browser cache your templates. This is especially useful for often used templates (such as templates for dialog boxes). This allows the browser to download the template only once and use the cached version the next time you call the template.
Anyway, that's how I did it last time. It scaled well enough to serve facebook users (the web app was a facebook app). Just sharing my experience. Hope it helps.
I've written a few huge single page application using Dojo Toolkit. I'm pretty sure whatever JavaScript framework you choose will probably work for you. I use Dojo because it provides me with features that makes huge single page application development easier to manage.
You can use Dojo's widget system to help you define all your screens and forms as widgets and then when you need them you can just instantiate and insert them wherever you need it. When ever you want to get rid of it, you can simply call destroy or destroyRecursive on that particular widget and its gone. Dojo's widget system also help you separate your HTML from your JavaScript, but still keep it together so that they are not located all over the place.
I've include a simple widget definition for a Login form.
This is the HTML template.
/* mine/forms/Login.html */
<div>
${form_name}
<label>Username</label>
<input data-dojo-type="dijit.form.TextBox"
data-dojo-attach-point="_usrfld" />
<br />
<label>Password</label>
<input data-dojo-type="dijit.form.TextBox"
data-dojo-props="type: 'password'"
data-dojo-attach-point="_pwdfld" />
<br />
<input data-dojo-type="dijit.form.Button"
data-dojo-props="label: 'Login'"
data-dojo-attach-event="onClick:_handleLogin" />
</div>
This is the JavaScript portion for the widget.
/* mine/forms/Login.js */
define([
"dojo/_base/declare",
"dijit/_Widget",
"dijit/_Templated",
"dijit/_WidgetsInTemplateMixin",
"dijit/form/Button",
"dijit/form/TextBox",
"dojo/text!./Login.html"
], function(
declare,
_Widget,
_Templated,
_WidgetsInTemplateMixin,
Button,
TextBox,
template
) {
return declare("mine.forms.Login", [_Widget, _Templated, _WidgetsInTemplateMixin], {
// assign the template
templateString: template,
// signal that we will have widgets within our template and the parser should
// locate them and instantiate them
widgetsInTemplate: true,
form_name: "My Login Form",
// place holders that will be referencing the corresponding widgets
// that I have placed a data-dojo-attach-point on
_usrfld: null,
_pwdfld: null,
_lgbtn: null,
// a call back function that will be trigger when the Login button is clicked
_handleLogin: function() {
var usr = this._usrfld.get('value');
var pwd = this._pwdfld.get('value');
// now you have the username & password
// you can use it to login
}
});
});
There are a few benefits that the widget system provides:
The HTML template will be loaded for you when needed
You can have widgets within widgets. Dojo takes care of instantiating and even destroying those widgets for you
You can use dojo's simple template language to help with inserting strings. The example above uses ${form_name}. If you want to use a more sophisticate facility dojo also supports a Django similar syntax templating language. This will allow you to use most of the tags available with Django like for, if-then-else, etc.
data-dojo-attach-point is very helpful. If you use this, you will never need to assign id to a DOM element anymore. You will not need to locate the element in your HTML DOM tree. The variable you name in data-dojo-attach-point will be auto assign to reference the widget or DOM element you have defined in your template. The example above uses the _usrfld, _pwdfld, and _lgbtn.
data-dojo-attach-event is also very helpful. If you use this, you will not have to manully add an event hook to the button, Dojo's widget system will hook it for you and will also clear the hook when your widget is destroyed.
If you use Dojo's build system, which is a system that takes all your JavaScript codes and compresses them, Dojo will replace your template with the actual HTML so that when you load your widget in production mode, Dojo doesn't have to make another AJAX request to grab your template.
These are just some of the features I use daily when I develop my projects. Hopefully it will provide you with some insight that you can use to make your decision when choosing the proper JavaScript framework for your project. As a side note, I'm not advocating Dojo or anything, just wanted to share what works for me.
To handle large size single page application it's recommended to break the individual module into different apps.
example : apps like search page app and result page app.

Categories

Resources