RE:NODE

ვებ ჰოსტინგი12 წუთის საკითხავი

Static საიტის ჰოსტინგი: build, ატვირთვა და caching

როგორ მოაწყო static ან Jamstack საიტის ჰოსტინგი სწორად: რომელი საქაღალდე ატვირთო, სუფთა URL-ები, caching წესები, გადამისამართებები და რას ვერ აკეთებს static საიტი.

0 მკითხველი

static საიტი ფაილების საქაღალდეა, რომელსაც web სერვერი უცვლელად გასცემს. არ არის აპლიკაცია, რომელიც უნდა გაეშვას, მონაცემთა ბაზა, რომლის backup-იც უნდა აიღო, და არაფერი, რასაც სამშაბათს patch უნდა დაადო. კარგი ჰოსტინგი ოთხ გადაწყვეტილებაზე დადის: რომელ საქაღალდეს ტვირთავ, როგორ ასახავს URL-ები ფაილებს, რას ამბობს cache header-ები და რა ხდება იმ URL-ებთან, რომლებსაც ხურავ. სწორად გააკეთე და 1 GB გეგმა გასცემს საიტს, რომელსაც თხუთმეტი წლის წინ პატარა ფლოტი დასჭირდებოდა.

ეს მთელი საქმეა, გავრცელებული გენერატორების build-იდან იმ რამეებამდე, რასაც static საიტი თავისით ნამდვილად ვერ აკეთებს.

რა არის static ჰოსტინგი და რა გიჯდება ის#

სერვერი თითქმის არაფერს აკეთებს: მოთხოვნა მოდის /about/-ზე, ის პოულობს about/index.html-ს დისკზე და აგზავნის. PHP პროცესი არ იწყება, query არ სრულდება. სწორედ ამიტომ არის static საიტები ნაგულისხმევად სწრაფი და სწორედ ამიტომ არის პირველ ბაიტამდე დრო შეზღუდული მხოლოდ ქსელითა და დისკით.

ის, რასაც თმობ, არის ყველაფერი, რაც სერვერზე მოთხოვნის დროს უნდა მოხდეს:

  • ფორმები. ფორმას სჭირდება ადგილი, სადაც გაიგზავნება. static ჰოსტს არ აქვს.
  • ყველაფერი მომხმარებლის მიხედვით. ლოგინები, კალათები, დაშბორდი. ამის გაკეთება კლიენტის მხარეს API-ს წინააღმდეგ შეიძლება, მაგრამ API სადმე უნდა მუშაობდეს.
  • სერვერის მხარის ძებნა. გვერდები ფაილებია, ამიტომ ძებნა ან ვიზიტორის ბრაუზერში ხდება, ან მესამე მხარესთან.
  • კონტენტის რედაქტირება არატექნიკური ადამიანების მიერ. CMS-ის გარეშე ცვლილება rebuild-ია, თუ headless CMS-ს და build hook-ს არ დაამატებ.

რასაც ინარჩუნებ, არის შესაძლებლობა, საიტი ათ წუთში სადმე გადაიტანო, და საიტი, რომლის გატეხვაც შეუძლებელია plugin-ით, რომელიც არავის განუახლებია. მარკეტინგული საიტის, დოკუმენტაციის, პორტფოლიოს ან ბლოგისთვის ეს გარიგება თითქმის ყოველთვის სწორია. მაღაზიისთვის - არა: იხილე WooCommerce ჰოსტინგის მოთხოვნები ან CMS სწორად გაუშვი.

სასარგებლო შუალედური პოზიცია არის static საიტი გეგმაზე, რომელიც PHP-საც უშვებს. მთელი საიტი ფაილებია და ერთი პატარა PHP სკრიპტი საკონტაქტო ფორმას ამუშავებს. ეს არის ფორმა, რომელიც პატარა ბიზნესის საიტების უმეტესობას უნდა ჰქონდეს, და მას არანაირი framework არ სჭირდება.

რა ატვირთო: build შედეგი გენერატორის მიხედვით#

ყველაზე გავრცელებული შეცდომაა პროექტის ატვირთვა build-ის ნაცვლად. შენი რეპოზიტორია შეიცავს წყაროებს, კონფიგურაციას, node_modules-სა და ისტორიას. web სერვერს არცერთი მათგანი არ უნდა ხედავდეს. ყოველი გენერატორი მზა საქაღალდეს წერს; ეს საქაღალდე და მხოლოდ მისი შიგთავსი მიდის სერვერზე.

