Best-practice for javascript configuration on new web project - javascript

I would like to ask a question about a new and large scale web project's javascript requirements. We will use lot of javascript, ajax requests, jquery, json objects & jquery plugins in our project. We planning to store global variables and lot of default values in a global site configuration file with php class and ini file on server-side.
But we need to read, use and sometimes override some variables and configuration values on client-side with javascript - jquery.
This javascript based configuration file must have following properties;
Won't have all server-side config values. Only we need.
Must be a single file that will be call on html head section.
Must define a global variable or json or javasctipt object or array (I don't know which is best)
This values must reachable by other javascript functions and objects.
Will store booleans, strings, integers maybe a some little initialization methods for 5-6 different pages (ex.: we don't need main page's config values on product detail page's and we don't need product detail page's some initialization methods and values on main page etc.)
We need to reach some values of this configuration object on every page like debugMode=true or false etc..
We need to know in other javascript objects to running platform via this config file for images and other resource paths (Developer-Test-Stage-Production)
Also we can completely generate this file on server side or generate a static .js file and after a PHP request, set some user-page-specific or language specific values, than we must be put (override) some of this server-side generated values in Js object.
What is best-practices for this solution? Any suggestions?

Must define a global variable or json
or javasctipt object or array (I don't
know which is best)
JSON is basically an object literal, so it can do both. Go for it. Think of JSON as a serialized javascript object.
This values must
reachable by other javascript
functions and objects.
As soon as you run the JSON it will be available in your code.
Will store
booleans, strings, integers maybe a
some little initialization methods for
5-6 different pages (ex.: we don't
need main page's config values on
product detail page's and we don't
need product detail page's some
initialization methods and values on
main page etc.)
Again, JSON can do all of that.
So I would suggest a JSON file, that is included via script tag on the client side. JSON is easy to generate, read and manipulate on the server side (eg.: json_encode, json_decode in php).
It SHOULD BE a static js file, as it stresses the server the least. Also, Gzip compression can help to keep the bandwidth cost low.

Related

How can I generate and serve dynamic .js files with a Node.js-server which deliver useable functions to the client?

The content of the .js file is different depending on the settings on the server and the variables provided by the client(s).
I have managed to send a dynamically generated string as a file using Express' res.type(".js") and res.send(file_as_string). I create this string by appending a stringified object behind "var name_of_an_object = " using JSON.stringify().
This works in most cases, but not for functions. Functions, whether within an object or not, magically morph into {} (empty objects). I just need a way to make the functions into strings that are immediately readable by the client when it has loaded the .js file.
Since I get a feeling there has to be a more robust way of doing this, I would love to know about it. If there isn't, I would like to know as well. Andy ideas?
I thank you in advance.

Creating and minifying JavaScript dynamically in ASP.NET MVC server-side code

I am using a ASP.NET route (to intercept the call to the .js) and controller to generate some JS I want to use on my client. The reason I'm doing this is so as to not have to duplicate id's or constants on the client. Here's the output of my JS:
app.serviceRootURL = 'http://localhost:65211/'; // set in my web.config
app.ajaxResponseStatuses = [
{ "status":"Success", "id":0 }, // set in my C# DTO
{ "status":"Failure", "id":1 },
];
First of all, I am not sure if this is the best approach, so other suggestions to doing this would be beneficial.
More importantly though, I'm wondering how I can bundle and minify this. As I understand it, even if I could minify the JS at compile or run-time, minification will change the names of my variables. So in the above JS, app.ajaxResponseStatuses could get changed to a.bc, and then in the actual JS files where I'm trying to access that variable, they could be looking for x.yz.
Can I minify this code and get it to the server?
Will I still be able to use the above properties in other minified files?
(bonus points) Is this a good aproach to pass server-side-only values to be used on the client?
Part 1
If you are generating the js at runtime, bundling isn't possible (at least not efficiently). You would have to create a new bundle for every request which isn't terribly quick. Plus, you wouldn't be able to cache the regular, constant script bundle.
EDIT: While bundling server-generated js isn't practical, rendering the values into a script tag in the page can achieve the same benefit of bundling, fewer HTTP calls. See the edit in Part 3 for more.
Minifying the server generated js however, is totally possible. This question should have the answer you're looking for. However, I'd recommend you cache this on the server if possible, as the minification process itself could take longer than simply sending down the extra bits.
Part 2
In most minifiers, global variables (those accessible on the window object) are skipped during the name mangling. With the same respect, variables that are accessed in other files that are not defined within that file are not renamed.
For example, if you have the following file...
// outside of a closure, so globally accessible
var foo = 1;
function bar() {
// within a closure, and defined with `var`, not globally accessible
var bar;
// reference to variable declared in another file
baz = null;
}
it would be minified as follows (with whitespace included for readability
var foo = 1;
function bar() {
var b;
baz = null;
}
This is one reason it is important to always declare your variables using the var keyword, otherwise they are assumed to be references to global variables and will not be minified.
Also, JSON (not Javascript object literals!!!) will never be distorted by minifiers, because it consists of string literals for all keys, and all values that aren't of another literal type.
Part 3
Not a bad way, and at my job we do use this approach. For small files though, or simple config values, we have transitioned to rendering server values in a script tag using ASP.NET in the actual view. i.e.
Default.aspx
<script> window.globals = <%= JsonConvert.SerializeObject(new AppGlobals(currentUser)) %>; </script>
We rip this out into a code behind, but the premise is the same.
EDIT:
Server-Generated JS (at it's own uri)
Pros
Cacheable by browser (if fresh values aren't needed on every request)
Cons
Extra round trip
Use when:
Your generated files are large, but rarely change or are the same for multiple users. These scripts can be treated the same as other static assets. To give an example, we serve a js file containing all the text in our app for localization purposes. We can serve a different js file based on the language set in the user's settings, but these values only change once at most with every release, so we can set aggressive cache headers and use a hash in the uri, along with a query string for the locale, to leverage browser caching and download each language file only once per client. Plus, if this file is going to be the same for every user accessing the same uri, you can cache it at the web server (IIS, Apache, etc.).
Ex: /api/language.v1-0-0.js?locale=en
Your js is independent from the rest of your app and not having it won't delay rendering. In this case, you can add the async attribute to your script tag, and this file will be downloaded asynchronously and executed when it is received without preventing the execution of other javascript.
Server-Rendered JS (within the page in a script tag)
Pros
No extra HTTP calls
Cons
Can add extra weight to your HTML, which may not be cacheable or minified depending on your circumstances
Use when:
Your values change often. The weight added to the page should be negligible unless you have a huge number of values (in that case, you might consider splitting them up and adding API endpoints for these values, and only getting them when you need them). With this, you can cut out the extra HTTP call as the js is injected into a script tag on a page the user would already have to retrieve.
But...
Don't waste too much time worrying about it. The differences in these two approaches is almost always negligible. If it becomes a problem, try both and use the better option for your case.

Breeze js - how to create an entity from a JSON string and import it into the breeze cache

I am working on a mobile single page site that uses breeze js, angular js, web API, entity framework, etc.
To optimize the site, I included the breeze metadata in a bundled JavaScript that contains all the other JavaScript the site needs. Ideally, all I would like the browser to request is index.html, which should contain everything the app needs to run including bundled and minified inline styles and JavaScript.
However, just as the breeze metadata is very important for the site to function and is therefore embedded in the bundled JavaScript, there is also a required complex entity (with some deep navigation properties to some other entities) that must also be present for the site to be fully functional. I would like to embed this entity and all the entities it references in the bundled JavaScript as well. How can I do this?
I can always create a JSON string that represents this entity and all the entities it references. Then embed that JSON string in the bundled JavaScript along with the rest. However, how can I easily import this complex entity into the breeze entity system using the entity JSON string I have embedded in JavaScript? Or is there a better solution to preload the breeze entity system with a complex entity without having to make a request for that entity from the server?
I would also like to avoid writing server code to spit out JavaScript that creates the entity on the client.
Simplest approach would be to use the "initializer" argument to the EntityManager.createEntity call.
See
http://www.breezejs.com/documentation/creating-entities and http://www.breezejs.com/sites/all/apidocs/classes/EntityManager.html#method_createEntity
This call looks this.
myEntityManager.createEntity("Employee", { lastName: Smith", firstName: "John" });
So in your case you could try:
var initialValues = JSON.parse(json);
myEntityManager.createEntity("Employee", initialValues);
Depending on your use case you may want to also set the 'entityState' of this newly created entity as well.
Here's a technique I often use to create entity data for automated tests:
Preparation
prime an EntityManager with the entities (and entity graphs) that you want available at launch.
export as a string with var exported = manager.exportEntities();. The exported string has the metadata embedded in it so you won't have to bring that down separately. Two-for-one!
capture the contents of exported to a JavaScript file that you load as script in index.html. My "capture" process is usually just to display in the console and scrape it.
Usage
Now when you need it:
load that JavaScript metadata+data file.
create a new EntityManager (remember to target the same dataservice endpoint).
import the entities you captured in your script: manager.importEntities(launchData);.
And you are good to go.
Read up on the EntityManager exportEntities and importEntities methods.
Example
One place you can see a variation on this technique is in the test directory of the "Zza-Node-Mongo".
I personally do not combine the data with the metadata so I export using the "no metadata" option. I put the metadata in one script and the data-to-load-on-launch (lookups usually) in a separate script and load both in index.html.
Caution
You say
to optimize the site, I included the breeze metadata in a bundled JavaScript that contains all the other JavaScript the site needs. Ideally, all I would like the browser to request is index.html, which should contain everything the app needs to run including bundled and minified inline styles and JavaScript.
Beware of premature optimization
I rather doubt that you will measurably improve the launch time of the app by embedding metadata and launch date in script files. Maybe some of the time if the browser caches these scripts. But that comes with its own risks and isn't a reliable strategy.
The data you want has to come over the wire to the client one way or another. It isn't self-evident that loading a script file - even a minimized script file - is any faster than pulling the metadata and launch data (both gzipped) down from the server via a web api AJAX call.
The techniques I described do speed up testing because I have to recreate metadata and the launch data before each test. I can measure the performance gain from avoiding repeated trips to the server. I gain nothing for the first trip ... which is the equivalent of your application launch.
Be mentally prepared to discover that your hard earned optimization efforts did not improve launch times ... and might even make them worse for some users.

Passing a JSON object to a remote LESS compiler to use as LESS variables

I have an admin panel where users customize the look of a static website (mostly fonts and colors). This panel generate a JSON object with the user values. What I would need to do is passing this JSON to the LESS compiler, so that it can dynamically generate a CSS file from a LESS one using the JSON content as LESS variables. The filename should be different every time, something line file-ID.css (the ID is for the user and it could be passed via JSON too).
Is it technically possible (without extending LESS)? I noticed, for example, that you can pass functions to the parser object when you create it, could I use this functions to evaluate the JSON and passing the variables to the compiler?
Obviously I don't need to know the details, just if it is doable and possibly some link to related information if you have it.
Thanks in advance.
The best way I've found to do what I was trying to accomplish was to use a server side LESS library like PHPLESS to parse the variables from the JSON before compiling. Regular LESS compiler doesn't allow to dynamically inject variables.
To my knowledge the LESS compiler doesn't support any other input than LESS. It would be trivial to make your own pre-parser that mixes-in the variables from JSON .. not even a parser, more of a string-replacer.

Best way to remove hardcoded string in javascript with Asp.Net MVC

In my javascript files, I have too much hardcorded url that references controllers actions. Sometime, I also have messages displayed directly from my javascript.
What is the best way to remove all these hardcoded strings from javascript files?
Step one, use T4MVC to automatically generate a structured set
of .NET classes that describe your ASP.NET MVC's application
structure
Step two, create a new partial view that defines server-side
information described by T4MVC as a set of Javascript constants.
<script type="text/javascript">
var SHOPPING_CART_DETAIL_URL = '#Url.Action(MVC.ShoppingCart.Detail(Model.ShoppingCartId))';
var CLIENT_DETAIL_URL = '#Url.Action(MVC.Client.Detail(Model.ClientId))';
var USER_IS_ADMIN = #(User.IsInRole(Roles.Admin) ? "true" : "false");
</script>
Step three, include this partial view in the head of whatever page
you need it. You could also include it in the head of your general
page layout. Make sure this loads before the rest of your JavaScript files.
Step four, use your newly defined JavaScript constants throughout your JavaScript files.
For that purpose I use T4MVC. It will allow you to use strongly typed objects in place of literal strings. You will need to initialize your javascript in your views, but other than that it works great.
For messages etc. here are some ideas: what are the different approaches to multilingual javascript applications
If you want to avoid using T4MVC, you could make a Controller that parses JS files. Just configure a route in Global.asax that catches all the javascript urls, and that action will ready the JS file, parse it, return a result with the URLs.
routes.MapRoute(
"Javascript",
"{url}.js",
new { controller = "Javascript", action = "Parse" }
);
Then write an action that reads the requested URL, finds the JS file, replaces values based on a Key/Value dictionnary. Perhaps even externalize that Key/Value dictionnary if could need that. The rest is up to you.
Another option would be to use a controller action that returns Javascript code. That javascript code would be a list of variables filled with URLs that are MVC generated.

Categories

Resources