I have a website, that uses a lot of jquery/javascript. Now, at the index page I have about 10 javascript files included in the head:
<head>
<script src="/js/jquery.js"></script>
<script src="/js/jquery_plugin_1.js"></script>
<script src="/js/jquery_plugin_2.js"></script>
<script src="/js/jquery_plugin_3.js"></script>
<script src="/js/my_scripts_1.js"></script>
<script src="/js/my_scripts_2.js"></script>
<script src="/js/my_scripts_3.js"></script>
<script src="/js/my_scripts_4.js"></script>
<!-- ...and so on -->
</head>
Since visitor count grows bigger, I am starting to think about performance of all of this. I have read, that it is good idea, to minify all javascript files and gather them together in one, so a browser must make only one HTTP request. I did so. Now I have everything.js file containing all javascript, including jquery, plugins and my custom scripts.
<head>
<!--
<script src="/js/jquery.js"></script>
<script src="/js/jquery_plugin_1.js"></script>
<script src="/js/jquery_plugin_2.js"></script>
<script src="/js/jquery_plugin_3.js"></script>
<script src="/js/my_scripts_1.js"></script>
<script src="/js/my_scripts_2.js"></script>
<script src="/js/my_scripts_3.js"></script>
<script src="/js/my_scripts_4.js"></script>
...
-->
<script src="/js/everything.js"></script>
</head>
The fun starts, when I need to make changes to one of the files. Every time, to check if my changes are working as expected, I need to compress the file and update everything.js or uncomment all the old code. With this kind of work-flow it is too easy to forget something and make a mistake.
Question: is there an automated thing that can take this headache away? Something, that would allow me to edit my separate files as I used to, and would minify and pull together everything when I'm ready to test my changes?
I'm using PHP5 and SVN
SOLUTION
Thank you for your help, everybody, I found my solution:
I will put a post-commit hook in my SVN repo that will take all my .js files, put them together and minify them using YUI compressor. Then, in my script I will fork javascript includes, so that in development environment the site will include separate javascript files, but in production the combined and minified file will be included.
We have custom deploy script taking care of it. In short, it minifies all CSS and JavaScript files using YUI Compressor and packs them in up to two files, one general and another one with specific logic for a given page. Once done, we create a symlink (or a new folder, depending on the project) to the folder with packed files and new changes are propagated instantly. This approach is used will all environments except development.
Before minification, this is what CSS structure looks like (it's more or less the same for JavaScript, it's just to give you an idea):
css/Layout/Core/reset.css
css/Layout/Core/index.css
css/Layout/Tools/notice.css
css/Layout/Tools/form.css
css/Layout/Tools/overlay.css
css/Skin/Default/Core/index.css
css/Skin/Default/Tools/notice.css
css/Skin/Default/Tools/form.css
css/Skin/Default/Tools/overlay.css
css/Layout/Tools/gallery.css
css/Layout/Tools/comments.css
css/Layout/Tools/pagination.css
css/Layout/Index/index.css
css/Skin/Default/Tools/gallery.css
css/Skin/Default/Tools/comments.css
css/Skin/Default/Tools/pagination.css
css/Skin/Default/Tools/achievements.css
css/Skin/Default/Tools/labels_main.css
css/Skin/Default/Index/index.css
After:
minified/1290589645/css/common.css
minified/1290589645/css/0135f148a7f6188573d2957418119a9a.css
We like this approach since it doesn't involve any additional code to be processed on the fly. It's just a matter of deployment which happens once every two weeks to production. Our staging environment is updated every day, sometimes even more than once a day, and we have not had any problems yet.
I think you should check if your scripts are working ok when they are in one file and then compress that file.
We don't have many files so we are using a js minifier for each file using yui compressor.
If you are using an automated deployment you should perform minification and then deployment, otherwise a batch script should be ok.
Honestly I havent done this before, but I came across this two solutions and thought they might be helpful to you:
jMerge
Automatic merging and versioning of CSS/JS files with PHP
Good luck!
create a php file like this and save it as merger_js.php in your js dir
<?php
ob_start ("ob_gzhandler");
$f=$_GET['f'];
if(#file_exists($f)){
$inhoud = file_get_contents($f);
header("Content-type: application/javascript; charset: UTF-8");
header("Cache-Control: must-revalidate");
$offset = 60 * 60 ;
$ExpStr = "Expires: " .
gmdate("D, d M Y H:i:s",
time() + $offset) . " GMT";
header($ExpStr);
}else{
// file not found, we return empty
$inhoud= "";
}
print $inhoud;
call your java like this
<script type='text/javascript' src='js/merger_js.php?f=blackcan.js'></script>
Now your javascript file is send zipped to the browser. Make sure you server can handle gzip ( normally this is installed by default)
Hope this helps
Related
I have a pretty big index.php file(about 500kB) in which lots of logic and database query are present(and the index.php which goes to the client is about 200kB). What I'd like to do is first of all compress the file using gzip, which I do by simply adding SendOutputFilter in my .htaccess file. Now, since the file is pretty big to process for the server, TTFB can take a while and therefore I'd like to send to the user the header of the file before even looking at the query so that the browser will discover images, css and js(which are also pretty big) and will start downloading instead of being idle waiting for the whole index.php being processed on the server (I'd like something like Google search does. It starts download pngs before the whole page is loaded(and the page is compressed)).
I made some query and I couldn't find any straightforward solution. All I found is that either I disable gzip and use flush or use gzip but not flush.
But as you can see in my case I need both, and I know this can be done somehow. Possibly with some workarounds.
This is how huge modern websites already do, so I'd like to know how.
Luckily I was wrong. Even though GZIP needs to be downloaded completely before you can unpack it, you dont have to send just one chunk. You can send several seperate chunks, where each one is encoded separately.
This means the browsers needs to download chunk one completely and then it can unpack it and start parsing the html. Meanwhile it is downloading chunk two.
Progressive rendering via multiple flushes is a nice article explaining how it works. It is however not PHP handled, but server/apache handled.
Check out How to make PHP generate Chunked response for the PHP part you need to do.
To make GZIP work is related to how your server is setup, for help your best bet would be serverfault
This doesn't address the issue of GZIP and flush but rather PHP script and page design tailored for your question about preloading css, html etc.
You may want to consider splitting your index.php workload between two scripts, first loading html for display purposes and then then requesting the "heavier" tasks asynchronously using ajax, subsequently updating portions of your screen.
This will allow CSS and all the rest to do their work first followed by longer running tasks to display their results later.
To accomplish this start of with a "lightweight" index.php file with basic webpage html and display logic, with a event/trigger like $(window).load(function(){ //ajax call to heavier heavy_index.php script and screen updating from response }) which would allow the page to render completely and then once loaded call the heavier stuff.
This gives a quick example:
index.php
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/my_css.css">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script type="text/javascript">
$(window).load(
function () {
alert("About to load more content");
$.ajax({
url: "/heavy_index.php",
success: function (html_data) {
$("#content_loaded_later").html(html_data);
}
});
});
</script>
</head>
<body>
<div class='content_initial' ><span>Content initially loaded</span></div>
<div class='content_later' id='content_loaded_later'>loading...</div>
</body>
</html>
heavy_index.php
<?php
echo "resulting content from heavier workload";
?>
my_css.css
.content_initial
{
border:1px solid red; width:120px; height:120px;
margin:10px;
}
.content_later
{
border:1px solid green; width:120px; height:120px;
margin:10px;
}
You may also want to look at this post Preload CSS/Javascript without Execution
Hope this helps at all.
As far as I know, there is no way within Apache to force early output of content to the browser. However it is possible to do so from PHP. Note that in PHP output buffers can be layered, hence you may need to....
while (ob_get_level()) ob_end_flush();
This will send the data back to Apache without closing stdout. In the absence of other complications, that will trigger a chunked response to the browser. But the mod_deflate output filter also buffers data - DeflateBufferSize - 8kb by default. If your <head> (NOT YOUR HEADER!) is more than this size it will sit in the buffer until it is pushed out by more content. You can reduce the size of the buffer and you can pad your content to fill it - in practice you should be using both methods.
Since other people have said that this is impossible (it is not - try it) and described using Ajax to load the page, you might want to take a look at PJAX. There are big adavantages to using this on very javascript heavy site.
What is the best way to represent CSS files for a large project
I am using CodeIgniter and there would be 100's of views and almost of them have different structure so I have a lot of options here but I don't know what is the best one so please help
Make a single file for CSS and single file for JS
Make a CSS file for each view and JS for each view
Make a simple database table to hold the associated files for
each method
for example
id ----- method_name ---- files (I will normalize it )
1 /test/first first.css,first.js
and so on
or make a PHP function get the associated files as text from PHP
for example
<?php
function get_assoc($view)
{
switch($view):
case '/test/first':
echo "<script>alert(); </script><style>p{font-weight:bold;}</style>";
break;
endswitch;
}
?>
Also what about caching? Performance is a big factor.
Thanks.
I like to seperate each section reset/typograpy/forms/tables, this way I dont get lost. Dont be afraid to use as many different files as you need ( for development purposes ).
Once your ready to go into production/live mode, grab the "build tool" from "html5boilerplate" and compress all your css into one file, same for js. This will also minify your code and cache your files. just keep your un-compressed files handy incase you need to do a major edit
<!-- CSS -->
<link rel=stylesheet href="assets/css/reset.css" >
<link rel=stylesheet href="assets/css/typography.css" >
<link rel=stylesheet href="assets/css/tools.css" >
<link rel=stylesheet href="assets/css/tables.css" >
<link rel=stylesheet href="assets/css/forms.css" >
<link rel=stylesheet href="assets/css/plugins.css" >
<!-- Script -->
<script src="assets/js/modernizr2.0.js"></script>
<script src=https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js></script>
<script src="assets/js/plugins.js"></script>
<script src="assets/js/tools.js"></script>
<script src="assets/js/tables.js"></script>
<script src="assets/js/forms.js"></script>
<script src="assets/js/functions.js"></script>
I then like to wrap each (js) file as an object, again this helps with readability.
example:
(function($){
var ToolsObj = {
init : function(){
this.tooltip();
this.tabs();
this.pagination();
this.alerts();
this.dropdowns();
this.lightbox();
},
tooltip : function(){
//tooltip code
},
tabs : function(){
//tabs code
},
pagination : function(){
},
alerts : function(){
//alert messages code
},
dropdowns : function(){
//dropdown-menu code
},
lightbox : function(){
//lightbox code
}
}
$(function(){
ToolsObj.init();
});
})(jQuery.noConflict());
Hope this gives you some insight into my workflow.
You may also want to check if each element exists in the document before running the objects.
Database = no
Don't use the database for this. The CSS/JS files needed to display a view are directly tied to the source code, so keep that info in the source (particularly if you're using an SCM like Git or SVN).
CSS/JS = presentation
As these files are related to presentation/UI, I'd recommend delegating the "responsibility" of loading them to the views themselves. The controllers & models shouldn't have to "know" anything about the CSS/JS required to display the view.
Be modular
Organize the files into discrete modular units. Don't have a separate CSS/JS file for every view UNLESS you truly have completely separate functionality on every single view. The more you share these files among views, the better off you'll be.
Leverage caching, rather than fighting it
I know it's a pain in the ass to rename a file every time you modify it, but it really is a good approach. Using cache invalidating approaches (like URL?time=...) simply puts extra strain on the server and clients for no good reason. Just take the two seconds to rename your "styles.css" file to "styles_v2.css". You'll thank yourself later. (And remember, you don't have to rename it for every single dev change--only when it's stable enough for QA / production).
Premature optimization = root of all evil
Finally--and most importantly--NEVER PREMATURELY OPTIMIZE! I've seen way too many people minify and gzip their asset files all the time, only to have them overhauled a few days later. Either create a true build process, or wait until things stabilize to worry too much about the fine tuning.
Do you already make a page database call to figure out which views should be used etc? May want to have a main js and css that would be used for all pages, then individual ones linked via DB that are specifically used only by certain views.
As for caching... These files will be cached by browsers as long as they have the same request name. I typically auto-version these with a view method that looks something like:
function autoversion($filename) {
$time = filemtime($filename);
return $filename . '?v=' . $time;
}
If you have a build system that can version these files for you, you will get a small performance gain.
Does anyone know how to achieve something like TypeKit when combining multiple CSS request? Maybe I'am not aware of that but when you list some fonts the site would generate (maybe dynamic) CSS like 567,568,569.css lo load the font-file. I thought of it as dynamic as it would change if you use other combination (in this case font ID).
I use the technique described by Carpetsmoker, but I didn't like the fact that the PHP script is invoked every time. On Apache, you can set the following rewrite rule (in .htaccess):
RewriteCond %{REQUEST_URI} ^/css/cache
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^css/cache/(.*)$ /css/csscacher.php?files=$1 [L]
So say a request comes in for /css/cache/file1.css-file2.css, Apache will test for its existence. If it doesn't exist, the request will be forwarded to the csscacher.php script with the filename passed as the value of the "files" param. csscacher.php will load and combine the multiple files, send the result to the browser, but also write the result to /css/cache/file1.css-file2.css. All subsequent requests will be served as a static file.
To clear the cache, you'd just delete everything in the /css/cache folder. csscacher.php will recreate them from the source files as requests come in. More detail here.
You could also just use
#import url('reset.css');
at the top of your main css fiel to import other css files on the fly.
Have a look at the Google minify project. It offers a good solution to combine and also compress your JavaScript or CSS files. It is a PHP library that you can set up on your webserver with a script that takes a list of JS or CSS files and outputs a concatenated version. It also caches the result.
The implementation could be separated into three steps. Firstly, define a control wraps all the reference JS files.
Secondly, during the rendering of that control, using any kind of algorithm (e.g. encoding / encrypting) for all file paths to a string, and generate the script tag with a src which points to a certain handler with that generated as querystring.
e.g. Image we have two files: a.js and b.js, we have a control wraps them and generates the script tag like:
<script type='text/javascript' src='/js.php?include=encodeab'></script>
Thirdly, when client side displays the html page and sends request for that script tag, a certain server side handler (js.php in above case) will decode / decrypt that querystring to a list of included files, then read content of them, combile together and output to stream.
Hope this helps.
Be wary using dynamic js or css files as you may accidentally force the user to download them on each page (instead of using browser caching).
You can include multiple javascript/php files into one file, then give it a header of type javascript:
header("Content-type: text/javascript");
include('javascript1.php');
include('javascript2.js');
The same holds true for CSS.
Resources:
http://www.javascriptkit.com/javatutors/externalphp.shtml
http://www.webmasterworld.com/php/4239826.htm
You can use something along the lines of:
<?php
header('Content-Type: text/css');
if (isset($_GET['files']))
{
$files = explode(',', $_GET['files']);
foreach ($files as $file)
{
# BEWARE!
# What happens if the file is ../../../../../../../../etc/passwd?
$file = str_replace('..', '', ltrim($file, '/'));
include($file);
}
}
?>
test.html
<html>
<head>
<link rel="stylesheet" type="text/css" href="css.php?files=style1.css,style2.css" />
</head>
<body>
<h1>This should be red</h1>
<p>red border</p>
</body>
</html>
style1.css
p { border: 1px solid red; }
style2.css
h1 { color: red; }
This is a simple example, you can easily expand it to allow javascript files. Another good optimisation would be setting the Last modified headers based on the mtime of the .css files (use stat()) ... But the general idea should be clear.
BEWARE, to be honest, I'm not sure if the escaping/parsing of the $_GET['files'] is enough ... Please research this topic to be sure, this can a very dangerous security problem :-)
Hope this is enough to get you in the right direction.
You can do something close by calling a dynamic JS file:
start with a php file and then in it:
<?php
if(isset($_GET['jsOne'])){
include'example.com/js/one.js'; // points to some .js file
}
if(isset($_GET['jsTwo'])){
include'example.com/js/two.js'; // points to some other .js file
}
if(isset($_GET['jsThree'])){
include'example.com/js/three.js'; // points to yet a another .js file
}
?>
and in the header just have:
<script type="text/javascript" src="js/allScripts.php?jsOne=yes&jsThree=yes"> and so on
Hope this helps.
I have some javascripts that I am using in my files. But when we view the source code it shows our javascript as it is. Is there any way with which we can hide our javascript from showing up in the browser using php.
There is a free javascript obfuscator at javascriptobfuscator.com. It will not prevent dedicated people from "stealing" your code, but normal copy&paste will not be easy.
Also see this question: How can I obfuscate (protect) JavaScript? . It contains some very good answers and also explain how this is security through obscurity.
That's how it works, it visible to everyone.
You can obfuscate it, though.
As Javascript is executed inside the browser, on the client's machine, it has to be sent to that client machine.
So, one way or another, the client has to be able to read it. So, no, you cannot prevent your users from seeing the JS code if they want to.
You could obfuscate it, but someone who really want to get to your source will always be able to (event if it's hard)... But the thing is : why would you prevent your users from seeing the JS source code if they want to ?
As a sidenote : with minified/obfuscated JS code, when you'll have a bug, it'll be really harder to track down... (and you really have to keep a no-obfuscated version on your development/testing machine)
I recommend minifying it and that will remove the comments and white spacing from your code. If you don't want the names of the variables visible then you will need to obfuscate it.
I'm not sure if this will work, I may try it sometime. But basically:
<script type="text/javascript" src="MyScript.php"></script>
In the PHP file add some sort of refering to check what page requested it or what the last page was. Then if it was one of your own pages, then echo the JS, if not then don't echo it. It will still be possible to read the JS, but even harder than just viewing source and de-obfuscate it. So you could also obfuscate the code inside the .php file.
no. javascript executes on the client side.
There is another way of hiding the Javascript for the most simple users
Just test here to try finding the javascript behind the textbox...
Yet, the script is still visible for experienced users -see the bottom of this post to understand why-
The idea is to put your javascript functions in a separate ".js" file. When loading your source PHP or HTML page, instead of calling it directly with
<SCRIPT language="JavaScript" SRC="original_file_to_hide.js"></SCRIPT>
, you will include a header php script that will copy the "mysource.js" file to a random "kcdslqkjfldsqkj.js" file, and modify your HTML file to call
<SCRIPT language="JavaScript" SRC="temporary_copy_of_the_file.js"></SCRIPT>
instead. After that, just delete the copy kcdslqkjfldsqkj.js file on your server, and when the user will look for the source code, the browser will link to a vanished file !!!
So this is for the theory, next, there is a small issue to workaround : if the HTML/PHP file is loaded too fast, your script will be vanished from your server before the browser had time to load the script.
Thus, you need
To copy the file to a different random name
To load the file in the source PHP file
To wait a few seconds after your HTML/PHP file is loaded before...
...Deleting the file
Here is the source for the HTML/PHP "test.php" page which is to be displayed to the end-user:
<?php
//javascript source code hiding technique : Philippe PUECH, 2013
//function thanks to Stackoverflow, slightly modified
//http://stackoverflow.com/questions/4356289/php-random-string-generator
function RandomString()
{
$characters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
$randstring = '';
for ($i = 0; $i < 10; $i++)
{
$randstring = $randstring.$characters[rand(0, strlen($characters))];
}
return $randstring;
}
//simple header script to create a copy of your "precious" javascript ".js" file
$original_filename="functions.js"; //find a better (complicated) name for your file
$hidden_filename=RandomString().".js"; //temporary filename
copy($original_filename,$hidden_filename);
?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Catch my Javascript if you can !</title>
</head>
<SCRIPT language="JavaScript" SRC="<?php echo($hidden_filename); ?>"></SCRIPT>
<script type="text/javascript">
</script>
<body onLoad="javascript:testfunc();">
This is the page with anything you like !
</body>
</html>
<?php
sleep(1);
//you can comment following line
echo "finished !";
unlink($hidden_filename);
?>
Here is the source for the "functions.js" file which will be hidden to the user.
// JavaScript Document
function testfunc(){
alert("It works...");
}
However, as told in the comment, the developer tools of the browser will keep the script in memory, and make it still visible to the curious users... ;-((
I have about 7 Javascript files now (thanks to various jQuery plugins) and 4-5 CSS files. I'm curious as to what's the best practice for dealing with these including where in the document they should be loaded? YSlow tells me that Javascript files should be--where possible--included at the end. The end of the body? It mentions that the delimeter seems to be whether they write content. All my Javascript files are functions and jQuery code (all done when ready()) so that should be OK.
So should I include one CSS and one Javascript file and have those include the rest? Should I concatenate all my files into one? Should I put Javascript my tags at the very end of my document?
Edit: FWIW yes this is PHP.
I would suggest using PHP Minify, which lets you create a single HTTP request for a group of JS or CSS files. Minify also handles GZipping, Compression, and HTTP Headers for client side caching.
Edit: Minify will also allow you to setup the request so that for different pages you can include different files. For example a core set of JS files along with custom JS code on certain pages or just the core JS files on other pages.
While in development include all the files as you normally would and then when you get closer to switching to production run minify and join all the CSS and JS files into a single HTTP request. It's really easy to setup and get working with.
Also yes, CSS files should be set in the head, and JS files served at the bottom, since JS files can write to your page and can cause massive time-out issues.
Here's how you should include your JS files:
</div> <!-- Closing Footer Div -->
<script type="application/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.1.min.js"></script>
</body>
</html>
Edit: You can also use Cuzillion to see how your page should be set up.
Here's what I do: I use up to two JavaScript files and generally one CSS file for each page. I figure out which JS files will be common across all of my pages (or enough of them so it's close - the file containing jQuery would be a good candidate) and then I concatenate them and minify them using jsmin-php and then I cache the combined file. If there are any JS files left over that are specific to that one page only, I concatenate, minify, and cache them into a single file as well. The first JS file will be called over a number of pages, the second only on that one or maybe a few.
You can use the same concept with CSS if you like with css-min, though I find I usually only use one file for CSS. One thing extra, when I create the cache file, I put in a little PHP code in the beginning of the file to serve it as a GZipped file, which is actually where you'll get most of your savings anyways. You'll also want to set your expiration header so that the user's browser will have a better chance of caching the file as well. I believe you can also enable GZipping through Apache.
For the caching, I check to see if the file creation time is older than the amount of time that I set. If it is, I recreate the cache file and serve it, otherwise I just get the existing cached file.
You haven't explicitly said that you've got access to a server-side solution, but assuming you do, I've always gone with a method involving using PHP to do the following:
jquery.js.php:
<?php
$jquery = ($_GET['r']) ? explode(',', $_GET['r']) : array('core', 'effects', 'browser', 'cookies', 'center', 'shuffle', 'filestyle', 'metadata');
foreach($jquery as $file)
{
echo file_get_contents('jquery.' . $file . '.js');
}
?>
With the snippet above in place, I then call the file just like I normally would:
<script type="text/javascript" src="jquery.js.php"></script>
and then if I'm ever aware of the precise functionality I'm going to need, I just pass in my requirements as a query string (jquery.js.php?r=core,effects). I do the exact same for my CSS requirements if they're ever as branched.
I would not recommend using a javascript based solution (like PHP Minify) to include your css as your page will become unusable if the visitor has javascript disabled.
The idea of minifying and combining the files is great.
I do something similar on my sites but to ease development I suggest some code which looks like this:
if (evironment == production) {
echo "<style>#import(/Styles/Combined.css);</style>"
} else {
echo "<style>#import(/Styles/File1.css);</style>"
echo "<style>#import(/Styles/File2.css);</style>"
}
This should let you keep your files separate during dev for easy management and use the combined file during deployment for quicker page loads. This assumes you have the ability to combine the files and change variables as part of your deploy process.
Definitely look into including your js at the bottom and the css at the top as per YUI recommendations as keeping the JS low has a tangible affect on the appearance of the rest of the page and feels much faster.
I also tend to copy+paste all of my jquery plugins into a single file: jquery.plugins.js then link to
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js">
for the actual jquery library.