Xin chào @Ash G:
Tôi đã không theo dõi 100% khi bạn đặc biệt gặp vấn đề vì vậy tôi không chắc chắn tôi thực sự có thể trả lời từng vấn đề của bạn nhưng tôi có thể giải thích cách thực hiện việc này từ đầu . Và trừ khi những gì bạn đang làm có liên quan nhiều hơn một chút thì bạn đã đề cập đến nó một chút công việc hơn tôi nghĩ bạn đã dự đoán nhưng nó vẫn hoàn toàn có thể làm được. Và ngay cả khi tôi bao quát nhiều nền tảng mà bạn đã biết thì rất có thể những người khác có ít kiến thức hoặc kinh nghiệm sẽ tìm thấy điều này thông qua Google và cũng được nó giúp đỡ.
Bootstrap WordPress với /wp-load.php
Điều đầu tiên chúng ta cần làm trong my_theme_css.php
tệp của bạn là bootstrap các chức năng thư viện cốt lõi của WordPress. Các dòng tải mã sau đây /wp-load.php
. Nó sử dụng $_SERVER['DOCUMENT_ROOT']
để xác định vị trí gốc của trang web để bạn không phải lo lắng về nơi bạn lưu trữ tệp này trên máy chủ của mình; giả sử DOCUMENT_ROOT
được đặt chính xác vì nó luôn phải dành cho WordPress thì điều này sẽ khởi động WordPress:
<?php
include_once("{$_SERVER['DOCUMENT_ROOT']}/wp-load.php");
Vì vậy, đó là phần dễ dàng. Tiếp đến là phần khó khăn ...
Các tập lệnh PHP phải xử lý tất cả các bộ đệm logic
Đây là nơi tôi cá là bạn có thể đã vấp ngã vì tôi chắc chắn đã làm như vậy khi tôi đang cố gắng tìm ra cách trả lời câu hỏi của bạn. Chúng ta đã quá quen với các chi tiết lưu trữ được xử lý bởi máy chủ web Apache đến nỗi chúng ta quên hoặc thậm chí không nhận ra rằng chúng ta phải tự làm mọi việc nặng nhọc khi tải CSS hoặc JS bằng PHP.
Chắc chắn tiêu đề hết hạn có thể là tất cả những gì chúng ta cần khi chúng ta có proxy ở giữa nhưng nếu yêu cầu gửi đến máy chủ web và tập lệnh PHP chỉ cần trả về nội dung và mã trạng thái "Ok" về bản chất bạn sẽ không có bộ nhớ đệm.
Trả lại "200 Ok" hoặc "304 không được sửa đổi"
Cụ thể hơn, tệp PHP của chúng tôi trả về CSS cần phản hồi chính xác với các tiêu đề yêu cầu được gửi bởi trình duyệt. Tập lệnh PHP của chúng tôi cần trả về mã trạng thái phù hợp dựa trên những gì các tiêu đề đó chứa. Nếu nội dung cần được phục vụ vì đó là yêu cầu lần đầu tiên hoặc vì nội dung đã hết hạn, tập lệnh PHP sẽ tạo ra tất cả nội dung CSS và trả về với "200 Ok" .
Mặt khác, nếu chúng tôi xác định dựa trên các tiêu đề yêu cầu liên quan đến bộ đệm mà trình duyệt máy khách đã có CSS mới nhất, chúng tôi không nên trả lại bất kỳ CSS nào và thay vào đó trả về với "304 Không được sửa đổi" . Quá nhiều dòng mã cho điều này tương ứng (tất nhiên bạn sẽ không bao giờ sử dụng cả hai dòng này đến dòng khác, tôi chỉ hiển thị theo cách đó ở đây để thuận tiện) :
<?php
header('HTTP/1.1 200 Ok');
header('HTTP/1.1 304 Not Modified');
Bốn hương vị của bộ nhớ đệm HTTP
Tiếp theo chúng ta cần xem xét các cách khác nhau HTTP có thể xử lý bộ đệm. Đầu tiên là những gì bạn đề cập; Expires
:
- Hết hạn :
Expires
Tiêu đềnàymong đợi một ngày ởđịnh dạng( chức năng PHPgmdate()
)'D, d M Y H:i:s'
có' GMT'
gắn thêm ( GMT là viết tắt của Giờ chuẩn Greenwich .) Về mặt lý thuyết nếu tiêu đề này được phục vụ trình duyệt và proxy xuôi dòng sẽ lưu trữ cho đến khi thời gian được chỉ định sau đó sẽ bắt đầu yêu cầu trang một lần nữa. Đây có lẽ là tiêu đề bộ nhớ đệm được biết đến nhiều nhất nhưng rõ ràng không phải là tiêu đề ưa thích để sử dụng; Kiểm soát bộ nhớ cache là tốt hơn . Điều thú vị trong thử nghiệm của tôilocalhost
với Safari 5.0 trên Mac OS XI là không bao giờ có thể khiến trình duyệt tôn trọngExpires
tiêu đề; nó luôn luônđã yêu cầu tệp lại (nếu ai đó có thể giải thích điều này tôi rất biết ơn.) Đây là ví dụ bạn đã đưa ra ở trên:
header("Expires: Thu, 31 Dec 2020 20:00:00 GMT");
- Kiểm soát bộ đệm :
Cache-Control
Tiêu đề dễ làm việc hơn so vớiExpires
tiêu đề vì bạn chỉ cần chỉ định số lượng thời gian tính bằng giây vìmax-age
có nghĩa là bạn không phải đưa ra định dạng ngày chính xác ở dạng chuỗi dễ bị sai . Ngoài ra,Cache-Control
cho phép một số tùy chọn khác như có thể yêu cầu khách luôn xác thực lại bộ đệm bằng cách sử dụngmustrevalidate
tùy chọn vàpublic
khi bạn muốn buộc lưu vào bộ đệm cho các yêu cầu không lưu trong bộ nhớ cache thông thường (tức là yêu cầu quaHTTPS
) và thậm chí không lưu bộ đệm nếu đó là những gì bạn cần (tức là bạn có thể muốn buộc theo dõi quảng cáo 1x1 pixel .GIF không được lưu trong bộ nhớ cache.) Giống nhưExpires
tôi cũng không thể để điều này hoạt động trong thử nghiệm ( có trợ giúp nào không?) Ví dụ sau lưu trữ trong khoảng thời gian 24 giờ (60 giây x 60 phút trong 24 giờ):
header("Cache-Control: max-age=".60*60*24.", public, must-revalidate");
- Last-Modified / If-Modified-Because : Sau đó, có cặp
Last-Modified
tiêu đề phản hồi vàModified-Since
cặp tiêu đềIf-request. Chúng cũng sử dụng định dạng ngày GMT giống nhưExpires
tiêu đề sử dụng nhưng chúng bắt tay giữa máy khách và máy chủ. Tập lệnh PHP cần gửi mộtLast-Modified
tiêu đề (nhân tiện, bạn chỉ nên cập nhật khi người dùng của bạn cập nhật CSS tùy chỉnh lần cuối) sau đó trình duyệt sẽ tiếp tục gửi lại giá trị tương tự như mộtIf-Modified-Since
tiêu đề và đó là trách nhiệm của tập lệnh PHP so sánh giá trị đã lưu với giá trị được gửi bởi trình duyệt. Đây là nơi tập lệnh PHP cần đưa ra quyết định giữa việc phục vụ a200 Ok
hoặc a304 Not Modified
. Đây là một ví dụ về việc phục vụLast-Modified
tiêu đề bằng cách sử dụng thời gian hiện tại ( không phải lànhững gì chúng ta muốn làm; xem ví dụ sau để biết những gì chúng ta thực sự cần):
header("Last-Modified: " . gmdate('D, d M Y H:i:s', time()).'GMT');
Và đây là cách bạn đọc Last-Modified
trình duyệt được trả về qua If-Modified-Since
tiêu đề:
$last_modified_to_compare = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
- ETag / If-none-Match : Và cuối cùng, có
ETag
tiêu đề phản hồi vàIf-None-Match
cặp tiêu đề yêu cầu. MãETag
thực sự chỉ là một mã thông báo mà PHP của chúng tôi đặt nó thành một giá trị duy nhất (thường dựa trên ngày hiện tại) và gửi đến trình duyệt và trình duyệt trả về nó. Giá trị hiện tại khác với giá trị mà trình duyệt trả về tập lệnh PHP của bạn sẽ tạo lại nội dung mà máy chủ200 Ok
tạo ra không có gì và phục vụ a304 Not Modified
. Dưới đây là ví dụ về cài đặtETag
sử dụng thời gian hiện tại:
header("ETag: " . md5(gmdate('D, d M Y H:i:s', time()).'GMT'));
Và đây là cách bạn đọc ETag
trình duyệt được trả về qua If-None-Match
tiêu đề:
$etag_to_match = $_SERVER['HTTP_IF_NONE_MATCH'];
Bây giờ chúng tôi đã trình bày tất cả những gì chúng ta hãy xem mã thực tế chúng ta cần:
Phục vụ tệp CSS qua init
vàwp_enqueue_style()
Bạn đã không thể hiện điều này nhưng tôi đoán rằng tôi sẽ thể hiện nó vì lợi ích của người khác. Đây là lời gọi hàm cho WordPress sử dụng my_theme_css.php
CSS của nó. Điều này có thể được lưu trữ trong functions.php
tệp của chủ đề hoặc thậm chí trong một plugin nếu muốn:
<?php
add_action('init','add_php_powered_css');
function add_php_powered_css() {
if (!is_admin()) {
$version = get_theme_mod('my_custom_css_version',"1.00");
$ss_dir = get_stylesheet_directory_uri();
wp_enqueue_style('php-powered-css',
"{$ss_dir}/my_theme_css.php",array(),$version);
}
}
Có một số điểm cần lưu ý:
- Sử dụng
is_admin()
để tránh tải CSS khi ở trong quản trị viên (trừ khi bạn muốn điều đó ...),
- Sử dụng
get_theme_mod()
để tải CSS với phiên bản mặc định 1.00
(nhiều hơn một chút),
- Sử dụng
get_stylesheet_directory_uri()
để lấy đúng thư mục cho chủ đề hiện tại, ngay cả khi chủ đề hiện tại là chủ đề con,
- Sử dụng
wp_enqueue_style()
để xếp hàng CSS để cho phép WordPress tải nó vào thời điểm thích hợp trong đó 'php-powered-css'
một tên tùy ý để tham chiếu như một phụ thuộc sau này ( nếu cần ) và trống array()
có nghĩa là CSS này không có phụ thuộc ( mặc dù trong thế giới thực, nó thường có một hoặc nhiều ) và
- Sử dụng
$version
; Có lẽ là điều quan trọng nhất, chúng tôi đang yêu wp_enqueue_style()
cầu thêm một ?ver=1.00
tham số vào /my_theme_css.php
URL để nếu phiên bản thay đổi, trình duyệt sẽ xem nó như một URL hoàn toàn khác (Nhiều hơn một chút về điều đó).
Cài đặt $version
và Last-Modified
khi người dùng cập nhật CSS
Vì vậy, đây là mẹo. Mỗi khi người dùng cập nhật CSS của họ, bạn muốn phân phát nội dung và không đợi cho đến khi 2020
bộ nhớ cache của trình duyệt hết thời gian chờ, phải không? Đây là một chức năng kết hợp với mã khác của tôi sẽ thực hiện điều đó. Mỗi khi bạn lưu trữ CSS được người dùng cập nhật, hãy sử dụng chức năng hoặc chức năng này tương tự như những gì có trong:
<?php
function set_my_custom_css($custom_css) {
$new_version = round(get_theme_mod('my_custom_css_version','1.00',2))+0.01;
set_theme_mod('my_custom_css_version',$new_version);
set_theme_mod('my_custom_css_last_modified',gmdate('D, d M Y H:i:s',time()).' GMT');
set_theme_mod('my_custom_css',$custom_css);
}
Các set_my_custom_css()
chức năng tự động increments phiên bản hiện tại của 0.01 (mà chỉ là một giá trị thặng dư tùy ý tôi nhặt) và nó cũng đặt ra ngày sửa đổi cuối cùng để ngay bây giờ và cuối cùng là lưu trữ CSS tùy chỉnh mới. Để gọi hàm này, nó có thể đơn giản như thế này (nơi new_custom_css
có thể sẽ được chỉ định thông qua người dùng được gửi $_POST
thay vì mã hóa như bạn thấy ở đây) :
<?php
$new_custom_css = 'body {background-color:orange;}';
set_my_custom_css($new_custom_css);
Điều này đưa chúng ta đến bước cuối cùng mặc dù có ý nghĩa:
Tạo CSS từ PHP Script
Cuối cùng chúng ta cũng được xem thịt, my_theme_css.php
file thực tế . Ở mức độ cao, nó kiểm tra cả If-Modifed-Since
so với lưu Last-Modified
giá trị và If-None-Match
chống lại ETag
được bắt nguồn từ lưu Last-Modified
giá trị và nếu không có thay đổi chỉ đặt tiêu đề để 304 Not Modifed
ngành đến cùng.
Tuy nhiên, nếu một trong hai đã thay đổi, nó tạo ra Expires
, Cache-Control
. Last-Modified
và Etag
các tiêu đề cũng như a 200 Ok
và chỉ ra rằng loại nội dung là text/css
. Chúng tôi có lẽ không cần tất cả những thứ đó nhưng được đưa ra cách bộ nhớ đệm tinh vi có thể với các trình duyệt và proxy khác nhau mà tôi cho rằng nó không gây hại cho tất cả các cơ sở. (Và bất cứ ai có nhiều kinh nghiệm hơn với bộ nhớ đệm HTTP và WordPress, vui lòng bấm nút nếu tôi có bất kỳ sắc thái nào sai.)
Có một vài chi tiết trong đoạn mã sau nhưng tôi nghĩ bạn có thể tự mình giải quyết chúng:
<?php
$s = $_SERVER;
include_once("{$s['DOCUMENT_ROOT']}/wp-load.php");
$max_age = 60*60*24; // 24 hours
$now = gmdate('D, d M Y H:i:s', time()).'GMT';
$last_modified = get_theme_mod('my_custom_css_last_modified',$now);
$etag = md5($last_modified);
if (strtotime($s['HTTP_IF_MODIFIED_SINCE']) >= strtotime($last_modified) || $s['HTTP_IF_NONE_MATCH']==$etag) {
header('HTTP/1.1 304 Not Modified');
} else {
header('HTTP/1.1 200 Ok');
header("Expires: " . gmdate('D, d M Y H:i:s', time()+$max_age.'GMT'));
header("Cache-Control: max-age={$mag_age}, public, must-revalidate");
header("Last-Modified: {$last_modified}");
header("ETag: {$etag}");
header('Content-type: text/css');
echo_default_css();
echo_custom_css();
}
exit;
function echo_custom_css() {
$custom_css = get_theme_mod('my_custom_css');
if (!empty($custom_css))
echo "\n{$custom_css}";
}
function echo_default_css() {
$default_css =<<<CSS
body {background-color:yellow;}
CSS;
echo $default_css;
}
Vì vậy, với ba bit chính của mã; 1.) add_php_powered_css()
chức năng được gọi bởi init
hook, 2.) set_my_custom_css()
chức năng được gọi bởi bất kỳ mã nào cho phép người dùng cập nhật CSS tùy chỉnh của họ và cuối cùng là 3.) my_theme_css.php
bạn nên thực hiện việc này.
Đọc thêm
Ngoài những bài đã được liên kết, tôi đã xem qua một vài bài viết khác mà tôi nghĩ là thực sự hữu ích về chủ đề này vì vậy tôi nghĩ rằng tôi nên liên kết chúng ở đây:
Phần kết:
Nhưng tôi sẽ hối hận khi rời khỏi chủ đề mà không đưa ra bình luận đóng.
Hết hạn trong 2020
? Có lẽ là quá cực đoan.
Đầu tiên, tôi thực sự không nghĩ rằng bạn muốn thiết lập Expires
đến năm 2020. Bất kỳ trình duyệt hoặc proxy nào tôn trọng Expires
sẽ không yêu cầu lại ngay cả khi bạn đã thực hiện nhiều thay đổi CSS. Tốt hơn là đặt một cái gì đó hợp lý như 24 giờ (như tôi đã làm trong mã của mình) nhưng ngay cả điều đó sẽ khiến người dùng thất vọng trong ngày mà bạn thực hiện các thay đổi trong CSS được mã hóa cứng mà quên nhưng số phiên bản được cung cấp. Điều độ trong tất cả mọi thứ?
Điều này có thể là tất cả quá mức cần thiết!
Khi tôi đang đọc các bài viết khác nhau để giúp tôi trả lời câu hỏi của bạn, tôi đã tìm thấy những điều sau đây từ chính Hướng dẫn của ông Cache , Mark Nottingham :
Cách tốt nhất để làm cho tập lệnh thân thiện với bộ đệm (cũng như hoạt động tốt hơn) là kết xuất nội dung của nó vào một tệp đơn giản bất cứ khi nào nó thay đổi. Sau đó, máy chủ Web có thể coi nó như bất kỳ trang Web nào khác, tạo và sử dụng trình xác nhận, điều này giúp cuộc sống của bạn dễ dàng hơn. Hãy nhớ chỉ ghi các tệp đã thay đổi, vì vậy thời gian sửa đổi lần cuối được giữ nguyên.
Mặc dù tất cả các mã này tôi đã viết nó rất hay và rất vui khi viết (vâng, tôi thực sự đã thừa nhận điều đó), có lẽ tốt hơn là chỉ tạo một tệp CSS tĩnh mỗi khi người dùng cập nhật CSS tùy chỉnh của họ và để Apache thực hiện mọi công việc nặng nhọc Giống như nó được sinh ra để làm gì? Tôi chỉ đang nói...
Hi vọng điêu nay co ich!