I am working on a chrome extension, written in React, and attaches itself to the page using a shadow DOM element. Inside I am loading the extension's logo and a content stylesheet.
However, it was reported that the extension was not loading properly and have pinpointed that any resource from web_accessible_resources (e.g. chrome-extensions://...) were being unmounted from the page on certain sites (e.g. https://www.skechers.com/).
In a work-around we ended up serving the content from our CDN, which works fine. Still wondered if anyone knew why this didn't work on a few sites.
I also wrote code to see if it removes the stylesheet and then loads the CDN version, just to test it out.
const onStylesLoad = (loaded) => {
const sheet = loaded.target.sheet
setTimeout(() => {
if (!sheet.ownerNode) {
console.log('FALLBACK', sheet);
setFallback('https://cdn.***/themes/browserExtension/content.css');
}
}, 1000);
}
// And later in the render...
<link rel='stylesheet' type='text/css' onLoad={onStylesLoad} href={browser.runtime.getURL('content.css')} />
{fallback && <link rel='stylesheet' type='text/css' href={fallback} />}
The extensions stylesheet does load, but then is immediately unmounted, which is how I am able to detect a moment later that the ownerNode is null (onLoad its attached to the link).
I am fine with the work-around, it just irks me that packaging any content is made moot, since we have too point it to a CDN regardless.
If you want to store the css files locally, rather than from a CDN, you could minify the css files, then store them as a string in your js files and insert them into the page by creating a style element on document ready. I guess they probably wouldn't be able to reference the local images though, but it seems you're not able to anyway
Related
I have been looking at a HTML 5 boilerplate template (from http://html5boilerplate.com/) and noticed the use of "?v=1" in URLs when referring to CSS and JavaScript files.
What does appending "?v=1" to CSS and JavaScript URLs in link and script tags do?
Not all JavaScript URLs have the "?v=1" (example from the sample below: js/modernizr-1.5.min.js). Is there a reason why this is the case?
Sample from their index.html:
<!-- CSS : implied media="all" -->
<link rel="stylesheet" href="css/style.css?v=1">
<!-- For the less-enabled mobile browsers like Opera Mini -->
<link rel="stylesheet" media="handheld" href="css/handheld.css?v=1">
<!-- All JavaScript at the bottom, except for Modernizr which enables HTML5 elements & feature detects -->
<script src="js/modernizr-1.5.min.js"></script>
<!------ Some lines removed ------>
<script src="js/plugins.js?v=1"></script>
<script src="js/script.js?v=1"></script>
<!--[if lt IE 7 ]>
<script src="js/dd_belatedpng.js?v=1"></script>
<![endif]-->
<!-- yui profiler and profileviewer - remove for production -->
<script src="js/profiling/yahoo-profiling.min.js?v=1"></script>
<script src="js/profiling/config.js?v=1"></script>
<!-- end profiling code -->
These are usually to make sure that the browser gets a new version when the site gets updated with a new version, e.g. as part of our build process we'd have something like this:
/Resources/Combined.css?v=x.x.x.buildnumber
Since this changes with every new code push, the client's forced to grab a new version, just because of the querystring. Look at this page (at the time of this answer) for example:
<link ... href="http://sstatic.net/stackoverflow/all.css?v=c298c7f8233d">
I think instead of a revision number the SO team went with a file hash, which is an even better approach, even with a new release, the browsers only forced to grab a new version when the file actually changes.
Both of these approaches allow you to set the cache header to something ridiculously long, say 20 years...yet when it changes, you don't have to worry about that cache header, the browser sees a different querystring and treats it as a different, new file.
This makes sure you are getting the latest version from of the css or js file from the server.
And later you can append "?v=2" if you have a newer version and "?v=3", "?v=4" and so on.
Note that you can use any querystring, 'v' is not a must for example:
"?blah=1" will work as well.
And
"?xyz=1002" will work.
And this is a common technique because browsers are now caching js and css files better and longer.
The hash solution is nice but not really human readable when you want to know what version of file is sitting in your local web folder. The solution is to date/time stamp your version so you can easily compare it against your server file.
For example, if your .js or .css file is dated 2011-02-08 15:55:30 (last modification) then the version should equal to .js?v=20110208155530
Should be easy to read properties of any file in any language. In ASP.Net it's really easy...
".js?v=" + File.GetLastWriteTime(HttpContext.Current.Request.PhysicalApplicationPath + filename).ToString("yyMMddHHHmmss");
Of coz get it nicely refactored into properties/functions first and off you go. No more excuses.
Good luck, Art.
In order to answer you questions;
"?v=1" this is written only beacuse to download a fresh copy of the css and js files instead of using from the cache of the browser.
If you mention this query string parameter at the end of your stylesheet or the js file then it forces the browser to download a new file, Due to which the recent changes in the .css and .js files are made effetive in your browser.
If you dont use this versioning then you may need to clear the cache of refresh the page in order to view the recent changes in those files.
Here is an article that explains this thing How and Why to make versioning of CSS and JS files
Javascript files are often cached by the browser for a lot longer than you might expect.
This can often result in unexpected behaviour when you release a new version of your JS file.
Therefore, it is common practice to add a QueryString parameter to the URL for the javascript file. That way, the browser caches the Javascript file with v=1. When you release a new version of your javascript file you change the url's to v=2 and the browser will be forced to download a new copy.
During development / testing of new releases, the cache can be a problem because the browser, the server and even sometimes the 3G telco (if you do mobile deployment) will cache the static content (e.g. JS, CSS, HTML, img). You can overcome this by appending version number, random number or timestamp to the URL e.g: JSP: <script src="js/excel.js?time=<%=new java.util.Date()%>"></script>
In case you're running pure HTML (instead of server pages JSP, ASP, PHP) the server won't help you. In browser, links are loaded before the JS runs, therefore you have to remove the links and load them with JS.
// front end cache bust
var cacheBust = ['js/StrUtil.js', 'js/protos.common.js', 'js/conf.js', 'bootstrap_ECP/js/init.js'];
for (i=0; i < cacheBust.length; i++){
var el = document.createElement('script');
el.src = cacheBust[i]+"?v=" + Math.random();
document.getElementsByTagName('head')[0].appendChild(el);
}
As you can read before, the ?v=1 ensures that your browser gets the version 1 of the file. When you have a new version, you just have to append a different version number and the browser will forget about the old version and loads the new one.
There is a gulp plugin which takes care of version your files during the build phase, so you don't have to do it manually. It's handy and you can easily integrate it in you build process. Here's the link: gulp-annotate
As mentioned by others, this is used for front end cache busting. To implement this, I have personally find grunt-cache-bust npm package useful.
I am building a web2py application.
I use my own css file called style.css
I do know that the following code
{{response.files.append(URL('static','css/base.css'))}}
{{include 'web2py_ajax.html'}}
will link my css file to my application.
I use this for layout.html; which is used for every page of application.
Initially, I do not have problem with this...
Suddenly, at some point, my css is not updated...
Every css before the point, works fine.
Every css after the point, do not work at all.
In web2py editor, all css changes are updated. However, If if run it, the css is not updated... If I inspect the css code using chrome, the css is not updated and remain to previous css file..
for clarification, I give you example
initially I just have the following.
#title{
font-size: 90px;
}
then I change it to the following
#title{
font-size:100px;
}
IN the web2py editor, the change is saved and set it to 100px. However, if i run the application and view css file using chrome inspect, it is still remained as 90px.
I thought the server may have some error, so I restarted. I still get error.
Another thing I can think of is the confit with bootstrap..
The following is the head part of layout.html
<head>
<title>NR</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
{{response.files.append(URL('static','css/bootstrap.min.css'))}}
{{response.files.append(URL('static','css/style.css'))}}
{{include 'web2py_ajax.html'}}
</head>
Actually, I do have a solution...
If I create css file with different name, and copy and paste all css work, it work!!
However, this takes extra work... create new css file and copy and paste.... It is not good way.
Can you help me?
Thank you
Perhaps your web server is configured to set the HTTP response headers so the assets will be cached by the browser (in which case, they will not be re-sent on every request). If this is just a development issue, you can simply force your browser to reload all assets (e.g., by pressing CTRL-F5).
For a more general solution, see the documentation on static asset management.
Another option is to let web2py serve the static content itself, in which case, the assets will be re-requested with each page and web2py will return 304 responses if the assets have not changed since last sent.
https://friends-with-you.myshopify.com/
I'm trying to develop my first shopify theme. I'm trying to load a stylesheet which is hosted on another server, but the CSS is not loading. If I copy and paste that CSS directly into a file in the shopify theme, it works.
<link type="text/css" rel="stylesheet" href="http://fwy.pagodabox.com/magic/themes/fwy/fwy.css" />
What am I doing wrong at the above URL, and why isn't the css loading?
thanks!
Can you load your CSS file over both http and https? If so, change your tag to look like this:
<link type="text/css" rel="stylesheet" href="//fwy.pagodabox.com/magic/themes/fwy/fwy.css" />
That way whether a user visits using http://yourstore.com or https://yourstore.com, they'll get the stylesheet served using the protocol they're on (and you won't get any mixed content warnings).
A little more background: http://paulirish.com/2010/the-protocol-relative-url/
Under IE7 and IE8, using this in a <link> tag will result in your content being fetched twice.
Change your link tag to use a secure URL:
<link type="text/css" rel="stylesheet" href="https://fwy.pagodabox.com/magic/themes/fwy/fwy.css" />
^
The URL you're using now works fine on its own, but since you're browsing to the Shopify store over SSL, many web browsers are going to be hesitant to load the CSS over an unsecured connection.
I just checked and pagodabox serves the CSS file just fine over SSL.
In normal HTML documents one can load stylesheets from anywhere, as long as they exist and you're able to load them by typing the URL in (which I can).
I see the page as two navigation bars with a logo on the left hand side. There are hover states with transitions to a colour background on each item. Although, when I loaded the page, Chrome warned me not to load supposedly insecure content. Before this is loaded I just see text in Times New Roman. I think this is you problem.
I use themes with WordPress and style-sheets come with them (mostly). I don't see why you couldn't just put the style-sheet in with the rest of the theme.
Overall, the answer is yes (normally) but in this case browsers may regard it as un-safe and therefore not load it.
Yes you can! But it is faster to host the stylesheet on your server/where the other files reside. If you plan to include a stylesheet from elsewhere, you could run into problems of that server being down/busy and hence your theme will not display as required. As #Blieque mentioned, some browsers may question external content causing unnecessary warning popups to a user/user-agent.
I know that a common practice is to set an expire time far in the future for css, javascript and image files and then make sure that all browsers fetches the latest content as soon the files changes by appending a querystring (or changing filename) like this
From this <link rel="stylesheet" type="text/css" href="base.css">:
to this:
<link rel="stylesheet" type="text/css" href="base.css?v=1234">
or:
<link rel="stylesheet" type="text/css" href="base_1234.css">
But what about images referenced in a css file?
// Inside base.css
background: url(/img/logo.png)
// Is this necessary(?):
background: url(/img/logo.png?v=1234)
Or will /img/logo.png be reloaded when base.css changes filename to base.css?v=1234 or base_1234.css automatically?
And also, what about images in src for img-tags?
The browser is making these requests after determining an absolute path, so if you are 'cache busting' your static assets in this way, you do need to do it for each file individually, no matter where it's called. You can, however, make it easer on yourself by making it a variable on the backend.
You can append the string as a variable that you only have to update in one place on your backend, probably in conjunction with a CSS pre-processor like LESS or SASS to get all your images.
Or use relative paths to your advantage by adding the version to the base url (site.com/folder/styles.css => site.com/v123/folder/styles.css). This can be added to an existing static asset base url variable in your app, then on the server you can just use a UrlRewrite to strip out the version. This way all the images relatively referred to from your CSS automatically get the version too, having the same 'cache busting' effect.
You could be extra clever and set the variable automatically as part of your build process as the last commit hash from you version control system - which will also make future debugging easier.
From my experience the cache busting of the css is not recursive. So the querystring at the end of the image referenced in css is required to bust the cache.
To be sure all images are fresh you may want to also cache bust with the querystring version (img.png?v=1234).
Chrome seems to be the worse of the browser-bunch for not updating it's cache (perhaps due to the new predictive caching methods it's using) and the way to do this is indeed with a querystring.
This website takes it one step further and uses the simple JavaScript Date().getTime(); method (with or without jQuery) that is attached to all img tags.
Another solution is to write a javascript code so that the browser does not pick up image
from the cache and loads it everytime.
The benefit of the above is that individual image-file renaming, for the sake of the querystring, is not needed as the JavaScript handles this in one pass.
While it does use a single line of JavaScript to accomplish this, it's not as high-maintenance as tracking down every img element in a large CSS file, which can take time and add to the file size.
EDIT: My sincere apologies! This wasn't an issue with anything but myself - I had a global.css file with correct stuff in it, but below that I included another file with the old CSS in it, in the <head> bit of my HTML. Facepalm.
I have a site I'm developing. I'm using LESS to enhance my CSS to make it easier to write. The problem is, when I change the .less file, the styles rendered in the browser refuse to change. I've looked in the generated .css file, and that updates to reflect the changes made, however the browser doesn't update it's rendered style from the CSS file. I've tried this in Chrome, FF(3 and 4) and Opera, with the same non-updating results.
I've even told the browser to cache nothing, both with PHP and meta tags, to no avail. My Apache config file is almost vanilla, although I am using multiple localhosts (this is a local server). The code used to convert LESS to CSS is given below, and is run every time the page is reloaded:
try
{
lessc::ccompile('global/global.less', 'global/global.css');
}
catch(exception $ex)
{
exit('lessc fatal error:<br />' . $ex->getMessage());
}
There are no exceptions here. the less.php parser checks if the file has been modified, which I removed for a bit, but the CSS file is re-generated on every change, so this must be a caching issue with the browser somewhere... Apache serves up the updated CSS file just fine :-/
Sorry to go on for so long, but I wanted to be clear. If you need anything else, do let me know.
Once I saw in a code the use of timestamp to force the browser to download the css and js files every request, that way:
<link rel="stylesheet" type="text/css" href="http://www.example.com/style.css?ts=<?=time()?>" />
The ?ts=123456789 forces the browser to reload the file whenever the number is different from the previous one.
So I adopted the idea, but instead of timestamp of now, I use timestamp of the modification of file style.css; so it's cached in the browser until be modified on the server:
<link rel="stylesheet" type="text/css" href="http://www.example.com/style.css?ts=<?=filemtime('style.css')?>" />
I'm using LESS and Laravel, and I finally figured out a good solution:
In my <head> tag, I have:
<link rel="stylesheet/less" type="text/css" href="/less/main.less?ts={{FileHelper::getMostRecentModifiedTimeInFolder(realpath(public_path() . '/less'))}}" />
Then I also created a FileHelper class (based on https://stackoverflow.com/a/6767411/470749):
<?php
class FileHelper {
public static function getMostRecentModifiedTimeInFolder($path)
{
//https://stackoverflow.com/a/6767411/470749
$iterator = new DirectoryIterator($path);
$mtime = -1;
foreach ($iterator as $fileinfo) {
if ($fileinfo->isFile()) {
if ($fileinfo->getMTime() > $mtime) {
$mtime = $fileinfo->getMTime();
}
}
}
return $mtime;
}
}
I might decide to use this approach only on my local development server and use a different approach for production so that it's not always checking file timestamps on every page load.
Since you can't control browser cache, I would suggest you give versions to your css file. Like global.1.11.css.