AssetManager:更新された静的データをユーザーに受信させる方法

Webアプリケーションを開発するとき、よく知られている問題が1つあります。 私たちプログラマーは、新しいJavaScriptコード、CSSのスタイルを作成し、静的変数を変更します...そして、この静的変数は通常、ユーザーのブラウザーによってキャッシュされ、かなり長い間キャッシュにとどまることができます(そして、これは実際には正しいです。 。

しかし、静的を変更したらどうなるでしょうか? ユーザーにキャッシュをフラッシュさせ、これらのファイルを更新させる方法は? 一般的な方法がいくつかあります。たとえば、ファイル名にバージョンタグを追加したり、ファイルを接続するときにGETパラメーターにタイムスタンプを追加したりします。

Yiiフレームワークを使用する場合、接続時にスクリプトとスタイルファイルのバージョンまたはタイムスタンプを指定することもできますが、これを常に監視する必要があります。Yiiの場合は、競合も監視する必要があります(たとえば、ウィジェットとビュー同じスクリプトを使用しますが、タイムスタンプが異なります)。
実際、Yiiでは、この問題に対するより文明的なアプローチを編成できます。


ステップ1.ファイルを準備します。


Webアプリケーションの保護フォルダーにアセットのサブフォルダーを作成します。
すべての統計をこのフォルダーに入れます。 永続的な外部リンク(ファビコン、ロゴ、一部のドキュメントなど)が必要な場合、一部のファイルはWebアプリケーションのルートに残す必要があります。
ファイル構造は次のようになります。
 /保護された
     /資産
         / css
             /main.css
         / img
             /bg.png
             /sprite.png
             /extra_icons.png
         / js
             /main.js
             /form.js
             /etc.js


ステップ2.ツールの準備。


ほとんどの場合、既にオーバーライドされたControllerクラスがあり、他のすべてのコントローラーの基本クラスとして使用します。
アセットに作業を提供するために少し変更します。
class Controller extends CController { private $_assetsBase; public function getAssetsBase() { if ($this->_assetsBase === null) { $this->_assetsBase = Yii::app()->assetManager->publish( Yii::getPathOfAlias('application.assets'), false, -1, YII_DEBUG ); } return $this->_assetsBase; } public $menu=array(); public $items=array(); public $breadcrumbs=array(); } 

すべてがシンプルです。
ここでゲッターを追加しました。ゲッターは、 / protected / assetsフォルダーから初めてアセットを公開し、 _assetsBaseプライベートプロパティへのパスを保存します。その後、このプライベートプロパティの値を返すだけです。
CAssetManagerクラスのpublish()メソッドには、いくつかの興味深いパラメーターがあります。

メソッドのシグネチャは次のとおりです。
 publish(string $path, boolean $hashByName=false, integer $level=-1, boolean $forceCopy=false) 

そして、パラメーターの簡単な説明:

$ path-実際に公開するアセットフォルダーへのパス。
$ hashByName-フォルダー名をそのまま公開するか、ハッシュするかを決定します。 このパラメーターのおかげで、すべての魔法が発生します。これについては後で説明します。
$レベル -パブリケーション用のフォルダーのネストの程度を決定します( -1-すべてのサブフォルダーは再帰的です);
$ forceCopy-ファイルが既に存在する場合でも、コピーファイルを強制するかどうかを決定します。 このパラメーターをYII_DEBUGに設定します。これにより、ローカルマシンおよび必要な場合にのみ運用環境でスクリプトが絶えず更新されます( 運用環境でYII_DEBUGfalseに設定する必要があります )。

ステップ3.準備されたファイルよりも準備されたツールを使用します。


ゲッターをもう少し上に書いたプロパティそのものであるassetBaseは 、どこでも使用できます。
ビューとレイアウトで次のように書くことができます:
 <link rel="stylesheet" type="text/css" href="<?=$this->assetsBase?>/css/main.css" /> 
または
 <?Yii::app()->clientScript->registerScriptFile($this->assetsBase.'/js/utils.js')?> 

そして、この場合$ thisは、すべてのコントローラーが継承され、ビューとレイアウトに渡されるControllerクラスのインスタンスであるため、そのように書くことができます。

ウィジェットの場合、状況は少し異なります。ウィジェットビューはコントローラーのコンテキストではなく、ウィジェットのコンテキストで実行されるため、独自のアプローチが必要です。したがって、ウィジェットビューでJavascriptファイルを接続するには、次のように記述します。
 <?Yii::app()->clientScript->registerScriptFile(Yii::app()->controller->assetsBase.'/js/widget.js')?> 


ステップ4.本番環境でバージョンを更新し、ユーザーのブラウザーに更新されたファイルを強制的にダウンロードさせます。


これが最も重要なポイントであり、私も含めて多くの開発者が見落としているものです。
Yiiの多くの記事を読むと、ユーザーが更新された静的ファイルを受信するために、サイトのルートにある/ protected / assetsを埋め、 / assetsフォルダー 消去するように見えるかもしれません( もちろんAssetManagerが使用されている場合を除く )。
しかし、これはまったくありません!

Webアプリケーションのルートにある/資産フォルダー内の自動生成されたサブフォルダー名は、フォルダー名/保護された/資産のハッシュに基づいており、Webアプリケーションのルートにある/資産フォルダーをクリーンアップしても、時々変更されません 。 それらは元の形に復元されます。 これは、キャッシュ時間が切れるまで、ユーザーのブラウザは何かが変更されたことを「カットスルー」しないことを意味します。

少なくとも最近までそうだった。 そして、この問題はこのトピックで議論されました。その後、Alexander Makarovが回避策を見つけ、2011年11月8日にコミットして状況を修正しました。
ここで、 CAssetManagerクラスのpublish()メソッドの2番目のパラメーター $ hashByNameパラメーターをfalseに設定は、Yiiに、このフォルダーの変更日だけでなく 、静的なフォルダー名のハッシュに基づいて、Webアプリケーションのルートの/ assetフォルダーにサブフォルダー名を作成させます

これにより、アプリケーションの静的ファイルを展開するときに非常に単純なフェイントを作成できます。
 touch /path/to/your/website/protected/assets 

Linuxサーバーのコンソールでこのコマンドを実行し(サイトがまだLinuxにデプロイされていると仮定します)、次に静的にアクセスすると、Yiiは新しいアセット名を生成します!
つまり、ページを開いたユーザーは、まったく新しい、改良されたスクリプト、スタイル、写真などを絶対にダウンロードします。

要するに


あなたがする必要があるのは:
  1. すべての統計を/ protected / assetフォルダーに移動します
  2. 上記のようにコントローラーの基本クラスを拡張します
  3. どこでもstaticsへのパスの基礎としてassetBaseを使用します
  4. サイトの統計を更新するとき、コマンドを実行します
     touch /path/to/your/website/protected/assets 
    / protected / assetフォルダの変更日が変更されます。つまり、サイトのルートにある/ assetフォルダに新しいハッシュが生成されます
  5. 利点:ユーザーがスクリプト、スタイルなどの最新バージョンを確実に受け取ることができます。


もう少し


ところで、たとえば私の知る限り、Ruby on Railsではこの問題はすでに解決されています。
開発中のYiiバージョン2では、この問題も解決される可能性があります。
フォーラムでYii 2のこの問題の解決策の議論に参加できます(アクセスはアクティブな参加者のみに許可されています)。

また、別の興味深い機能は、スクリプトとcssの自動縮小です。 現時点では、フレームワークレベルでは実装されていませんが、いくつかの拡張機能で実装されていますが、これは別の記事のトピックです...

関連リンク


  1. CAssetManagerクラスのドキュメント
  2. Yiiフォーラムでのこのトピックの議論
  3. Yii 2の新しいバージョンに関するこの問題の議論 (アクティブユーザーのみが利用可能)
  4. 縮小の拡張:
  5. この記事の英語版
  6. CAssetManagerに関する別の記事


PS:この記事は翻訳でもクロスポストでもないことに注意してください。Yiiナレッジベースの記事の英語版も書いたためですが、ロシア語版は(言語の知識レベルが異なるため)より良く、より理解しやすくなりました。

Source: https://habr.com/ru/post/J139166/


All Articles