Load CDN (many) scripts before "merged-stylesheets.css" on the <HEAD> tag


#1

I think the title if kinda self explanatory. But I dont know how I inject my CDN scripts before “merged-stylesheets.css”

I’m getting something like this:

<head>
    <link rel="stylesheet" type="text/css" class="__meteor-css__" href="/merged-stylesheets.css?hash=7a38addd2f1829674fa74e5b80d6c347df6844e4">
    <title>Title</title>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/simple-line-icons/2.3.2/css/simple-line-icons.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap-theme.min.css" rel="stylesheet">
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
</head>

But I need something like this:

<head>
    <title>Title</title>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/simple-line-icons/2.3.2/css/simple-line-icons.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap-theme.min.css" rel="stylesheet">
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
    <link rel="stylesheet" type="text/css" class="__meteor-css__" href="/merged-stylesheets.css?hash=7a38addd2f1829674fa74e5b80d6c347df6844e4">
</head>

The LINK at the end of the HEAD tag. This is what I need…
Can someone help?


How to make Meteor append its JS files **after** JS libs from a CDN
#2

How are you adding the CDN scripts?

In one app I’ve been working on recently, all of the meteor generated stuff gets added after the explicit script declarations in my main.html head section. I thought that was standard behaviour.


#3

My main.js file looks like this…

import '/imports/startup/client';

Inside /imports/startup/client/index.js I have:

import './routes.js';

…and finally inside routes.js:

import { FlowRouter } from 'meteor/kadira:flow-router';
import { BlazeLayout } from 'meteor/kadira:blaze-layout';

BlazeLayout.setRoot('body');

import '../../ui/layouts/app';
import '../../ui/layouts/auth';

import '../../ui/pages/login';

FlowRouter.route('/login', {
    name: 'login',
    action: function() {
        BlazeLayout.render("authLayout", {content: "login"});
    }
});

Here I got stuck! Cannot figure out how to put content inside the head tag. So I auto-loaded on client/head.html

<head>
    <title>Title</title>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/simple-line-icons/2.3.2/css/simple-line-icons.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap-theme.min.css" rel="stylesheet">
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
</head>

#4

Sorry, my bad. I took another look and it’s doing the same thing as your app - inserting the stylesheet link at the top of head. I assumed it was adding it at the end like it does with JavaScript.

Might be wasting your time here but you might be able to put your CSS in an imports folder and explicitly import it into your view somewhere?

Again not to waste your time but, I’m curious about why it matters when the CSS is loaded?


#5

@peter.roehlen Unfortunately I don’t have design skills, hehehe, so I buy a theme. The theme overrides some bootstrap css tags. So if the theme’s autoloaded css load first and bootstrap later, bootstrap will set the styles back to default.


#6

I could be wrong but I don’t think load order affects what CSS rules are used. They are all loaded and the browser determines which rule gets applied in any given element based on CSS selectors giving preference to how specific the rule is.

You can try and force a particular rule to used by using the !important flag but its not considered good practice and it wouldn’t help your situation anyway since you aren’t using your own styles but a large file you’ve purchased.

Hopefully someone else can weigh in here if I’m wrong.


#7

@jonathanpmartins actually a quick google tells me that I might be wrong about load order not being relevant.


#8

I just find Inject Initial. Will take a look. I think it solves my problem… will do a try and return the results.
https://github.com/meteorhacks/meteor-inject-initial


#9

Another thing you could try is using the bootstrap package instead of loading it via the head script tags. I’ve used it in several projects with themes from Bootswatch and don’t recall ever having a problem with the Bootswatch theme being overridden.


#10

Yeah, but then my app will serve the css and scrips, or am I wrong?
For now I guess I will load the scripts with the meteor’s autoload feature.
In this projects I need to use CDN scripts for production.


#11

OK, one other option you could try is doing exactly what you had originally but move your purchased theme CSS file into /public/styles or similar and then add it manually to your html head after the bootstrap stylesheet. Just leave public out of the URL as the public folder is the root folder for serving resources.

You could also just try removing the bootstrap standard CSS altogether. I’m pretty sure the bootswatch themes (for example) include everything making the standard theme/CSS redundant but don’t quote me on it.


#12

I think I need a little more effort. Turns out that a very simple vanilla javascript make the wheel turn.
I created a file called aCDNload.js inside de client folder.

var cdnStyles = [
    'https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css',
    'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css',
    'https://cdnjs.cloudflare.com/ajax/libs/simple-line-icons/2.3.2/css/simple-line-icons.min.css',
    'https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap-theme.min.css',
    'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css',
];
var cdnScripts = [
    'https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js',
    'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js',
    'https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js'
];
var headFirstChild = document.querySelector('head').firstChild;

for (var i = 0; i < cdnStyles.length; i++) {
    var style = document.createElement('link');
    style.setAttribute('rel', 'stylesheet');
    style.setAttribute('href', cdnStyles[i]);
    document.querySelector('head').insertBefore(style, headFirstChild);
}
for (var i = 0; i < cdnScripts.length; i++) {
    var script = document.createElement('script');
    script.setAttribute('src', cdnScripts[i]);
    document.querySelector('head').appendChild(script);
}

and boom!!! now its working…


#13

My final aproach for now is:
head.html sending script tags with the request.

<head>
    <title>Title</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
</head>

aCssLoader.js loading the scripts async before everything inside the HEAD tag.

var cdnStyles = [
    'https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css',
    'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css',
    'https://cdnjs.cloudflare.com/ajax/libs/simple-line-icons/2.3.2/css/simple-line-icons.min.css',
    'https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap-theme.min.css',
    'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css',
], headFirstChild = document.querySelector('head').firstChild;

for (var i = 0; i < cdnStyles.length; i++) {
    var style = document.createElement('link');
    style.setAttribute('rel', 'stylesheet');
    style.setAttribute('href', cdnStyles[i]);
    document.querySelector('head').insertBefore(style, headFirstChild);
}