This might be more detail than is needed, so thought I’d include specifics in the comments. Our current structure is as follows:
- Top level application.js file that pulls in separate files and initializes them located in
app/javascript/packs
, for example with several lines like this:
import { initAccountLinks } from '../javascripts/accounts-links.js';
document.addEventListener('turbolinks:load', function () {
initAccountLinks();
}
- Each of those files has some functionality for either one page or multiple pages, but they are initialized on every page. The code is just written to have no effect if it is loaded on an irrelevant page. Either it checks the current
window.location.href
or it uses a loop. For example:
export function initAccountLinks() {
var account_rows = document.querySelectorAll('.account-row');
account_rows.forEach(function (account_row) {
// do stuff, attach event handlers, etc. If no account rows on this page do nothing.
});
}
- There are also some files with shared methods that are imported into multiple files. For example, there are several forms that share functionality to prompt for unsaved changes so they all use an exported function from one file:
import { init_prompt_for_unsaved_changes } from "../javascripts/shared/prompt_for_unsaved_changes.js";
// then later in the file somewhere when a form is submitted
init_prompt_for_unsaved_changes(model);
And in prompt_for_unsaved_changes.js
export function init_prompt_for_unsaved_changes(form_model){
// do stuff
}
- Lastly we make use of some classes. Currently the pattern is that there is one file that holds the class definition:
export default class Thing {
constructor(){
this.id = options['id'];
}
// various properties and functions
}
This class definition is imported where needed, stored on the window and then instantiated where needed by multiple files.
I would love to hear any suggestions about how to port this over to the new rails 8 propshaft/import maps structure.
So far in my new test app I have successfully added a javascript file: app/javascript/my_application.js
And loaded it in application.html.erb
.
<%# Includes all stylesheet files in app/assets/stylesheets %>
<%= stylesheet_link_tag :app, "data-turbo-track": "reload" %>
<%= javascript_importmap_tags %>
<%= javascript_include_tag 'my_application' %>
I’m considering ignoring the controllers folder altogether but wondering if its intention is something like one javascript file per backend controller? Also considering a directory structure similar to what we currently have like:
- Continue to add imports and initialize all functions from separate files in
app/javascript/application.js
- Put separate files in
app/javascript
and add a shared
folder with files that hold shared functions and class definitions.
- Other subfolders as needed in either
app/javascript
or app/javascript/shared
as needed.
- Outside of that I see there are already folders created in
app/assets
for stylesheets and images. Just use these and update any tags to use the new asset finding helpers.
Would really appreciate some feedback if I’m on a good track or if another structure is recommended.