# Discourse-common asset availability: difference between development and production?

**URL:** https://meta.discourse.org/t/discourse-common-asset-availability-difference-between-development-and-production/107490
**Category:** Development
**Created:** [January 25, 2019, 2:37am UTC](https://meta.discourse.org/t/discourse-common-asset-availability-difference-between-development-and-production/107490 "2019-01-25T02:37:42Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![angus](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/angus/32/341715_2.png) [@angus](https://meta.discourse.org/u/angus)
#### Post date: [January 25, 2019, 2:37am UTC](https://meta.discourse.org/t/discourse-common-asset-availability-difference-between-development-and-production/107490/1 "2019-01-25T02:37:42Z")

</div>

I’m adapting the [locations plugin](https://meta.discourse.org/t/locations-plugin/69742) to work better within the context of the [custom wizard plugin](https://meta.discourse.org/t/custom-wizard-plugin/73345).

The locations plugin has a component called [`location-selector`](https://github.com/angusmcleod/discourse-locations/blob/master/assets/javascripts/discourse/components/location-selector.js.es6), which is essentially an autocomplete input for geocoding locations. It uses the Discourse autocomplete jQuery plugin, which requires a raw template.

As the raw templating system is not available in the wizard app (e.g. the `Discourse.RAW_TEMPLATES` constant is not pre-loaded), and I want this component to work across both apps, I’ve assigned the raw template to a constant in the component file and used the various `RawHandlebars` methods in `discourse-common/lib/raw-handlebars`, e.g.

```plaintext
import RawHandlebars from 'discourse-common/lib/raw-handlebars';

const autocompleteTemplate = "<div class='autocomplete'><ul>{{#each options as |o|}}{{#if o.no_results}}<div class='no-results'>{{i18n 'location.geo.no_results'}}</div>{{else}}{{#if o.provider}} <label>{{{i18n 'location.geo.desc' provider=o.provider}}}</label> {{else}} <li class='ac-form-result'><label>{{geo-location-format o geoAttrs=o.geoAttrs}}</label> {{#if o.showType}} {{#if o.type}} <div class='ac-type'> {{o.type}} </div> {{/if}} {{/if}} </li> {{/if}} {{/if}} {{/each}} </ul></div>";
...

this.$().val(val).autocomplete({
   template: RawHandlebars.compile(autocompleteTemplate),
...

```

This works fine in development (in both normal Discourse and the Wizard app), however it fails in production in the normal Discourse app with

```plaintext
n.default.compile is not a function

```

(you can see this error currently [here](https://discourse.angusmcleod.com.au/c/locations) if you compose a post and click “Add Location”). Note, importing specific functions (e.g. ‘compile’) doesn’t fix it.

For some reason, `discourse-common/lib/raw-handlebars` is not loaded or required the same in production as it is in development.

I’m sure there’s an obvious reason why this is not working in production, but I’m just not seeing it at the moment. Any ideas welcome.

---

<div class="post-metadata">

### Author: ![angus](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/angus/32/341715_2.png) [@angus](https://meta.discourse.org/u/angus)
#### Post date: [January 28, 2019, 10:53pm UTC](https://meta.discourse.org/t/discourse-common-asset-availability-difference-between-development-and-production/107490/2 "2019-01-28T22:53:15Z")

</div>

Ok, I figured this out.

Production includes `handlebars.runtime.js` instead of `handlebars.js` (see `javascripts/template_include.js`), which doesn’t include `compile`, as it is assumed the templates are pre-compiled (see [here](https://stackoverflow.com/questions/19147161/what-is-the-difference-between-handlebar-js-and-handlebar-runtime-js)).

So I could just include `handlebars.js` in production, but that would be cheating. Rather I’ll need to figure out the best way to precompile raw templates for the wizard app…

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [January 28, 2019, 11:23pm UTC](https://meta.discourse.org/t/discourse-common-asset-availability-difference-between-development-and-production/107490/3 "2019-01-28T23:23:55Z")

</div>

Sorry, I meant to respond to this topic when I saw it last week, but completely forgot. You may be interested in how we compile templates for themes:

> <https://github.com/discourse/discourse/blob/main/lib/theme_javascript_compiler.rb#L163-L189>

We have extended versions of the compilers for some theme-specific functionality, but for basic use you can use `Barber::Precompiler` for raw templates, and `Barber::Ember::Precompiler` for ember templates.

It is indeed confusing that the compiler is loaded on the client in dev, but not production 🤔. It seems to me that it would be better to keep things the same, but maybe there is some reason for it.

---

<div class="post-metadata">

### Author: ![angus](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/angus/32/341715_2.png) [@angus](https://meta.discourse.org/u/angus)
#### Post date: [January 28, 2019, 11:30pm UTC](https://meta.discourse.org/t/discourse-common-asset-availability-difference-between-development-and-production/107490/4 "2019-01-28T23:30:01Z")

</div>

Thanks! Yeah I saw that and thought that’d be the way, so good to have confirmation 👍

---

<div class="post-metadata">

### Author: ![angus](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/angus/32/341715_2.png) [@angus](https://meta.discourse.org/u/angus)
#### Post date: [January 29, 2019, 12:27am UTC](https://meta.discourse.org/t/discourse-common-asset-availability-difference-between-development-and-production/107490/5 "2019-01-29T00:27:38Z")

</div>

The basic implementation of this in the custom wizard will be

```plaintext
Discourse.unofficial_plugins.each do |plugin|
  plugin_name = plugin.metadata.name
  if require_plugin_assets = CustomWizard::Field.require_assets[plugin_name]
    plugin.each_globbed_asset do |f, is_dir|
      if f.include? "raw.hbs"
        name = File.basename(f, ".raw.hbs")
        compiled = Barber::Precompiler.new().compile(File.read(f))
        result << "
          (function() {
            if ('Wizard' in window) {
              Wizard.RAW_TEMPLATES['#{name}'] = requirejs('discourse-common/lib/raw-handlebars').template(#{compiled});
            }
          })();
        "
      end
    end
  end
end

```

Which just requires a plugin to include ‘templates’ in the assets they add to the wizard asset pipeline, e.g.

```plaintext
CustomWizard::Field.add_assets('location', 'discourse-locations', ['components', 'helpers', 'lib', 'stylesheets', 'templates'])

```

The upshot being, I can access the pre-compiled a raw template in a common component by just switching the global namespace:

```plaintext
const global = this.get('global');
let template = global.RAW_TEMPLATES['javascripts/location-autocomplete'];

```