გენერატორიBuild ბრძანებაგამომავალი საქაღალდე
Hugohugopublic/
Jekylljekyll build_site/
Eleventynpx @11ty/eleventy_site/
Astronpm run builddist/
Vite (plain)npm run builddist/
SvelteKit (static adapter)npm run buildbuild/
Next.js (output: 'export')npm run buildout/
Nuxt (nuxt generate)npm run generate.output/public/
Gatsbygatsby buildpublic/
Docusaurusnpm run buildbuild/
MkDocsmkdocs buildsite/

ატვირთვამდე შეამოწმე შედეგი. ორი რამის დადასტურება ყოველ ჯერზე ღირს: რომ index.html ზედა დონეზე დგას და არა ერთი საქაღალდით ქვემოთ, და რომ asset URL-ები root-relative-ია. საიტი, რომელიც base path-ით /my-project/ აიგო და დომენის ძირში გაიშვა, გაძლევს გვერდს სტილის გარეშე და ბრაუზერის კონსოლს 404-ებით სავსეს. ყველა გენერატორს ამისთვის პარამეტრი აქვს - baseURL Hugo-ში, base Astro-სა და Vite-ში, baseurl Jekyll-ში - და ის უნდა ემთხვეოდეს იმას, სადაც საიტი ნამდვილად ცხოვრობს.

Build გააკეთე შენს მანქანაზე ან CI-ში და არა web სერვერზე. 1 GB გეგმას build-ის გაშვება შეუძლია, მაგრამ დიდი JavaScript პროექტი მეხსიერების ზღვარს დაეჯახება, ხოლო ჰოსტი, რომელიც კონტეინერს ზღვარზე აჩერებს, build-ს შუაში გააჩერებს. სერვერზე Node-ის დაყენების მიზეზი არ არსებობს, როცა მისი მთელი საქმე ფაილების გაგზავნაა.

ფაილების სერვერზე მიღება#

სამი გზა, იმის მიხედვით, რამდენად მოგეწონება.

rsync, თუ SSH გაქვს. ის მხოლოდ იმას აკოპირებს, რაც შეიცვალა, და შეუძლია წაშალოს ის, რაც მოხსენი, რაც მნიშვნელოვანია, რადგან ძველი ფაილებია გზა, რომლითაც წაშლილი გვერდი წელიწადს ონლაინ რჩება.

bash
$ rsync -avz --delete --exclude '.DS_Store' dist/ user@example.com:/var/www/site/

SFTP, რომელიც ყველა ჰოსტს აქვს. გამოიყენე კლიენტი, რომელსაც ლოკალური საქაღალდის mirror-ი შეუძლია, და გახსოვდეს, რომ უმეტესი მათგანი დისტანციურ ფაილებს, რომლებიც ლოკალურად აღარ გაქვს, არ წაშლის, თუ არ სთხოვ. ატვირთე დროებით საქაღალდეში და შეცვალე, თუ გინდა, რომ ცვლილება ატომური იყოს.

არქივი, რაც ყველაზე სწრაფი ვარიანტია პანელის ჰოსტინგზე. დააარქივე build, ატვირთე ერთი ფაილი, გახსენი ადგილზე. RE:NODE-ზე ფაილების მენეჯერი არქივებს იქვე ხსნის და აქვს ბრაუზერში რედაქტორი ფაილისთვის, რომლის გასწორებაც შემდეგ აუცილებლად დაგჭირდება, ხოლო SFTP მონაცემები გაიცემა თითო სერვერზე - SFTP და ფაილების მენეჯერი შეიცავს კავშირის დეტალებს.

რასაც არ უნდა იყენებდე, გამორიცხე node_modules, .git, src და შენი environment ფაილები. .git-ის ატვირთვა შენს მთელ ისტორიას აქვეყნებს, ყველაფრის ჩათვლით, რაც დააკომიტე და მოგვიანებით წაშალე, და ავტომატური სკანერები ყოველ საიტზე, რომელსაც პოულობენ, /.git/config-ს ეძებენ.

URL-ები: სუფთა გზები, 404 გვერდები და SPA fallback#

