Page specific javascript files in Rails 3.1 - javascript

I've been doing research on this:
Using Rails 3.1, where do you put your "page specific" javascript code?
But I have yet to see a satisfactory answer, which also makes me question whether I'm doing something wrong.
Here's my mental model: for different views, I'm going to have different
$(document).ready(....)
blocks, that obviously reference elements that are very specific to that page. I don't want to pollute things by loading that code for every single page and somehow trying to figure out how to only execute it when on specific pages; that seems pretty ugly.
My intuition, admittedly not backed up by any preliminary experiments, is that the ideal thing would be to:
Load application wide code from application.js.
Load shared controller code from something like assets/controller_name/shared.js
Load view-specific code from something like assets/controller_name/show.js
Off the top of my head. The helper would, the first time it ran, check if the file exists and, if so, do a javascript_include for it.
Perhaps this has some performance issues compared to the "let's just wrap the whole thing up in a big sticky ball and send it all" approach, but seems like a better approach to compartmentalizing code.
However, as above, I get the feeling I'm missing something. Is $(document).ready on a per-page basis a bad idea? Should that just be in the template and call a page specific bit of JS from application.js? The linked article above comes to that conclusion, but I don't like the image I'm getting in my head of one huge $(document).ready riddled with if this, if that, if the other thing.

What you propose is sound, but not the rails 3.1 way.
They say to divide the JS into many files, but serve as a whole single piece to the user. This allows better performance and scalability, so is a good thing if the final big piece of mud is not so big. Really 3 http requests give worse performance than 1 http request.
So you have already dipartimentized your code, because you have different Coffeescript files, which have different scopes.
To load in your app, just standardize a way to initialize the single piece of code, like calling a "myapp.users.init()" method-.
You could even automatize that peace of code using an helper, so it will be transparent for the controller.

Background
(Why Use The Asset Pipeline At All?)
One of the basic premises behind the Rails asset pipeline is the idea that it is preferable to load all the JS and CSS for a site up front once, and then cache them indefinitely (at least until the site is updated). The Asset Pipeline allows you to do this relatively automatically while still organizing your JS and CSS src files in a logical fashion.
This of course carries an upfront load cost, at the promise of saving time on additional roundtrips loading individual files. If that premise doesn't sit well then the asset pipeline is probably not for you.
The Nut Of The Problem
Ok, so we want to combine all our JS into one file to load it more efficiently. Just because we are going to load all of our JS doesn't mean we want to run all of our JS.
In the reality of a complex webapp you will probably have lots of page specific functionality that you won't want to spend resources executing when the user is not viewing the corresponding page. What we need is a uniform strategy for executing only the portion of our big monolithic JS file that is applicable to the current page.
Convention To The Rescue
I'm not aware of an official Rails strategy to deal with this, but there are some great solutions that establish and then leverage a good convention (which makes things feel "railsy"). The general idea is to define all your page specific JS code into an object literal, and then run only the code relevant to the current page on load.
For the specifics great strategy on how to organize and conditionally execute your JS code, see the answer by #welldan97 on this question:
Using Rails 3.1, where do you put your "page specific" javascript code?
which in turn is based on this article by Jason Garber:
http://viget.com/inspire/extending-paul-irishs-comprehensive-dom-ready-execution

Related

Migrating Javascript from the database

