Is it bad to add js and css in template_preprocess for a custom block? If I load my page where my block is displayed as user 2 (any user besides user 1) my block displays correctly.  If I reload the page my block doesn't display correctly and my js and css that was added via template_preprocess() doesn't show up.

I verified that if I turn off Block caching the problem goes away so it tells me that I shouldn't be adding js and css in the template_preprocess functions and add it via '#attach' but I have a function (video_widget_add_js) that I am adding javascript because I am adding it in multiple places and want to reuse the code.  Anyone have a good suggestion on this?

  &lt;?php

  /**
   * Implements hook_block_view().
   */
  function leadership_block_view($delta = '') {
    $block = array();

    switch($delta) {
      case 'leadership_all_companies':
        $node = menu_get_object();

        $data_card_content = leadership_get_data_card_content($node);

        if (!$data_card_content) {
          $block = array(
            'subject' =&gt; '&lt;img class="ld-block-logo" src="' . variable_get('leadership_block_logo') . '" alt="Leadership Logo" /&gt;',
            'content' =&gt; theme('leadership_allcompanies', array(
                'taxonomies' =&gt; leadership_get_taxonomies(FALSE),
                'delta' =&gt; $delta,
              )
            ),
          );
        }
        break;

    }

  }

  /**
   * Implements hook_theme().
   */
  function leadership_theme() {
    return array(
      'leadership_allcompanies' =&gt;  array(
        'variables' =&gt; array('taxonomies' =&gt; NULL, 'delta' =&gt; NULL, 'has_data_card' =&gt; NULL),
        'template' =&gt; 'leadership-allcompanies',
      ),
    );
  }

  /**
   * Preprocess for the all companies block.
   *
   * @param array $vars
   *   An associative array containing:
   *   - taxonomies array
   *     An array that contains taxonomy objects @see taxonomy_get_tree().
   *   - delta string
   *     The block string key.
   *   - has_data_card
   *     This will only be used in the all_companies_and_data_card block. If set
   *     to FALSE then only all data that would appear in the all companies block
   *     will appear. If set to TRUE both will appear.
   */
  function template_preprocess_leadership_allcompanies(&amp;$vars) {
    // Add js and css files.

    $js_extension = (variable_get('smg_global_is_production', false)) ? '.min.js' : '.js';

    $path = drupal_get_path('module', 'leadership');
    $video_widget_path = drupal_get_path('module', 'video_widget');
    drupal_add_css($path . '/css/all_companies_block.css');
    drupal_add_css($path . '/css/datacard.css');
    drupal_add_css($path . '/css/datacard_' . variable_get('smg_global_site') . '.css');
    drupal_add_css($video_widget_path . '/video_widget_includes/css/video_widget.css');
    drupal_add_js($video_widget_path . "/video_widget_includes/angular/app{$js_extension}");
    //drupal_add_js('sites/all/libraries/angularjs/bower_components/angular-animate/angular-animate.min.js');
    drupal_add_js($path . "/angular/js/all_companies_block{$js_extension}", array('every_page' =&gt; TRUE, 'preprocess' =&gt; TRUE));
    drupal_add_js($path . "/angular/js/datacard{$js_extension}");

    $vars['site_id'] = variable_get('smg_global_site');

    $taxonomies = $vars['taxonomies'];
    if ($taxonomies) {
      if (variable_get('smg_global_site') == 'pw') {
        // Add the parent tids,titles (Ex: Machinery, Materials, Service)
        foreach ($taxonomies as $taxonomy) {
          $categories[$taxonomy-&gt;parents[0]]['tids'][] = $taxonomy;
        }
        foreach ($categories as $tid =&gt; $category) {
          $categories[$tid]['tid'] = $tid;
          $categories[$tid]['title'] = taxonomy_term_load($tid)-&gt;name;
        }
        $vars['taxonomies'] = $categories;
      }

      // Add taxonomy list to Drupal object to be used by Angular.
      drupal_add_js(array('leadership_all_companies_block' =&gt; $taxonomies), 'setting');

      // Call the video widget registering function
      video_widget_add_js();
    }
  }
Generally, yes, you should use ['#attached'] in renderable arrays to add assets in a cache-compatible way. $block['content'] can be a renderable array if you make it an array instead of a string, so you're not too far off here. I'm not sure exactly what you're doing inside video_widget_add_js(), but if it's just adding a bunch of assets, then consider implementing hook_library() instead. Library implementations are attachable in ['#attached'].

In your case, however, the attached assets aren't your only problem. With block caching enabled, a cache hit bypasses hook_block_view() completely, instead retrieving the previously compiled $block array from cache. Since you use $node = menu_get_object() in hook_block_view(), you probably need the block to vary by page. However, the default block cache setting is DRUPAL_CACHE_PER_ROLE, which only varies by a user's role combinations.

You could set your block to cache with DRUPAL_CACHE_PER_PAGE instead, but the easiest thing to do without refactoring a bunch of your code is to set your block to DRUPAL_NO_CACHE.  DRUPAL_CACHE_PER_PAGE isn't hugely efficient anyway unless you have a lot of authenticated user traffic.

To set a particular cache setting on a block, edit the hook_block_info() implementation:


/**
 * Implements hook_block_info().
 */
function leadership_block_info() {
  return array(
    'leadership_all_companies' => array(
      'info' => t('Leadership block'),
      'cache' => DRUPAL_NO_CACHE,
    );
  );
}