უმეტესი გენერატორი წერს about/index.html-ს და არა about.html-ს, რადგან სერვერი, რომელსაც /about/ მისცეს, ამ საქაღალდეში index.html-ს ეძებს. ეს nginx-ის ნაგულისხმევი ქცევაა index index.html;-ით და პრაქტიკულად ყველა სხვა web სერვერისა, ამიტომ კარგად აგებულ static საიტს სუფთა URL-ებისთვის კონფიგურაცია არ სჭირდება.

სადაც სერვერის ბლოკს აკონტროლებ, სამი ხაზი თითქმის ყველაფერს ფარავს:

nginx
root /var/www/site;index index.html;location / {    try_files $uri $uri.html $uri/ =404;}error_page 404 /404.html;

try_files თითოეულ კანდიდატს რიგრიგობით ამოწმებს: ზუსტ ფაილს, იმავე გზას .html-ის დამატებით - რაც /about-ს ამუშავებს გენერატორისთვის, რომელმაც about.html დაწერა - შემდეგ საქაღალდეს, შემდეგ 404-ს. error_page ხაზი ის არის, რაც სერვერის ნაცრისფერის ნაცვლად შენს დაპროექტებულ 404 გვერდს აჩვენებს. შენი გენერატორი თითქმის აუცილებლად 404.html-ს უკვე აგებს.

single-page აპლიკაცია განსხვავებულია: ყოველი გზა ერთსა და იმავე HTML-ს აბრუნებს და router-ს ანებებს დანარჩენს.

nginx
location / {    try_files $uri $uri/ /index.html;}

ეს fallback მოსახერხებელია და შეცდომებს მალავს, რადგან asset-ის გზაში გაშვებული შეცდომა 404-ის ნაცვლად 200-ით შენს HTML-ს აბრუნებს, ბრაუზერი კი მას JavaScript-ად გარჩევას ცდილობს. თუ კონსოლში ხედავ „Unexpected token '<'“, ეს მოხდა.

თუ სერვერის კონფიგურაციის რედაქტირება არ შეგიძლია, ააგე საიტი ისე, რომ წესები არ სჭირდებოდეს. გვერდი-თითო-საქაღალდე გამომავალი რეალური index.html ფაილებით ყველგან მუშაობს, try_files არ სჭირდება და ნებისმიერ სხვა ჰოსტზე გადასვლას უძლებს. გაითვალისწინე, რომ .htaccess ფაილები nginx-ზე არაფერს აკეთებს, რასაც უმეტესი თანამედროვე ჰოსტინგი უშვებს - Apache-ისთვის ნაპოვნი ინსტრუქციები ჩუმად ეფექტს არ გამოიღებს.

Caching და შეკუმშვა#

აქ იგება ან იკარგება static საიტი და ეს ორი წესია.

Fingerprint-იანი asset-ები სამუდამოდ cache-დება. თანამედროვე build ინსტრუმენტები ფაილებს ასახელებენ შიგთავსის hash-ით - app.9f2c1b.css. ფაილი შეიცვალა, სახელი იცვლება. რადგან სახელი შიგთავსისთვის უნიკალურია, ბრაუზერს არასოდეს სჭირდება ხელახლა შემოწმება:

nginx
location ~* \.(css|js|woff2|avif|webp|png|jpg|svg)$ {    expires 1y;    add_header Cache-Control "public, max-age=31536000, immutable";}

HTML არასოდეს cache-დება დიდი ხნით. ეს ის ფაილია, რომელიც ყველა დანარჩენზე მიუთითებს, ამიტომ ის უნდა იყოს ახალი, თორემ deploy საათებში გამოჩნდება:

nginx
location ~* \.html$ {    add_header Cache-Control "public, no-cache";}

no-cache არ ნიშნავს „ნუ შეინახავ“. ის ნიშნავს „შეინახე, მაგრამ ხელახლა გამოყენებამდე იკითხე“, რაც უმეტესად იაფ 304 პასუხს გაძლევს და მყისიერ განახლებას, როცა აქვეყნებ. HTTP caching header-ები ახსნილი გადის ყველა დირექტივასა და იმას, რასაც proxy-ები მათთან აკეთებენ.