I am working on an old enterprise solution with these properties:
The solution has a MVC web application
The solution has a WCF service layer
The solution has javascript in the database, in the form of functions in a database column
The web application retrieves said javascript through the service layer and plugs it into certain pages
My team cannot modify the web application, nor the service layer
My team must write javascript by inserting functions into said database columns
This architecture leads to:
A very inefficient development loop
Very poor source control
I'd like to propose a solution for them, how to upgrade this, but here's where I fall a bit short on experience. My suggestion would be:
Migrate the javascript from the database to javascript files
Make some sort of hook in the web application for other teams' javascript files
My questions are:
Has anyone had this kind of problem and how did they solve it?
Is there an effective way to do this kind of javascript migration into files? My idea would be to write a small console program to do the migration
How would they make a hook to import our javascript files? My idea is to make a script bundle with some naming convention, so we can add scripts without them needing to change their code. Are there problems with this approach?
Any kind of input would be invaluable.
Edit:
Additional explanation:
The mechanism maps the javascript function names to a certain DOM elements' event attributes and inlines the code right after the element
The functions are standalone functions, depending only on libraries already in the web application
The functions are grouped by a common form
So I suppose it would be better to group them into files bearing the form names.
If these are just simple, static function definitions being inlined into the web page, then I suppose it might be possible to serialize/aggregate them all into a giant file and run something like prettier on it to make it readable.
That wouldn't be ideal to gain traction in your proposed migration, though. If the code has any volume to it at all, it would be nice to give some structure and order to maintain it.
It's already kind of a huge assumption that this javascript is just pure functions without any complex dependencies on each other, but it's possible that these pieces of Javascript work in isolation already if they are being pulled out of a database. It's hard to know without knowing more context. It seems unlikely that your life will be that easy.
If you managed to extract this monolithic Javascript file, the easiest thing to do would be include it in a script tag for the entire site and be done with it. This could be a bad idea if the file is getting to the ~MB size and slows your initial page load time.
Then again, the point at which you have a bunch of functions in one file, you could probably do a lot there to optimize and reduce duplication of code.
This is still all conjecture because I don't know the mechanism by which your web application imports the javascript once it retrieves it from the database.

Does using more external files, opposed to cramming everything into one file, reduce run-time-efficiency?

I am relatively new to web design and the world of jquery, javascript and php. I guess this question would also suit css style sheets as well. Is it better to have everything stuffed into one "external document"? Or does this not affect the run time speeds?
Also to go along with this. Is it wrong, or less efficient, to use php in places where jquery / javascript could be implemented? Which of the two languages is generally faster?
The way you should look at it would be to load the minimum resources required initially which would be needed on page load, not everything. Make sure you group all of these resources together into a single file, and minify them.
Once your page is loaded, you can thereafter load other resources on demand. For e.g a modal, which does not need to be immediately visible can be loaded at a later point of time, when user does some action, and it needs to be shown. This is called lazy loading. But when you do load any module on demand, make sure you load all of its resources together and minified as well.
It's important to structure your code correctly and define the way you batch files together for concatenation and minification. It will help you save on performance by optimizing the number of calls made to the server.
About PHP and JavaScript, I would say in general JavaScript is faster than PHP, but it depends on your application, as one runs on the server and other on the client. So if you are doing too heavy and memory intensive operations, the browser might limit your capabilities. If that is not a problem, go ahead with JavaScript.
There's a lot of different factors that come into play here. Ultimately, it is better to call the least amount of resources possible to make the site run faster. Many sites that check page speed will dock points if you call a ton of resources. However, you don't want to go insane condensing and try to cram everything into a single file either... The best way to approach it is to use as few files as possible while maintaining a logical organization.
For example, maybe you're using a few different JS libraries... well merging those all into one would eventually get confusing and hard to update so it makes sense to keep them all separate. However, you can keep all your custom JS where you call those libraries in one separate file. This can even be applied to images. Let's say you're uploading 5 different social media icons and 5 different hover states for them. Well, instead of making the site call 10 different files, use a sprite and just call one.
You can also do things like use google's hosted libraries: https://developers.google.com/speed/libraries/ Many sites use these and therefore many users already have these resources cached which means they don't need to freshly load the libraries when visiting your site. It's very helpful for things like jQuery.
Another thing to keep in mind is minifying those files. Any library you use should have a minified version and you should use that as opposed to a full version. While you should keep unminified copies of your work around, whatever ends up on the live site should be minified to help with page speed. Here are a few resources for that: https://cssminifier.com/ https://javascript-minifier.com/ If you're using WP, there's tons of plugins out there that have similar functions like WP Fastest Cache.
You php/js/jquery question I can't really weigh in on too heavily. As mentioned, the base difference between php and JS ist whether the requests are client-side or server-side. Personally, I use whatever is prevalent in the project and whatever works best for your changes. For example, if you're working with variables and transferring data, PHP can be a really great

Improve AngularJS performance on multiple levels

