# Overriding plugin javascript in a theme component

**URL:** https://meta.discourse.org/t/overriding-plugin-javascript-in-a-theme-component/213748
**Category:** Development
**Created:** [January 3, 2022, 8:42pm UTC](https://meta.discourse.org/t/overriding-plugin-javascript-in-a-theme-component/213748 "2022-01-03T20:42:28Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [January 3, 2022, 8:42pm UTC](https://meta.discourse.org/t/overriding-plugin-javascript-in-a-theme-component/213748/1 "2022-01-03T20:42:28Z")

</div>

Continuing the discussion from [Splitting up theme Javascript into multiple files](https://meta.discourse.org/t/splitting-up-theme-javascript-into-multiple-files/119369):

There was a discussion from someone a while back about developing in a theme vs a plugin. The Rails part of [https://www.pfaffmanager.com/](https://www.pfaffmanager.com/) is starting to be fairly stable, and what I’d like to do is move development of the rails part into a theme component. This is working pretty well, and changes in templates and initializers in the theme component are overriding the plugin as expected. **But,** changes to `javascripts/discourse/components/server-item.js.es6` in the theme are not overriding those same files in the plugin.

I suppose I could remove entirely the ember stuff from the plugin and have it exist only in the theme, but that sounds like a day’s work to get all of those pieces moved around tested and pushed to the server. Might I be missing something silly? Should I suck it up and completely remove the stuff I’d like in the theme component from the plugin? Should I just keep it all in the plugin?

---

<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 4, 2022, 10:55am UTC](https://meta.discourse.org/t/overriding-plugin-javascript-in-a-theme-component/213748/2 "2022-01-04T10:55:23Z")

</div>

Having the same code in both the theme component and the plugin seems a little weird to me - IMO it would be better to decide between theme-component/plugin, and then go all-in. Overriding entire files isn’t something we do ourselves, and it’s not something we recommend. To override core/plugin behaviour, your theme component should use methods like `api.modifyClass`.

I suspect the root cause here is that plugin ES6 modules are prefixed differently from core/theme modules. Running this on your site, I see the modules are prefixed with `plugin`. I suspect if you enabled the theme component, we’d see another entry, but with a different prefix.

![Screenshot 2022-01-04 at 10.53.36](https://global.discourse-cdn.com/meta/optimized/3X/e/1/e1bf4a95fda189812f483b0a64966d056eada12f_2_690x32.png)

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [January 5, 2022, 2:32pm UTC](https://meta.discourse.org/t/overriding-plugin-javascript-in-a-theme-component/213748/3 "2022-01-05T14:32:13Z")

</div>

> [@david](#):
>
> Having the same code in both the theme component and the plugin seems a little weird to me

Well, all of Ember still seems weird to me. 🤷‍♂️

> [@david](#):
>
> IMO it would be better to decide between theme-component/plugin, and then go all-in.

Cool. I’ll stick with the single plugin that has all the javascript in it.

And that `Object.keys` magic is very cool and I’d never have figured that out. I can’t thank you enough for that. And you’re right:

```plaintext
(4) ['discourse/plugins/Pfaffmanager/discourse/components/compact-server-item', 
'discourse/plugins/Pfaffmanager/discourse/components/server-item', 
'discourse/theme-11/components/server-item', 
'discourse/theme-11/components/compact-server-item']

```

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [January 5, 2022, 3:24pm UTC](https://meta.discourse.org/t/overriding-plugin-javascript-in-a-theme-component/213748/4 "2022-01-05T15:24:04Z")

</div>

> [@david](#):
>
> IMO it would be better to decide between theme-component/plugin, and then go all-in.

I agree in general, however, there are some edge cases:

1. Where the volume of changes to the javascript far outweighs the changes to the back-end, in which case Theme Components are a great way to deploy and test-deploy code FAST.

2. Where most of the functionality can be delivered in the base Theme Component but adding a complementary plugin can add additional features not possible in Javascript alone. I employ this technique in Topic List Previews, where the Component does 90% of what the add-on is capable of, but if you also add in the plugin, you get some additional cool stuff.

That said, packaging everything in a plugin makes sense as there is less confusion on configuration & installation and everything is always kept in step.

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [January 5, 2022, 3:28pm UTC](https://meta.discourse.org/t/overriding-plugin-javascript-in-a-theme-component/213748/5 "2022-01-05T15:28:47Z")

</div>

But even in your plugin+theme scenario, I’d not duplicate the Ember code in both the plugin and the theme. So I’d need to yank at least most of the templates, initializers, components, out of the plugin and have them only in the theme component.

Since I’m the only one who’s going to be confused about the configuration, that’s not a huge deal. I really like the idea of being able to test some new front end stuff on the live site by switching to the beta version of the theme.

---

<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 5, 2022, 3:29pm UTC](https://meta.discourse.org/t/overriding-plugin-javascript-in-a-theme-component/213748/6 "2022-01-05T15:29:39Z")

</div>

Having server-side stuff in a plugin, and client-side stuff in a theme makes a lot of sense - we do that ourselves 👍

My objection was to defining **the same** JavaScript file in a theme and a plugin simultaneously.

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [January 5, 2022, 4:07pm UTC](https://meta.discourse.org/t/overriding-plugin-javascript-in-a-theme-component/213748/7 "2022-01-05T16:07:20Z")

</div>

Yep so all on same page 👍🏻

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [January 5, 2022, 4:26pm UTC](https://meta.discourse.org/t/overriding-plugin-javascript-in-a-theme-component/213748/8 "2022-01-05T16:26:09Z")

</div>

I appreciate you guys helping me out with this.

The other issue that I see is doing qunit tests. (I’ll pretend that I can figure out how to add any, which is another issue entirely; I think my problem is that I don’t know how to seed the tests with data for the stuff to display…). I think that if I have quinit tests in my plugin then they’ll get run when I push to gitihub (because I’m pretty sure I’ve seen my broken ones fail).

Can I get a theme component to do the same?

---

<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 5, 2022, 4:38pm UTC](https://meta.discourse.org/t/overriding-plugin-javascript-in-a-theme-component/213748/9 "2022-01-05T16:38:48Z")

</div>

Technically it should be possible, but I don’t think we have any ready-made GitHub actions workflows for themes yet. Theme testing is getting a bit of an overhaul currently (for the ember-cli transition), but after that, maybe we’ll be able to add some theme-testing workflow templates to [GitHub - discourse/.github · GitHub](https://github.com/discourse/.github)

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [October 9, 2022, 8:34pm UTC](https://meta.discourse.org/t/overriding-plugin-javascript-in-a-theme-component/213748/10 "2022-10-09T20:34:37Z")

</div>

> [@david](#):
>
> Overriding entire files isn’t something we do ourselves, and it’s not something we recommend.

Is this true of templates too?

Scenario: I want to override a template deployed in a plugin. But I want to override in a code controlled way.

So I tried to ship the new template in a theme component. The same file exists in a plugin (but is different).

This appears to work on my dev cloud install but not in a standard production install.

So is it fair to say that you can’t predict if this will be successful or not with templates? ie the asset pipeline is such that you can’t predict which ‘template’ will stick as there is no predefined or predictable precedence?

I have been working with some strange assumption that there was a hierarchy, something like:

- core
- plugin
- theme component
- local site changes

And if you placed a “file” with the same path and name in a later level of that hierarchy, it would override any “previous” definition.

But my assumption is probably not safe?

Is the only “packaged” solution (ruling out local site changes) therefore to fork the plugin and make the changes directly within it?

That would in some senses be a shame as it would increase the maintainance effort for customisations as you’d have to merge in changes to the main plugin repo periodically …

---

<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: [October 10, 2022, 9:09am UTC](https://meta.discourse.org/t/overriding-plugin-javascript-in-a-theme-component/213748/11 "2022-10-10T09:09:08Z")

</div>

> [@merefield](#):
>
> Is the only “packaged” solution (ruling out local site changes) therefore to fork the plugin and make the changes directly within it?

The best way would be to update the existing plugin and give it a plugin outlet and/or customisation API which the theme component can use.

My comment above was specifically about overriding entire JS files (i.e. es6 modules). That is not possible. The asset pipeline automatically prefixes plugin/theme modules with the plugin/theme name/id, so it’s impossible to create a clash with core.

For templates, we know that people (including us, in some situations) do override them, so we will likely keep that system working. But please remember it **is a hack**. If the original component/controller changes its behaviour, your overridden template will probably cause the site to break.

In general I think the hierarchy you mentioned (core, plugin, theme) should be true - so if you’re seeing something different please do share the details of the file paths in the plugin and theme.

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [October 10, 2022, 2:15pm UTC](https://meta.discourse.org/t/overriding-plugin-javascript-in-a-theme-component/213748/12 "2022-10-10T14:15:19Z")

</div>

Thanks for confirmation. My issue was actually unrelated and the clarification helped me look in the right place! 😊