შეკუმშვა მეორე ნახევარია. ტექსტი დაახლოებით 70-80 პროცენტით იკუმშება, ამიტომ 200 KB HTML ფაილი ქსელში დაახლოებით 50 KB ხდება. nginx თავისით ამკუმშავს gzip on;-ითა და სწორი gzip_types-ით და შეუძლია წინასწარ შეკუმშული ფაილების გაცემა gzip_static on;-ით, თუ შენი build თითოეული asset-ის გვერდით .gz-ს წერს, რაც სერვერს მოთხოვნის დროს არაფერს ჯდება. ნუ შეკუმშავ სურათებს ან ვიდეოს: ისინი უკვე შეკუმშულია და ხელახლა შეკუმშვა CPU-ს ტყუილად ხარჯავს.

სურათებისთვის ფაილის ფორმატი ნებისმიერ სერვერის პარამეტრზე მეტს ღირს. მთავარი სურათი, რომელიც 2 MB PNG-ად გაიტანეს და 800 პიქსელის სიგანეზე აჩვენეს, „სწრაფი“ საიტის შენელების ყველაზე გავრცელებული მიზეზია. გაიტანე იმ ზომით, რა ზომითაც ჩანს, გამოიყენე WebP ან AVIF და ყოველთვის დააყენე width და height ატრიბუტები, რომ ბრაუზერმა ადგილი დაჯავშნოს და განლაგება არ გადახტეს.

გადამისამართებები და URL-ის შეცვლა ტრაფიკის დაკარგვის გარეშე#

ყოველი URL, რომელიც ოდესმე გამოაქვეყნე, დანაპირებია. როცა საიტს ხელახლა აწყობ, ძველი გზები მუშაობა უნდა განაგრძობდეს, თორემ მათზე მიმართული ბმულები ფასს კარგავს.

nginx
location = /old-page.html { return 301 /new-page/; }location ^~ /blog/2019/ { return 301 /archive/; }

გამოიყენე 301 გადატანისთვის, რომელიც მუდმივია, რასაც თითქმის ყოველთვის გულისხმობ. ბრაუზერები 301-ს აგრესიულად cache-ავენ, ამიტომ გამოსცადე curl -I-ით deploy-მდე და არასოდეს გამოიყენო 301 იმაზე, რისი უკან შეცვლაც შეიძლება. 302 დროებითია და უსაფრთხო არჩევანია, როცა დარწმუნებული არ ხარ.

სადაც სერვერის კონფიგურაციაზე წვდომა არ გაქვს, <meta http-equiv="refresh"> გვერდი ძველ გზაზე სარეზერვო ვარიანტია. ის ადამიანებისთვის მუშაობს, ბმულის ღირებულების უმეტესობას საბოლოოდ გადასცემს და ყველა მხრივ 301-ზე უარესია. გამოიყენე მხოლოდ მაშინ, როცა ალტერნატივა მკვდარი URL-ია.

მეორე გადამისამართება, რომელიც ყველა საიტს სჭირდება, apex-სა და www ფორმას შორისაა: აირჩიე ერთი კანონიკური ჰოსტი და მეორე გადაამისამართე მასზე 301-ით, რომ ორი ვერსია ერთმანეთს არ შეეჯიბროს. www თუ apex დომენი და გადამისამართებები DNS მხარეს განიხილავს, იმის ჩათვლით, რატომ არ არის apex CNAME ის, რაც შენს რეგისტრატორს აუცილებლად შეუძლია.

ფორმები, ძებნა და კომენტარები backend-ის გარეშე#

სამი ფუნქცია, რომელიც ხალხს აკლდება, და პატიოსანი ვარიანტები თითოეულისთვის.

ფორმები. ან გააგზავნე მესამე მხარის ფორმის სერვისზე, ან დაამატე პატარა PHP სკრიპტი გეგმაზე, რომელიც PHP-ს უშვებს. სკრიპტი დაახლოებით ოცი ხაზია: გადაამოწმე ველები, გააგზავნე შეტყობინება, გადამისამართე მადლობის გვერდზე. ერთი გაფრთხილება, რომელიც ყველას ეჭრება: PHP-ის mail() ფუნქციას ლოკალური mail transfer agent სჭირდება, ჰოსტინგის კონტეინერს კი ის ზოგადად არ აქვს. გააგზავნე SMTP პროვაიდერის API-ით, იმ დომენიდან, რომლის ჩანაწერებიც გაქვს დაყენებული - რატომ ხვდება შენი დომენიდან ფოსტა spam-ში განმარტავს SPF-ს, DKIM-სა და DMARC-ს, რომლებიც დაგჭირდება იმის მიუხედავად, ვინ გზავნის ფოსტას. RE:NODE ელფოსტას არ ჰოსტავს, ამიტომ შენი დომენის ფოსტა ყოველთვის სხვისი სერვისია.

