css/js files - no caching

Από που να ξεκινήσω; Που θα βρω; κ.α. γενικές ερωτήσεις για την δημιουργία μιας ιστοσελίδας.

Συντονιστές: WebDev Moderators, Super-Moderators

Απάντηση
Άβαταρ μέλους
cherouvim
Script Master
Δημοσιεύσεις: 3137
Εγγραφή: 13 Ιούλ 2005 22:56
Τοποθεσία: Athens, Greece
Επικοινωνία:

css/js files - no caching

Δημοσίευση από cherouvim » 30 Δεκ 2007 21:56

Το digg.com σε κάθε αλλαγή στο css και js, βάζει τα αρχεία αυτά σε ένα νέο folder. Προφανώς για να μην δει κανείς "σπασμένο" το site λόγω του browser caching:

Κώδικας: Επιλογή όλων

<style type="text/css" media="all">@import "/css/60/global.css";</style>
<style type="text/css" media="all">@import "/css/60/lightbox.css";</style>
<script src="/js/60/prototype.js" type="text/javascript"></script>
<script src="/js/60/jquery.js" type="text/javascript"></script>
<script src="/js/60/digg.js" type="text/javascript"></script>
Το slashdot.org απλά προσθέτει ένα GET parameter σε αυτά τα στατικά αρχεία:

Κώδικας: Επιλογή όλων

<link rel="stylesheet" type="text/css" media="screen" href="/core-tidied.css?T_2_5_0_188">
<link rel="stylesheet" type="text/css" media="print" href="/print.css?T_2_5_0_188">
<link rel="stylesheet" type="text/css" media="handheld" href="/handheld.css?T_2_5_0_188">
Αυτός ο 2ος τρόπος συνεπάγεται no caching σε όλους τους browsers και όλους τους web servers;

Άβαταρ μέλους
fafos
Script Master
Δημοσιεύσεις: 6231
Εγγραφή: 30 Νοέμ 2004 03:09

css/js files - no caching

Δημοσίευση από fafos » 31 Δεκ 2007 02:12

An den kano lathos o 2os tropos einai sympiesh ton arxeion tou typou:
<link rel="stylesheet" type="text/css" href="{compress file="style.css" css=true theme=true}" />

(einai paradeigma apo smarty template me GZIP sympiesh)

Άβαταρ μέλους
skeftomilos
Script Master
Δημοσιεύσεις: 2888
Εγγραφή: 07 Ιαν 2005 07:22
Τοποθεσία: Αθήνα

css/js files - no caching

Δημοσίευση από skeftomilos » 31 Δεκ 2007 08:51

Η λύση του digg είναι αντικειμενικά καλύτερη κατά τη γνώμη μου, αλλά είναι πιο περίπλοκη στην υλοποίησή της από τη λύση του slashdot, και ελαφρά λιγότερο portable (λόγω ανάγκης για write premissions στους φακέλους /css και /js). Το πρόβλημα της λύσης του slashdot είναι ότι by the book οι browsers δε θα έπρεπε να χρησιμοποιούν την τοπική cache για resources με querystring, με αποτέλεσμα για κάθε page request να κάνουν hit στον server για τα συνοδευτικά αρχεία. Από πρακτική άποψη ο μόνος browser που τηρεί κατά γράμμα τον κανόνα είναι ο Opera. Γι αυτό μέχρι τώρα προτιμώ να εφαρμόζω αυτή τη λύση, τουλάχιστον για μικρά sites (π.χ. www.promodora.gr).
The pure and simple truth is rarely pure and never simple. Ο μη νους δε σκέπτεται μη σκέψεις για το τίποτα.

Άβαταρ μέλους
dik_
Δημοσιεύσεις: 476
Εγγραφή: 07 Ιουν 2007 11:28

css/js files - no caching

Δημοσίευση από dik_ » 31 Δεκ 2007 16:32

Αυτό που λέει ο skeftomilos καταλαβαίνω κι εγώ από το RFC 2616 13.9. Πάντως, τον τρόπο του /. χρησιμοποιώ κι εγώ. Όσο έψαξα, είδα ότι πράγματι μόνο ο Opera τηρεί τις οδηγίες του RFC.

Άβαταρ μέλους
cherouvim
Script Master
Δημοσιεύσεις: 3137
Εγγραφή: 13 Ιούλ 2005 22:56
Τοποθεσία: Athens, Greece
Επικοινωνία:

css/js files - no caching

Δημοσίευση από cherouvim » 31 Δεκ 2007 17:12

skeft: Τη πολυπλοκότητα τη χτυπάς μία φορά ενσωματώνοντας τη διαδικασία στο "production deployment" task του build σου (ant, nant, phing κτλ).
Αυτή μπορεί να είναι κάπως έτσι:
  1. αύξηση count (1, 2, 3 κτλ)
  2. inject count για χρήση από τα html header templates
  3. αντιγραφή των περιεχομένων των css/ και js/ στα css/${count}/ και js/${count}/
κτλ

Άβαταρ μέλους
skeftomilos
Script Master
Δημοσιεύσεις: 2888
Εγγραφή: 07 Ιαν 2005 07:22
Τοποθεσία: Αθήνα

css/js files - no caching

Δημοσίευση από skeftomilos » 31 Δεκ 2007 18:33

@Cherouvim: Αν καταλαβαίνω καλά, αυτή η στρατηγική προϋποθέτει ότι θα γίνεται build της εφαρμογής για κάθε αλλαγή στα styles ή στα scripts, οσοδήποτε μικρή; Και στη συνέχεια FTP upload όλων των παραγόμενων αρχείων; Η διαδικασία στην οποία έχω εμπειρία είναι λιγότερο αυτόματη, μόνο τα αλλαγμένα αρχεία ανεβαίνουν με FTP.

Μια άλλη δυνατότητα είναι να δημιουργούνται τα αρχεία με δυναμικό τρόπο από την ίδια την εφαρμογή. Για παράδειγμα έστω ότι μια εφαρμογή χρησιμοποιεί τρία scripts, τα a.js, b.js και c.js, αλλά τα σερβίρει πακεταριμένα σε ένα αρχείο pack.yyyy.mm.dd.hh.mm.ss.js. Η δημιουργία του pack.js μπορεί να γίνεται κατά το build της εφαρμογής, ή μπορεί να το φτιάχνει η εφαρμογή κάθε φορά που η ημερομηνία μεταβολής κάποιου από τα a,b,c.js είναι νεώτερη από την ημερομηνία δημιουργίας του pack.js.
The pure and simple truth is rarely pure and never simple. Ο μη νους δε σκέπτεται μη σκέψεις για το τίποτα.

Άβαταρ μέλους
cherouvim
Script Master
Δημοσιεύσεις: 3137
Εγγραφή: 13 Ιούλ 2005 22:56
Τοποθεσία: Athens, Greece
Επικοινωνία:

css/js files - no caching

Δημοσίευση από cherouvim » 31 Δεκ 2007 18:46

Διαδικασίες build έχω ούτοσιαλλος στα projects, λόγω πολυπλοκότητας προετοιμασίας του deployment.

Κάνουμε πολύ συχνά in-house releases, στα οποία δεν χρειάζεται να τρέξει αυτή η διαδικασία. Ο pm/cm/tester μπορεί να ζήσει και με ένα CTRL+R για hard refresh των css/js. Στα, πιο σπάνια, production releases (πχ 1 φορά το μήνα) το ανεβάζουμε όλο.

Η ιδέα με το pack.yyyy.mm.dd.hh.mm.ss είναι ωραία. Την έχω δει κάπου, αλλά ως query string, και όχι ως όνομα αρχείου.

Άβαταρ μέλους
skeftomilos
Script Master
Δημοσιεύσεις: 2888
Εγγραφή: 07 Ιαν 2005 07:22
Τοποθεσία: Αθήνα

css/js files - no caching

Δημοσίευση από skeftomilos » 31 Δεκ 2007 19:07

@dik_: Παρόλο που ο Opera φαίνεται να είναι τυπικά σωστός, η πολιτική caching που υιοθετεί δεν είναι από τα δυνατά του σημεία. Κάποιοι που χρησιμοποιούν καθημερινά τον Opera θα το έχουν παρατηρήσει (π.χ. Simon Willison Sticking with Opera 9).