I'm writing a complex, multi-component app using AngularJS. Currently, the main components are ready and I want to improve the performance of the app.
After a short investigation on the field, I found some very useful resources:
11 Tips to Improve AngularJS Performance
Improving AngularJS wep app performance example
AngularJS Performance in large applications
Anyway, I need some additional advises on a few topics:
1. Script and Services/Factories loading
currently, all scripts are loaded at the bottom of the <body></body> tag inside index.html. Therefore, when the user loads directly a ui-route or we simply reload given page, all the scripts are loaded again. I want to load the scripts only in states that use the given script.
Services/Factories/etc. are loaded the same way. This causes pages which do NOT need the given e.g. Service to load it and this is slowing the performance, because of the big data load. I need to initialize/load them only when they are needed in the current state.
2. Translation/Localization
I'm using Angular Translate - i18n Reference, but when I'm translating the page elements I must use e.g. <button>{{btnName | translate}}</button. This technique and the overall usage of filters is pointed as one of the biggest performance drawbacks. The page has a lot of elements so this really might slow the loading. Is there any better solution or any workaround?
3. Overall
I've read the multiple threads on ng-repeat and its track by feature, so I assume it done, but I'm still not 100% sure that I understand the $digest ($apply) cycles correctly.
I read some comments that we should "avoid bind anything directly to a function", but I don't quite get it.
Any additional comments or advises relative to AngularJS and its performance are welcome!
Thank you :)
Reading the above, it looks like you already tried to optimize AngularJS itself. However, there is no mention of optimizations on your build process. I guess it would be wise for you to investigate Grunt or Gulp. With these tools you can concatenate and minify all your JavaScript to a single minified file. This way you only have a one-time payload while initialising your site.
Check this https://medium.com/#dickeyxxx/best-practices-for-building-angular-js-apps-266c1a4a6917

What is the suggested way to use template in Chrome content scripts?

I use several templates in a Chrome content script for elements I'm adding to matched pages.
Currently I'm storing these templates as string in the script, but I wonder if there are better ways to do this.
tl;dr answer - Yes, you can store them in a <script type="text/html"> tags or load them dynamically through ajax. Examples here (from KnockoutJS) and here. Store them in a file with the proper extension and use an empty tag with an id X, then $("#X").load("/path/to/template", function() { renderX(); })
Long answer with insightful thoughts, keep reading...
Please make sure templates/views or related GUI components of your system are in separate files (Keep reading to know why)
As a front end engineer, I learned to keep layers as separate as possible; this helps your team to understand better your code and make it more maintainable. Separating your layers in modules and then assembling them through an "assembly" mechanism is probably one of the best practices in software engineering. Some of the benefits of this practice include:
Maintainability: Multiple developers can browse and edit single parts of your code in order to create a more robust piece of software.
Readability: With the amount of languages around, you can't expect everyone to understand all the syntax of these X or Y language; mixing languages in a single file is just one step to confusing your code reviewer and make him spend more time than needed.
Accessibility: Take for instance, html, jade, haml, smarty, twig, erb or other template files. Those files should always be named with the proper extension in order to help code editors and IDE's to syntax highlight. A developer should only need to glance a folder to know what those files are supposed to do. A script or bot can come up with important information from just an extension.
By keeping views in separate files, other coders can view them and understand an important layer of the system without needing to understand the entire application; even collaboration gets easier when the developer just need to review those specifics files. Through bashing or scripting, even large architectural systems with thousand of "views" like files can be filtered in order to output just what needs to be reviewed.
(By now I hope I convinced you into removing your string from your code and create a new file and it there, otherwise I really need to improve my writing skills)
So, after we have moved our template to an external file, what do we do next?
A word on Javascript and Chrome-Extensions
Javascript doesn't have a default templating feature (heck, it doesn't even have a modular one, although some smart people are working on it for the ECMAScript Ed. 6, yay!), which means that we need to use a templating library for that. Let's assume you are using Mustache, Underscore template of something alike and thus using its library to render it.
Most of those templating engines use the infamous eval, which can provide a vulnerability to your code, which Chrome Extensions dislike, a lot. The Chrome Extension Dev Team even enforced a new version of the manifest.json file in order to forbid eval, and gave developers the choice to use Sandboxing Pages in order to do so. Luckily for us, they decided to relax the policies a little bit and we can continue use it with a proper CSP definition in our manifest.json.
This means that we need to tackle two problems instead of only one: the "load the template" one and the "render the template in a way won't freak out the new incoming versions of CSP in case the Chrome Extension Dev team change their mind".
Load the template
Load the template, luckily, can be done through an XML HTTP Request through AJAX. Just point the url with the name of the file and you can receive the template as a string, which was probably your original set up. Here's an example that I do with KnokcoutJS:
$("#aiesecTemplate").load('js/libs/aiesec/aiesecTemplate.html', function() {
ko.applyBindings(AIESECViewModel);
});
The #aiesecTemplate is a <script type="text/html"> tag that the browser won't render as part of the DOM. You can use that with other template mechanisms in order to actually assemble your DOM. If you have already a solution for this, this is probably the end of the answer and you can move on with your life. If you are wondering how do we render the code from there, keep reading.
Render the template
The Chrome Dev team suggest us to Sandbox our rendering process due most templating engine libraries being non-CSP compliant (AngularJS being an exception). Here'an excerpt of the code from the Sandbox page.
iframe.contentWindow.postMessage(message, '*');
Where iframe is a specific DOM Iframe Element from the sandbox page with a src attribute of a page that has the templating engine; message has the string template previously loaded, so after posting the message a window.addEventListener for message inside the iframe can render it without a problem. More information about sandboxing eval can be read here
Conclusion
If you made it to here, awesome! My answers might not be that boring. As a last note, you might be thinking "What about AMD or RequireJS?"; to be honest I haven't tried them, but really smart people think that AMD is not the best approach. Loading through a XML HTTP Request might not be better, but in case you think it hits your performance (I have used it in my application and it doesn't) you can always use some Event Pages and Web Workers with that.