ძებნა. რამდენიმე ათას გვერდამდე საიტისთვის კლიენტის მხარის ინდექსი სწორი პასუხია: Pagefind აგებს მას build-ის დროს და ფრაგმენტებს მოთხოვნით ტვირთავს, Lunr და Fuse ინდექსირებას ბრაუზერში აკეთებენ. ამის მიღმა - hosted საძიებო სერვისი. web სერვერზე არაფერი იცვლება ორივე შემთხვევაში.

კომენტარები. მესამე მხარის ვიჯეტი, ბმული სხვაგან არსებულ დისკუსიაზე ან არაფერი. „არაფერი“ დასაცავი არჩევანია და ერთადერთი, რომელსაც კონფიდენციალურობის შედეგები არ აქვს.

რომელიმეს დამატება საიტს static-ობას არ უკარგავს. ხელის წესი: თუ მას სერვერზე დისკზე ჩაწერა სჭირდება, ეს აღარ არის static საიტი და გადაწყვეტილება შეგნებულად უნდა მიიღო და არა შემთხვევით.

დომენი, სერტიფიკატი და გაშვების checklist#

დომენის static ფაილებზე მიმართვა იგივეა, რაც სხვაგან: A ჩანაწერი apex-ისთვის და ჩანაწერი www-ისთვის, შემდეგ სერტიფიკატი ორივე სახელისთვის. ჰოსტზე, რომელსაც წინ reverse proxy უდგას, ჩანაწერს მიუთითებ მისამართზე, რომელსაც გაძლევს, და სერტიფიკატი გაიცემა, როცა სახელი იქ გადაწყდება - RE:NODE-ზე ეს განახლება ავტომატურად ხდება 21-დღიან ფანჯარაში, წლიური ამოცანის გარეშე. დომენის მიმართვა შენს სერვერზე განიხილავს ოპერაციების თანმიმდევრობას, ხოლო HTTPS და Let's Encrypt ახსნილი - რატომ ვარდება გაცემა, როცა DNS ჯერ მზად არ არის.

რამეს გამოცხადებამდე:

  1. ჩატვირთე საიტი https://-ით და შეამოწმე, რომ ბრაუზერი mixed-content გაფრთხილებას არ აჩვენებს.
  2. შეამოწმე, რომ /404 აბრუნებს შენს 404 გვერდს 404 სტატუსით და არა 200-ით.
  3. შეამოწმე, რომ robots.txt და sitemap.xml არსებობს და კანონიკურ ჰოსტს ჩამოთვლის.
  4. გაჰყევი საკუთარ გადამისამართებებს curl -I-ით და დარწმუნდი, რომ თითოეული ერთი ნახტომია.
  5. ჩატვირთე საიტი ტელეფონზე მობილური ინტერნეტით და არა ოფისის wifi-ზე.

პრობლემების მოგვარება#

გვერდი სტილის გარეშე იტვირთება. base path არასწორია, ან CSS 404-ს აბრუნებს. გახსენი network ჩანართი: თუ /assets/app.css HTML-ს აბრუნებს, შენი SPA fallback მას იჭერს და ნამდვილი ფაილი სხვაგანაა.

საიტის ნაცვლად დირექტორიის სია. იქ, სადაც სერვერი ეძებს, index.html არ არის და დირექტორიის ინდექსები ჩართულია. შეამოწმე, რომ build საქაღალდის შიგთავსი ატვირთე და არა თავად საქაღალდე, რის გამოც ყველაფერი ერთი დონით ქვემოთ აღმოჩნდება.

ცვლილებები არ ჩანს. შენსა და ფაილს შორის რაღაც cache-ავს. გადატვირთე cache-ის გვერდის ავლით, შეამოწმე Cache-Control header, რომელსაც სერვერი HTML-ზე აგზავნის, და თუ CDN-ის უკან ხარ, გაწმინდე ის. ეს არის HTML-ზე გრძელი max-age-ის ფასი და მიზეზი, რის გამოც მას არ უნდა დააყენო.