@Cherouvim: Για την προσθήκη του time stamp στο querystring χρησιμοποιώ αυτόν τον κώδικα (ASP.NET, C#):

Κώδικας: Επιλογή όλων

<link type="text/css" href="style.css?<%=GetFileVersion&#40;"style.css"&#41;%>" rel="stylesheet">
...και στο code behind:

Κώδικας: Επιλογή όλων

protected string GetFileVersion&#40;string relPath&#41; &#123;
  string cacheKey = "File-" + relPath + "-Version";
  string version = &#40;string&#41;HttpContext.Current.Cache&#91;cacheKey&#93;;
  if &#40;version == null&#41; &#123;
    string filePath = MapPath&#40;relPath&#41;;
    version = File.GetLastWriteTime&#40;filePath&#41;.ToString&#40;"ddMMyy&#58;HHmm&#58;ssff"&#41;;
    HttpContext.Current.Cache.Insert&#40;cacheKey, version, new CacheDependency&#40;new string&#91;&#93;&#123;filePath&#125;&#41;&#41;;
  &#125;
  return version;
&#125;
Ο κώδικας τρέχει σε κάθε page request, αλλά η ανάγνωση της ημερομηνίας μεταβολής του αρχείου γίνεται σπάνια γιατί κασάρεται server-side.
The pure and simple truth is rarely pure and never simple. Ο μη νους δε σκέπτεται μη σκέψεις για το τίποτα.

Άβαταρ μέλους
cherouvim
Script Master
Δημοσιεύσεις: 3137
Εγγραφή: 13 Ιούλ 2005 22:56
Τοποθεσία: Athens, Greece
Επικοινωνία:

css/js files - no caching

Δημοσίευση από cherouvim » 06 Μαρ 2008 16:26

skeftomilos έγραψε:Το πρόβλημα της λύσης του slashdot είναι ότι by the book οι browsers δε θα έπρεπε να χρησιμοποιούν την τοπική cache για resources με querystring, με αποτέλεσμα για κάθε page request να κάνουν hit στον server για τα συνοδευτικά αρχεία. Από πρακτική άποψη ο μόνος browser που τηρεί κατά γράμμα τον κανόνα είναι ο Opera. Γι αυτό μέχρι τώρα προτιμώ να εφαρμόζω αυτή τη λύση, τουλάχιστον για μικρά sites (π.χ. www.promodora.gr).
Τελικά με querystring γίνεται δουλειά για τους major browsers;
Ή θα πρέπει ο χρήστης να πατήσει CTRL+R;

Άβαταρ μέλους
skeftomilos
Script Master
Δημοσιεύσεις: 2888
Εγγραφή: 07 Ιαν 2005 07:22
Τοποθεσία: Αθήνα

css/js files - no caching

Δημοσίευση από skeftomilos » 06 Μαρ 2008 18:22

Ναι, μια χαρά δουλεύει η αλλαγή του querystring.

Browser: Άλλο URL, άρα άλλο resource, άρα download it.

Άβαταρ μέλους
skeftomilos
Script Master
Δημοσιεύσεις: 2888
Εγγραφή: 07 Ιαν 2005 07:22
Τοποθεσία: Αθήνα

css/js files - no caching

Δημοσίευση από skeftomilos » 23 Μαρ 2008 05:19

Το Facebook υιοθετεί και τις δύο λύσεις ταυτόχρονα! Δυστυχώς το πρόβλημά του είναι τα αμέτρητα εξωτερικά αρχεία.
Στη σελίδα https://register.facebook.com/editaccount.php έχασα το μέτρημα, κάπου 70 external styles και scripts...

Κώδικας: Επιλογή όλων

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http&#58;//www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http&#58;//www.w3.org/1999/xhtml" xml&#58;lang="en" lang="en" id="facebook">
<head>
<title>Facebook | My Account</title>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<script type="text/javascript">Env=&#123;method&#58;"GET",dev&#58;0,start&#58;&#40;new Date&#40;&#41;&#41;.getTime&#40;&#41;,ps_limit&#58;5,ps_ratio&#58;4,pkgv&#58;0,static_base&#58;"https&#58;\/\/www.facebook.com\/"&#125;;</script>
<meta id="robots" name="robots" content="noodp" />
<meta id="description" name="description" content="Facebook is a social utility that connects people with friends and others who work, study and live around them. People use Facebook to keep up with friends, upload an unlimited number of photos, share links and videos, and learn more about the people they meet." /><link rel="stylesheet" href="/rsrc.php/72882/css/actionspro.css?58&#58;72882" type="text/css"/>
<link rel="stylesheet" href="/rsrc.php/87620/css/base.css?58&#58;87620" type="text/css"/>
<link rel="stylesheet" href="/rsrc.php/79182/css/apps_menu.css?58&#58;79182" type="text/css"/>
<link rel="stylesheet" href="/rsrc.php/84920/css/captcha/captcha.css?58&#58;84920" type="text/css"/>
<link rel="stylesheet" href="/rsrc.php/86004/css/wallpro.css?58&#58;86004" type="text/css"/>
<link rel="stylesheet" href="/rsrc.php/39930/css/dialog.css?58&#58;39930" type="text/css"/>
<link rel="stylesheet" href="/rsrc.php/74947/css/attachments.css?58&#58;74947" type="text/css"/>
<link rel="stylesheet" href="/rsrc.php/84091/css/editor.css?58&#58;84091" type="text/css"/>
<link rel="stylesheet" href="/rsrc.php/81048/css/account.css?58&#58;81048" type="text/css"/>
<link rel="stylesheet" href="/rsrc.php/53705/css/components.css?58&#58;53705" type="text/css"/>
<link rel="stylesheet" href="/rsrc.php/19905/css/typeahead.css?58&#58;19905" type="text/css"/>
<link rel="stylesheet" href="/rsrc.php/88533/css/typeaheadpro.css?58&#58;88533" type="text/css"/>
<link rel="stylesheet" href="/rsrc.php/82941/css/dialogpro.css?58&#58;82941" type="text/css"/>
<link rel="stylesheet" href="/rsrc.php/86706/css/intl.css?58&#58;86706" type="text/css"/>
<!--&#91;if lte IE 6&#93;><style type="text/css" media="screen">/* <!&#91;CDATA&#91; */ @import url&#40;/css/ie6.css?58&#58;88431&#41;; /* &#93;&#93;> */</style><!&#91;endif&#93;-->
<!--&#91;if gte IE 7&#93;><style type="text/css" media="screen">/* <!&#91;CDATA&#91; */ @import url&#40;/css/ie7.css?58&#58;88431&#41;; /* &#93;&#93;> */</style><!&#91;endif&#93;-->
<script type="text/javascript" src="/js_strings.php/t83766/en_US"></script>
<script type="text/javascript" src="/rsrc.php/86588/js/lib/util/bootloader.js?58&#58;86588"></script>
<script type="text/javascript" src="/rsrc.php/84984/js/lib/type/array.js?58&#58;84984"></script>
<script type="text/javascript" src="/rsrc.php/86410/js/lib/type/object.js?58&#58;86410"></script>
<script type="text/javascript" src="/rsrc.php/87361/js/lib/type/function.js?58&#58;87361"></script>
<script type="text/javascript" src="/rsrc.php/83874/js/lib/type/string.js?58&#58;83874"></script>
<script type="text/javascript" src="/rsrc.php/82857/js/lib/type/list.js?58&#58;82857"></script>
<script type="text/javascript" src="/rsrc.php/83911/js/lib/ua/ua.js?58&#58;83911"></script>
<script type="text/javascript" src="/rsrc.php/87083/js/lib/event/extensions.js?58&#58;87083"></script>
<script type="text/javascript" src="/rsrc.php/85647/js/lib/event/onload.js?58&#58;85647"></script>
<script type="text/javascript" src="/rsrc.php/82857/js/lib/event/controller.js?58&#58;82857"></script>
<script type="text/javascript" src="/rsrc.php/83911/js/lib/ua/adjust.js?58&#58;83911"></script>
<script type="text/javascript" src="/rsrc.php/82857/js/lib/ua/cookie.js?58&#58;82857"></script>
<script type="text/javascript" src="/rsrc.php/83874/js/lib/string/escape.js?58&#58;83874"></script>
<script type="text/javascript" src="/rsrc.php/82857/js/lib/string/misc.js?58&#58;82857"></script>
<script type="text/javascript" src="/rsrc.php/83874/js/lib/string/sprintf.js?58&#58;83874"></script>
<script type="text/javascript" src="/rsrc.php/83874/js/lib/string/uri.js?58&#58;83874"></script>
<script type="text/javascript" src="/rsrc.php/83874/js/lib/util/util.js?58&#58;83874"></script>
<script type="text/javascript" src="/rsrc.php/83874/js/lib/util/configurable.js?58&#58;83874"></script>
<script type="text/javascript" src="/rsrc.php/87083/js/lib/math/vector.js?58&#58;87083"></script>
<script type="text/javascript" src="/rsrc.php/83874/js/lib/math/rect.js?58&#58;83874"></script>
<script type="text/javascript" src="/rsrc.php/86410/js/lib/math/extensions.js?58&#58;86410"></script>
<script type="text/javascript" src="/rsrc.php/88189/js/base.js?58&#58;88189"></script>
<script type="text/javascript" src="/rsrc.php/86747/js/lib/dom/dom.js?58&#58;86747"></script>
<script type="text/javascript" src="/rsrc.php/83874/js/lib/dom/css.js?58&#58;83874"></script>
<script type="text/javascript" src="/rsrc.php/83874/js/lib/dom/form.js?58&#58;83874"></script>
<script type="text/javascript" src="/rsrc.php/83874/js/lib/dom/html.js?58&#58;83874"></script>
<script type="text/javascript" src="/rsrc.php/83874/js/lib/dom/misc.js?58&#58;83874"></script>
<script type="text/javascript" src="/rsrc.php/83478/js/lib/dom/control.js?58&#58;83478"></script>
<script type="text/javascript" src="/rsrc.php/83478/js/lib/dom/controls/text_input.js?58&#58;83478"></script>
<script type="text/javascript" src="/rsrc.php/83478/js/lib/dom/controls/text_area.js?58&#58;83478"></script>
<script type="text/javascript" src="/rsrc.php/87712/js/lib/net/async.js?58&#58;87712"></script>
<script type="text/javascript" src="/rsrc.php/84002/js/lib/net/async_signal.js?58&#58;84002"></script>
<script type="text/javascript" src="/rsrc.php/84117/js/deprecated.js?58&#58;84117"></script>
<script type="text/javascript" src="/rsrc.php/84002/js/apps_menu.js?58&#58;84002"></script>
<script type="text/javascript" src="/rsrc.php/72979/js/socialads.js?58&#58;72979"></script>
<script type="text/javascript" src="/rsrc.php/88471/js/intl.js?58&#58;88471"></script>
<script type="text/javascript" src="/rsrc.php/84183/js/captcha.js?58&#58;84183"></script>
<script type="text/javascript" src="/rsrc.php/84183/js/recaptcha_ajax.js?58&#58;84183"></script>
<script type="text/javascript" src="/rsrc.php/77307/js/dynamic_dialog.js?58&#58;77307"></script>
<script type="text/javascript" src="/rsrc.php/71785/js/editaccount.js?58&#58;71785"></script>
<script type="text/javascript" src="/rsrc.php/88533/js/lib/ui/typeaheadpro.js?58&#58;88533"></script>
<script type="text/javascript" src="/rsrc.php/72123/js/typeahead_ns.js?58&#58;72123"></script>
<script type="text/javascript" src="/rsrc.php/88535/js/dialogpro.js?58&#58;88535"></script>
<script type="text/javascript" src="/rsrc.php/88225/js/suggest.js?58&#58;88225"></script>
<script type="text/javascript" src="/rsrc.php/87935/js/networks.js?58&#58;87935"></script>
<script type="text/javascript" src="/rsrc.php/70930/js/network_actions.js?58&#58;70930"></script>
<script type="text/javascript" src="/rsrc.php/68239/js/editnetworks.js?58&#58;68239"></script>
<script type="text/javascript" src="/rsrc.php/75963/js/editlanguages.js?58&#58;75963"></script>
<script type="text/javascript" src="/rsrc.php/82857/js/page/edit_account.js?58&#58;82857"></script>
<script type="text/javascript" src="/rsrc.php/86339/js/editregion.js?58&#58;86339"></script>
<script type="text/javascript" src="/rsrc.php/87987/js/lib/ui/dialog.js?58&#58;87987"></script>
<script type="text/javascript" src="/rsrc.php/87639/js/error_data.js?58&#58;87639"></script>
<script type="text/javascript" src="/rsrc.php/72172/js/search_typeaheadpro.js?58&#58;72172"></script>
<script type="text/javascript" src="/rsrc.php/83874/js/lib/ui/animation.js?58&#58;83874"></script>
<script type="text/javascript" src="/rsrc.php/86410/js/support/json.js?58&#58;86410">
...

Άβαταρ μέλους
cherouvim
Script Master
Δημοσιεύσεις: 3137
Εγγραφή: 13 Ιούλ 2005 22:56
Τοποθεσία: Athens, Greece
Επικοινωνία:

css/js files - no caching

Δημοσίευση από cherouvim » 23 Μαρ 2008 07:58

1) OMG! Πολλά αρχεία!

