Understanding "Assets"

You are viewing revision #2 of this wiki article.
This version may not be up to date with the latest version.
You may want to view the differences to the latest version or see the changes made in this revision.

« previous (#1)next (#3) »

  1. Background
  2. Asset Manager
  3. Example: Asset use by Gii
  4. CAssetManager class
  5. Maintenance of the assets folder
  6. Upgrading Yii

Many newcomers to Yii ask about the assets/ directory found under the webroot, and this article means to explain why it's there and how to work with it.

Background

Many applications are entirely self contained, and there's no trouble or conflict putting necessary resources (images, CSS files, Javascript files, etc.) under the webroot:

  • webroot/css/*
  • webroot/js/*
  • webroot/images/*

and so on. If a module needs to add one more resources, it's added directly and referenced by the path down from webroot.

But if one creates a module intended for widespread reuse elsewhere, naming conflicts start to emerge: How do you insure that your filename css/foo.css won't conflict with some unrelated application's attempt to use a file of the same name? Likewise with Javascript, images, and all the rest. This gets more difficult the more popular the module gets: it's going to eventually conflict with something.

Asset Manager

Yii addresses this by use of CAssetManager, available as Yii::app()->assetManager, which can take a module's private resource files and automatically publish them to the web-visible area (typically, webroot/assets/) on demand, giving the assets a non-conflicting unique name that can be later referenced in the code.

This copying/publishing is done the first time a module's resources are used, returning a URL to the application to use when generating HTML.

In addition to supporting resource publication by modules (both internal and for user application), Yii uses assets internally for core resources, such as jQuery.

Example: Asset use by Gii

A good example of asset publication is the Gii code generator, which can be found in the framework directory. Looking here we see:

  • framework/gii/GiiModule.php
  • framework/gii/models/...
  • framework/gii/views/...
  • framework/gii/controllers/...
  • framework/gii/assets/css/...
  • framework/gii/assets/js/...
  • framework/gii/assets/images/...
  • etc

The models, views, and controllers (along with the module config file) are like any other module, accessed at runtime by Yii just like the application code itself.

But Yii needs additonal web resources -- CSS, JS, images -- at runtime, but they're generally not available to the browser client from within the framework directory.

So the Gii module arranges to publish these assets to an area under webroot/, and the first time Gii is used these new folders show up:

  • webroot/assets/2472c2df/css/...
  • webroot/assets/2472c2df/images/...
  • webroot/assets/2472c2df/js/...

The 2472c2df is a unique name created by Yii in a way that won't conflict with any other module that publishes assets, but the particular numbers don't mean anything. After publication, the Gii module knows that the path /assets/2472c2df/css/main.css can be used in a URL to load the main CSS file.

CAssetManager class

(Note: this section is just an overview, not a detailed howto.)

The application's asset manager is available as Yii::app()->assetManager, and the main method is publish(). It's given a pathname where to find the source material - either one file or a directory to be published recursively - and it returns the URL base that can be used to access the published material.

This trimmed-down example was adapted from Gii (1.1.6) with much extraneous material removed:

// in the module initialization program
class XxiiModule extends CWebModule
{
    ...
    // getAssetsUrl()
    //    return the URL for this module's assets, performing the publish operation
    //    the first time, and caching the result for subsequent use.
    private $_assetsUrl;

    public function getAssetsUrl()
    {
        if ($this->_assetsUrl === null)
            $this->_assetsUrl = Yii::app()->getAssetManager()->publish(
                Yii::getPathOfAlias('xxii.assets') );
        return $this->_assetsUrl;
    }
    ....

// xxii/views/layouts/main.php

   <link rel="stylesheet"
         type="text/css"
         href="<?php echo $this->module->assetsUrl; ?>/css/main.css"/>
   ...
   <div id="logo">
   <?php echo CHtml::link(
                 CHtml::image($this->module->assetsUrl.'/images/logo.png'),
                 array('/xxii')); ?>
   </div>

The first time this is used in an application, the asset manager copies all the files to the webroot/assets/ folder, and then the module can use the $model->assetsUrl property to form the base of generated URLs for each of the particular resource files.

Using the example assets layout shown in the earlier section, these two uses would generate the URLs:

  • /assets/2472c2df/css/main.css
  • /assets/2472c2df/images/logo.png

respectively.

Maintenance of the assets folder

Many newcomers ask: "What do we do with the assets folder?", and the answer is "Mostly nothing".

  • It's important that the directory be writable by the webserver user so that Yii can publish the resources there when needed.
  • When a project has multiple versions (production, testing, development, etc.) do not copy the assets/ folders from one area to another; allow Yii to deploy them automatically in each area.
  • Do not manually edit any file under assets/ - if you have a real need to make a change, find the publishing module, edit the source, delete the subfolder under assets/, and let Yii re-publish the updated files.
  • Do not reference names under the assets/ folder directly (say, to get at some other module's assets). If you need to use that
  • Do not add the contents of the assets/ folder to any source-code control system; these files have master source in other places.

Upgrading Yii

The upgrade instructions to every new release of Yii include the note:

  • Clean up your 'assets' folder.

This means to delete the contents of this folder (but leave the folder itself behind): Yii will re-deploy these assets from the new versions the first time each one is used.

This step is important!

Yii only publishes the resource files if the target unique-name folder does not exist, so if they're not removed during an upgrade, then the new version of the code will use old versions of asset files: this probably matters.

45 0
40 followers
Viewed: 174 226 times
Version: Unknown (update)
Category: Tutorials
Written by: Steve Friedl
Last updated by: GOsha
Created on: Feb 19, 2011
Last updated: 6 years ago
Update Article

Revisions

View all history

Related Articles