403 Forbidden ყველა გვერდზე. ფაილების უფლებები. ფაილები web სერვერის მომხმარებელს უნდა შეეძლოს წაიკითხოს, ხოლო დირექტორიებს execute ბიტი სჭირდება გასავლელად: 644 ფაილებისთვის, 755 დირექტორიებისთვის.

საიტი მუშაობს `www`-ზე, მაგრამ არა apex-ზე, ან პირიქით. სერტიფიკატში მხოლოდ ერთი სახელია ან მხოლოდ ერთს აქვს DNS ჩანაწერი. ორივეს ორივე სჭირდება.

შენთვის ყველაფერი სწრაფია და ვიზიტორებისთვის ნელი. შენ სერვერთან ახლოს ხარ და ისინი არა. static საიტის დარჩენილი დაყოვნება მანძილია, რასაც უფრო დიდი გეგმა არ ცვლის - იხილე TTFB, Core Web Vitals და რას ცვლის ჰოსტინგი და დააყენე CDN წინ, თუ შენი აუდიტორია კონტინენტებზეა გაფანტული.

FAQ#

რამდენი ჰოსტინგი სჭირდება static საიტს სინამდვილეში?

ძალიან ცოტა. უმეტესი static საიტი რამდენიმე მეგაბაიტი HTML-ია და რამდენიმე ათეული მეგაბაიტი სურათი, და ფაილის გაცემა თითქმის არ ხარჯავს CPU-ს. ნებისმიერი ჰოსტის უმცირესი გეგმა ჩვეულებრივ სწორია და გეგმას აუმჯობესებ შენახვისთვის ან ისეთი ტრაფიკისთვის, რომელიც პატარა საიტისთვის უჩვეულოდ მაღალია.

მჭირდება Node.js სერვერზე?

არა. Node საიტს აგებს; არ აგზავნის. ააგე ლოკალურად ან CI-ში და ატვირთე შედეგი. თუ გინდა, რომ Node სერვერზე მუშაობდეს, ის, რაც გაქვს, აპლიკაციაა და არა static საიტი და მას აპლიკაციის გეგმა სჭირდება.

შემიძლია რამდენიმე static საიტის ჰოსტინგი ერთ გეგმაზე?

გეგმის შენახვისა და proxy ლიმიტების ფარგლებში - კი. თითოეულ საიტს სჭირდება საკუთარი საქაღალდე და საკუთარი hostname, რომელიც სერვერზე მიუთითებს. უფრო დიდი დონეები მეტ შენახვასა და proxy სიმძლავრეს ატარებენ.

აუცილებელია CDN?

მხოლოდ თუ შენი ვიზიტორები სერვერისგან შორს არიან ან დიდ მედიას გასცემ. CDN ასლებს ვიზიტორთან ახლოს cache-ავს, რაც static asset-ებისთვის მანძილს განტოლებიდან იღებს. ის არაფერს აკეთებს ნელი წყაროსთვის, რომელიც cache-ში არმყოფ HTML-ს გასცემს, და ამატებს ფენას დასაბაგებლად - Cloudflare ვებსაიტებისთვის და გეიმ სერვერებისთვის განიხილავს, რას აკეთებს და რას არ აკეთებს proxy.

როგორ გავაკეთო ავტომატური deploy push-ის დროს?

ააგე CI-ში და დააყენე job, რომ შედეგი SFTP-ით ან rsync-ით ატვირთოს. deploy ერთ ნაბიჯად შეინახე, რომელიც საქაღალდის შიგთავსს ცვლის, რომ ნახევრად დასრულებული ატვირთვა ნახევრად გატეხილ საიტად არ იქცეს.

რა აკეთებს static საიტის backup-ს?

შენი რეპოზიტორია წყაროს backup, მაგრამ არა build-ის და არა იმის, რაც შემდეგ ატვირთე. აიღე backup ასევე სერვირებული საქაღალდის, განრიგით, და ერთხელ აღადგინე, რომ დაამტკიცო მუშაობს - backup-ები, რომლებიც მართლა აღდგება განმარტავს, რატომ არის ეს მეორე ნახევარი მნიშვნელოვანი.


კომენტარები

სრულიად ანონიმურად: ანგარიშის, ელფოსტის და cookie-ის გარეშე. ინახება მხოლოდ სახელი, ტექსტი და დრო - სხვა არაფერი. ბმულების რაოდენობა ლიმიტირებულია.

0/2000