Best way to structure a multiple page application in Javascript

As an Actionscript programmer shifting to JS/jQuery I often have to author multipage apps targeted mainly to iOS and I'd like to know what is the best way to structure such apps.
Most of the time my apps are presentations, where each page has a different behavior (i.e., some popups on page1, a group of sliders on page2, some drag and drop action on page3... you get the picture), and more often than not I have to keep track of several variables across different pages.
Right now I handle it like this: I have a group of common functions in a script named my_app.js, while each page has its dedicated pageX.js script to account for its specific duties. I store persistent values through the storage.js library and somehow manage to stick it all together and make it work.
However I recognize that there may be a vast area for improvement to this approach, so I'd like to know how more seasoned developers deal with this situation.
Thanks a lot,
Goblin
What you've done seems OK for a smallish app, but as another answerer said, I'd look at an MVC architecture. I can heartily recommend backbone.js, it's pretty lightweight, and simple to use.
You could easily make a controller for each type of view that you need (e.g. sliderController, dragDropController, etc) and then if you needed to, subclass ('extend') these controllers to be platform specific (e.g. iPhoneSliderController, iPadSliderController, desktopSliderController, etc).
If I had more info about this app - like the data behind it, what the user is achieving by dragging/sliding - then I might be able to give a more specific layout for the models, views, and controllers you might want. But hopefully this is a good starting point, and if you take a look at the backbone.js documentation, it should give you a good idea if it's appropriate for your app.
The structure you have sounds sensible enough (common JS file complemented by page-specific JS files). It also sounds like you're onto the right lines with storage.
What I would do in your situation is focus on how your code is structured in terms of architecture. Chapter 6 of Stoyan Stefanov's Javascript Patterns (O'Reilly) would probably be quite enlightening.
I would also probably explore JS MVC implementations given your situation would lend itself well to this methodology (lots of views).
I realise this is only scattered thoughts, but hopefully it might give you some ideas.
Here is how I organize stuff
in /
modFOO.php
modBAR.php
in /js/
main.js
resourceloader.php //this is a resource loader, so I can load multiple JS in a single request
in /js/pages
modFOO.js
modBAR.js //javascript that for page modBAR
in /css/
main.css
resourceloadercss.php //this a resource loader, so I can load multiple CSS in a single request
in /css/pages/
modFOO.css
modBAR.css
With this setup I know exactly where to find stuff, and where to put stuff. And based on the filename, modepic.css, I know exactly where to put the file, and what is (the CSS file for modepic).

Categories

Resources