Meteor css and javascript files loading best practice - javascript

TL,DR: How to load css and javascript files independent of Meteor assumptions about alphabetical order (which is far from how it works in practice.)
Stackoverflow tells me this question might be subjective but I hope not.
Meteor loads files based on alphabetical order (and other rules.)
So to force it to load the CSS and JS files in the order I wanted, I had to start the fiels with numbers that indicate the load order. If I have jquery.js and bootstrap.js, Meteor will load bootstrap.js before jquery.js. But bootstrap depends on jquery so jquery must be loaded first.
In order to solve this, the options are:
1. Put the files in the public directory and manually load them. But this didn't work as Meteor appears to be sending the files with text/html MIME type.
2. Create a Meteor package and specify the load order from there. I find this like hitting a fly with a hammer just for loading CSS and Javascript.
3. Put a number before every file. In the previous example, to load jquery before bootstrap, rename the fiels to 1.jquery.js and 2.bootstrap.js This works and is tedious but at least I get to load the files the way I want them to.
I am new to Meteor so I am wondering if there are recommended best practices concerning this. I was thinking of using AMD for javascript but that's limited to javascript.

Its an interesting question and this is probably one of the pitfalls of making a Meteor app.
You've mentioned all of the usable solutions such as creating an explicit package or renaming the files.
The best way I would think is to use the atmosphere packages. For example if you add bootstrap, jquery is a dependency of it so it will always load first. Most js libraries that involve load order are typically on atmosphere.
The other best way if there's no atmosphere package, though i'm not sure I would say is tedious is to put a number in front of the js file to indicate load order.
One thing is when you use the /public folder the files map to /, so you can load the js file yourself manually in the order you would want (in the root html file using /public. Meteor returns the text/html MIME type as its version of a 404 file not found error. This method is a bit troublesome though because the files are seperated in production and can cause trouble if one or the other dont load.

Related

Dynamically load JS/CSS per template with Meteor

I understand a couple questions (i.e. this) of this nature have already been posted, however no solid solution has been found. From what it seems, Meteor currently lacks of the ability to dynamically load/render different UI JavaScript (i.e. uilang) or CSS files per template. In my application, I have templates that require specific JS libraries and CSS as oppose to other templates.
For example:
user.html requires -> uilang.js, user_ui_code.js, userstyle.css
admin.html requires -> uilang.js, admin_ui_code.js, admin_style.css
I would need each js/css file to render/load depending on which route gets requested (i.e. example.com/user or example.com/admin), for things like different background-colors, transitions, etc. Meteor documentation states:
Files in /public are served to the client as-is. Use this to store assets such as images. For example, if you have an image located at /public/background.png, you can include it in your HTML with or in your CSS with background-image: url(/background.png). Note that /public is not part of the image URL.
So you would think that putting all your js/css/images assets in public and calling the needed files statically in head would solve the problem. Instead, it seems that the JS (CSS as well) files get concatenated and it all runs at the same time regardless of which route you are on, thus overlapping code. I'm not sure if I am missing something blatantly obvious or is this an actual issue in Meteor?
Thanks for any help.
Meteor doesn't yet support lazy/on demand loading of resources. The feature is on the roadmap as "incremental loading".
In the meantime, have a look at numtel:publicsources and numtel:privatesources, which let you create bundles for lazy loading resources, with or without authentication.

Meteor and Bootstrap admin

I would like to use meteor with a bootstrap admin, i.e. a bundle including several bootstrap plugins, script and everything typically made as a kind of framework for developing a web application.
Usually those bundles comes with a lot of dependencies, such as external links for fonts, IE hacks as well as their own shipped file of bootstrap, jQuery and other stuff. If we were in a regular php-like framework it would have been fine.
But in order to make such a template be "native" on meteor, I thought to refactor it in such a way that local dependencies (script and css basically) are stored into folders and not loaded via a <script src="…"></script> tag (otherwise the local path would not be found) but I doubt it is really the best practice, this is why I do consider 3 options:
To use the project/public folder in order to store all the bundle's dependencies (as if it would have been in php for example)
I might refactor the bundle's code by removing any script or style tag aimed to import the js or css into the page and add the corresponding js file aside so that meteor will dynamically load it during at runtime
Like in option 2 but instead of using the bundle's jQuery source files I would install the official jQuery's package for meteor (if existing).
The first (1) option should be the quickest one to get something running but it would not be very meteor native. The advantage however would be to keep the code near to the original one and being able to upgrade once a new version of the bundle would be released.
The 2 other options would be much more elegant (especially the third one) but it would involve a lot of refactoring and induce the risk of introducing bugs I did not expected.
My preference for now is the first option one but I'm afraid of not seing the drawbacks of this approach. Does someone have any experience in importing manually the CSS and JS files the "old fashion way" in meteor ? What is the risk of such an approach compared to using the "place in folder to include" way of meteor ?

Javascript one request for multiple JS files

I was thinking about creating script that would do the following:
Get all javascripts from JS directory used on server
Combine all scripts to one - that would make only one request instead of multiple
Minify combined script
Cache the file
Let's say that the order in which the files need to be loaded is written in config file somewhere.
Now when I load myexamplepage.com I actually use jQuery, backbone, mootools, prototype and few other libraries, but instead of asking server for these multiple files, I call myexamplepage.com/js/getjs and what I get is combined and minified JS file. That way I eliminate those additional requests to server. And as I read on net about speeding up your website I found out that the more requests you make to server, the slower your web become.
Since I'm pretty new to programming world I know that many things that I think of already exists, I don't think that this is exception also.
So please list what you know that does exactly or similar to what I described.(please note that you don't need to use any kind of minifiers or third party software everytime you want your scripts to be changed, you keep original files structure, you only use class helper)
P.S. I think same method could be used for CSS files also.
I'm using PHP and Apache.
Rather than having the server do this on-the-fly, I'd recommend doing it in advance: Just concatenate the scripts and run them through a non-destructive minifier, like jsmin or Google Closure Compiler in "simple" mode.
This also gives you the opportunity to put a version number on that file, and to give it a long cache life, so that users don't have to re-download it each time they come to the page. For example: Suppose the content of your page changes frequently enough that you set the cache headers on the page to say it expires every day. Naturally, your JavaScript doesn't change every day. So your page.html can include a file called all-my-js-v4.js which has a long cache life (like, a year). If you update your JavaScript, create a new all-in-one file called all-my-js-v5.js and update page.html to include that instead. The next time the user sees page.html, they'll request the updated file; but until then, they can use their cached copy.
If you really want to do this on-the-fly, if you're using apache, you could use mod_pagespeed.
If you're using .NET, I can recommend Combres. It does combination and minification of JavaScript and CSS files.
I know this is an old question, but you may be interested in this project: https://github.com/OpenNTF/JavascriptAggregator
Assuming you use AMD modules for your javascript, this project will create highly cacheable layers on demand. It has other features you may be interested in as well.

YUICompressor or similar in PHP?

I've been using yuicompressor.jar on my test server for on-the-fly minimisation of changed JavaScript files. Now that I have deployed the website to the public server, I noticed that the server's policies forbid the use of exec() or its equivalents, so no more java execution for me.
Is there a decent on-the-fly JS compressor implemented in PHP? The only thing resembling this that I was able to find was Minify, but it's more of a full-blown compression solution with cache and everything. I want to keep the files separate and have the minimised files follow my own naming conventions, so Minify is a bit too complex for this purpose.
The tool, like yuicompressor, should be able to take either a filename or JavaScript as input and should either write to a file or output the compressed JavaScript.
EDIT: To clarify, I'm looking for something that does not have to be used as a standalone (i.e. it can be called from a function, rather than sniffing my GET variables). If I just wanted a compressor, Minify would obviously be a good choice.
EDIT2: A lot has changed in the five years since I asked this question. Today I would strongly recommend separating the front-end workflow from the server code. There are plenty of good tools for JS development around and except for the most trivial jQuery enhancements it's a better idea to have a full workflow with automated bundling, testing and linting in place and just deploy the minified bundles rather than the raw files.
Yes there is, it's called minify.
The only thing in to worry about in the way of complexity is setting up a group, and there's really nothing to it. Edit the groupsConfig.php file if you want multiple JS/CSS in one <script> or <link> statement:
return array(
'js-common' => array('//js/jquery/jquery-1.3.2.min.js', '//js/common.js', '//js/visuals.js',
'//js/jquery/facebox.js'),
'css-common' => array('//css/main.css', '//css/layout.css','//css/facebox.css')
);
To include the above 'js-common' group, do this:
<script type="text/javascript" src="/min/g=js-common"></script>
(i know i was looking for the exact same thing not knowing how to deal directly with the jar file using php - that's how i ended up here so i'm sharing what i found)
Minify is a huge library with tons of functionalities. However the minifying part is a very tiny class : http://code.google.com/p/minify/source/browse/trunk/min/lib/Minify/YUICompressor.php
& very very easy to use :
//set the path to the jar file
Minify_YUIcompressor::$jarFile=_ROOT.'libs/java/yuicompressor.jar';
//set the path to a writable temp folder
Minify_YUIcompressor::$tempDir=_ROOT.'temp/';
//minify
$yourcssminified=Minify_YUIcompressor::minifyCss($yourcssstringnotminified,$youroptions)
same process for js, if you need more functionalities just pick from the library & read the source to see how you can make direct call from your app.
I didn't read the question well, since minify is based on using the jar files, the op can't use it anyway with his server config
Minify also include other minifying methods than yui, for example:
http://code.google.com/p/minify/source/browse/trunk/min/lib/JSMinPlus.php?r=443&spec=svn468
Try Lissa:
Lissa is a generic CSS and JavaScript loading utility. Lissa is an extension of the YUI PHP Loader aimed at solving one of the current loader limitations; combo loading. YUI PHP Loader ships with a combo loader that is capable of reducing HTTP requests and increasing performance by outputting all the YUI JavaScript and/or CSS requirements as a single request per resource type. Meaning even if you needed 8 YUI components which ultimately boil down to say 13 files you would still only make 2 HTTP requests; one for the CSS and another for the JavaScript. That's great, but what about custom non-YUI resources. YUI PHP Loader will load them, but it loads them as separate includes and thus they miss out on benefits of the combo service and the number of HTTP requests for the page increases. Lissa works around this limitation by using the YUI PHP Loader to handle the loading and sort of YUI and/or custom resource dependencies and pairs that functional with Minify.

How do you manage your Javascript files?

Nowadays, we have tons of Javascript libraries per page in addition to the Javascript files we write ourselves. How do you manage them all? How do you minify them in an organized way?
Organization
All of my scripts are maintained in a directory structure that I follow whenever I work on a site. The directory structure normally goes something like this:
+--root
|--javascript
|--lib
|--prototype.js
|--scriptaculous
|--scriptaculous.js
|--effects.js
|--..
|--myOwnScript.js
|--myOwnScript2.js
If, on the off chance, that I'm working on a team uses an inordinate amount of scripts, then I'll normally create a custom directory in which we'll organize scripts by relationship. This doesn't happen terribly often, though.
Compression
Though there are a lot of different compressors and obfuscators out there, I always come back to YUI Compressor.
Inclusion
Unless a site is using some form of a master page, CMS, or something that dictates what can be included on a page beyond my control, I only included the scripts necessarily for the given page just for the small performance sake. If a page doesn't require any script, there will be no script inclusions on that page.
First of all, YUI Compressor.
Keeping them organized is up to you, but most groups that I've seen have just come up with a convention that makes sense for their application.
It's generally optimal to package up your files in such a way that you have a small handful of packages which can be included on any given page for optimal caching.
You also might consider dividing your javascript up into segments that are easy to share across the team.
Cal Henderson (of Flickr fame) wrote Serving JavaScript Fast a while back. It covers asset delivery, not organization, but it might answer some of your questions.
Here are the bullet points:
Yes, you ought to concatenate JavaScript files in production to minimize the number of HTTP requests.
BUT you might not want to concatenate into one giant file; you might want to break it into logical pieces and spread the transfer cost over several pages.
gzip compression is good, but you shouldn't serve gzipped assets to IE <= 6, so you might also want to minify/compress your JavaScript.
I'll add a few bullet points of my own:
You ought to come up with a solution that works for both development and production. In development mode, it should pull in extra JavaScript files on demand; in production it should bundle everything ahead of time. Switching from one behavior to the other should be as easy as setting a flag.
Rails 2.0 handles all this through an asset cache; other web app frameworks might offer similar solutions.
As another answer suggests, placing third-party libraries in a lib directory is a good start. You can also divide your own JS files into sub-directories if it makes sense. Ideally, you'll be able to arrange them in such a way that the files in a given sub-directory can be concatenated into one file.
I will have a folder for all javascript, and a sub folder of that for 3rd party/shared libraries, and sub folders for each component of the site to keep everything organized.
For example:
/
+--/javascript/
+-- lib/
+-- admin/
+-- compnent1/
+-- compnent2/
Then run everything through a minifier/obfuscator during the build process.
I'v been using this lately:
http://code.google.com/apis/ajaxlibs/
And then have a "jscripts" folder where I keep my custom code.
In my last project, we had three kinds of JS files, all of them inside a JS folder.
Library code. A bunch of functions used on most all of the pages, so they were put together in one or a few files.
Classes. These had their own files, organized in folders as needed, but not necessarily so.
Ad hoc JS. Code that was specific to that page. These were saved in files that had the same name as the JSP pages they were supposed to run in.
The biggest effort was in having most of the code on the first two kinds, having custom code only know what to call, and when.
This might be a different approach than what you're looking for, but I've been playing around with the idea of JavaScript templates in our blog engine. In a nutshell, you assign a Javascript template to a page id using the database and it will dynamically include and minify all the JavaScript files associated with that template and create a file in a server-side cache with the template id as a file name. When a page is loaded, it calls the template file which first checks if the file exists in the cache and loads it if it does. If it doesn't exist, it creates it on the fly and includes it. I also use the template file to gzip the conglomerate JavaScript file.
The template idea would work well for site-wide JavaScript (like a JavaScript library), but it doesn't cover page-specific JavaScript. However, you can still use the same approach for page specific JavaScript by including a second file that does the same as above.

Categories