2) OMG! Είσαι facebook;

Άβαταρ μέλους
skeftomilos
Script Master
Δημοσιεύσεις: 2888
Εγγραφή: 07 Ιαν 2005 07:22
Τοποθεσία: Αθήνα

css/js files - no caching

Δημοσίευση από skeftomilos » 23 Μαρ 2008 08:28

Μπα, απλά είδα κάπου το παρακάτω σχόλιο και πέρασα να δω τι γίνεται.
1) facebook platform launched
2) land grab in progress
3) nobody makes money on facebook apps

Άβαταρ μέλους
dik_
Δημοσιεύσεις: 476
Εγγραφή: 07 Ιουν 2007 11:28

css/js files - no caching

Δημοσίευση από dik_ » 28 Μαρ 2008 00:44

Λοιπόν, όπως είπα και παλιότερα, μέχρι πριν λίγο χρησιμοποιούσα query string, αλλά επειδή μου βάλατε ψύλλους στ' αφτιά, είπα να το αλλάξω σε κάτι της μορφής

css/style.20080327.css

Παράλληλα είπα να κάνω combine τα assets που είναι πιθανότερο να ζητούνται μαζί, ώστε να μειώσω το overhead από το κάθε request. Το μερτζάρισμα όλων σε ένα δεν ενδεικνύεται μιας και με την παραμικρή αλλαγή κάθε client θα πρέπει να ξανακατεβάσει ένα μεγάλο αρχείο.

