Sie unterscheiden sich geringfügig - der ETag enthält keine Informationen, anhand derer der Client feststellen kann, ob er in Zukunft erneut eine Anfrage nach dieser Datei stellen soll oder nicht. Wenn ETag alles ist, was er hat, wird er immer eine Anfrage stellen müssen. Wenn der Server jedoch den ETag aus der Client-Anfrage liest, kann er entscheiden, ob er die Datei sendet (HTTP 200) oder dem Client mitteilt, dass er nur seine lokale Kopie verwenden soll (HTTP 304). Ein ETag ist im Grunde nur eine Prüfsumme für eine Datei, die sich semantisch ändert, wenn sich der Inhalt der Datei ändert.
Der Expires-Header wird vom Client (und von Proxies/Caches) verwendet, um festzustellen, ob er überhaupt eine Anfrage an den Server stellen muss oder nicht. Je näher Sie dem Expires-Datum sind, desto wahrscheinlicher ist es, dass der Client (oder Proxy) eine HTTP-Anfrage für diese Datei vom Server stellt.
Sie sollten also wirklich BEIDE Header verwenden - setzen Sie den Expires-Header auf einen vernünftigen Wert, je nachdem, wie oft sich der Inhalt ändert. Konfigurieren Sie dann ETags, die gesendet werden sollen, damit der Server bei Anfragen von Clients leichter feststellen kann, ob er die Datei zurücksenden soll oder nicht.
Ein letzter Hinweis zu ETag: Wenn Sie einen Server mit Lastverteilung auf mehreren Rechnern verwenden, auf denen Apache läuft, sollten Sie die ETag-Generierung deaktivieren. Dies liegt daran, dass Inodes als Teil des ETag-Hash-Algorithmus verwendet werden, der von Server zu Server unterschiedlich sein wird. Sie können Apache so konfigurieren, dass Inodes nicht als Teil der Berechnung verwendet werden, aber dann sollten Sie sicherstellen, dass die Zeitstempel der Dateien exakt gleich sind, um sicherzustellen, dass auf allen Servern der gleiche ETag generiert wird.