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.
Related
I have made a CMS with rails, users can upload js and css freely to customize the pages made by the CMS, I just generate a simple link to the assets according to what they are, and they have worked without any problems, how ever after updating the service to Rails5, there have been some troubles with the files uploaded in the public directory.
Mainly when people directly edit the css file in the public directory since they prefer to do that when running the CMS locally with there preferred editors when doing initial mocking.
The things known are,
The css or js does not update when locally edited (so changing body background to #000 or something doesn't show up)
directly accessing them in the browser seems to update them for subsequent accesses
assets are mostly generated by compass or webpack-dev-server since js is jsx and css is sass, but the problem reproduces even when directly editing css or js.
I know its a vague problem to ask, but I feel the asset pipeline may be interfering with files directly placed in the public directory somehow, its even more bizarre since it happens on some computers, and not on all of them.
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.
I've started using SailsJS for a small web app and so far it's great.
However I'm struggling with the assets and layout.
Basically I would like to be able to use different type of assets (groups of css files) depending on the page.
For this, I wrote 2 different layouts, each should includes the correct css files.
However, when I add those files in the config/assets.js files there all bundled together.
Is there a way to specifiy in my layout which assets i want to use ?
I know you can specify assets.js or assets.styles but I would like to be able to create my own group .
I also tried to put those assets in a different directory (public for example) and load them manually in my layout. It's still not working because the server doesn't want to 'serve' them.
Any idea ?
Glad you're liking Sails :)
For now, you can (a) bring in all styles all the time and make only the relevant ones apply (b) use another tool (like Grunt) to bundle assets like you would in a vanilla node.js project or (c) link the stylesheets manually (put them in your public folder).
As for the roadmap-- the community is working on more options for serving templates/styles/client-side logic. There's an open spec here:
https://github.com/balderdashy/sails/issues/240
Hope that helps!
I know this is old, but in case anyone else comes across this; in recent versions of sails the asset pipeline is built around grunt by default (I haven't used sails before 0.10.x).
You can add your own exports in tasks/pipeline.js and link those to the appropriate location in tasks/config/sails-linker.js. E.g. you could have a views/public folder and tell sails-linker to inject publicCSS vars there. Then adjust your layout.ejs so that it imports the styles/javascript from whichever folder.
I would like to configure my environment to serve css and javascript files from static.example.com instead of example.com/static.
The second has the convenience that I can code my html pages to load the css and javascript files relatively eg "static/reset.css" independent of the actual domain.
Is there a good practice to avoid altering all my source files whenever I change
static.example.com to static.otherexample.com
as I would have to rewrite all my HTML source files importing css and javascript?
Use some kind of configurable prefix to include js and css files. Depending on the technology you're using, it is helpful to have some kind of helper method for this. In ASP.NET MVC, I use some custom method like CSS.Add("reset.css"), which knows the path and URL.
The js files should not really care where they are loaded from. As for css, it's important to know that relative URLs in CSS are interpreted as relative to the URL the CSS was loaded from, not relative to the URL the page was loaded from. So make sure you understand that background-image: url('/images/img1.png') would also load from the static page (which is usually a good thing).
The better way
It's best practice to compress, minify and merge all of the CSS / js files. Therefore, you should only have a very small number of files (one js, one css) to keep the number of requests low. The inclusion of these files would happen on the server, so the URLs don't matter. To implement this, you will need some kind of helper method (and a lot of compression logic, but there are libraries for all this).
For ASP.NET MVC there is SquishIt, but I'm sure there are plenty of tools for various environments.
How is the html being generated?
You could use a config value or constant, and use that value for the domain portion of the url for any of the static assets.
You can always do a trick on the server, i.e. all your urls in HTML could be relative to /static, but once your server receive request, it can "change" the route and get files from static.current-domain.com instead of current-domain.com/static
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.