Επίσης καλό θα είναι τα blanks και comments σε css και js να αφαιρούνται. Προαιρετικά τα js μπορούν να συμπιεστούν με κάποιον απ' τους packers που κυκλοφορούν.

Ένα θέμα που προκύπτει είναι το production vs. dev environment που θίχτηκε και παραπάνω. Γι' αυτό έφτιαξα ένα scriptaki το οποίο κάνει χοντρικά τα εξής:
  • Συμπιέζει το περιεχόμενο των css και js, αφαιρώντας blanks/comments
  • Δημιουργεί νέα αρχείο με την τρέχουσα ημερομηνία
  • Χώνει μέσα το συμπιεσμένο περιεχόμενο.
Στο σκριπτ έχω ορίσει groups αρχείων, συσχετίζοντας π.χ. τα a.js, b.js και c.js που βρίσκονται σε dev με το abc της production έκδοσης. Κάπου στο web app μου έχω μια global μεταβλητή που ορίζει το περιβάλλον. Αν είναι dev τότε ένα loop φορτώνει όλα τα αρχικά αρχεία, δηλ a.js, b.js και c.js. Αν είναι production τότε φορτώνει το abc.20080327.js.

Με ένα .bat η όλη φάση γίνεται με ένα διπλό κλικ!

Σίγουρα υπάρχουν καλύτεροι τρόποι, αλλά κάπως έπρεπε να αρχίσω :D

Περισσότερα εδώ και κυρίως εδώ. ;)

Άβαταρ μέλους
skeftomilos
Script Master
Δημοσιεύσεις: 2888
Εγγραφή: 07 Ιαν 2005 07:22
Τοποθεσία: Αθήνα

css/js files - no caching

Δημοσίευση από skeftomilos » 28 Μαρ 2008 03:02

Σωστός. Πρόσεχε μόνο στην αφαίρεση των σχολίων, μπορεί να υπάρχουν conditional comments που πρέπει να διατηρηθούν:

Κώδικας: Επιλογή όλων

var IS_IE /*@cc_on = true @*/
var IS_IE6 /*@cc_on @if &#40;@_jscript_version <= 5.6&#41; = true @end @*/

Απάντηση

Επιστροφή στο “Γενικές ερωτήσεις κατασκευής ιστοσελίδων”

Μέλη σε σύνδεση

Μέλη σε αυτήν τη Δ. Συζήτηση: Δεν υπάρχουν εγγεγραμμένα μέλη και 0 επισκέπτες