Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider Brian Mann style AppModules and folder layout in the generator #37

Open
thadk opened this issue Dec 6, 2013 · 14 comments
Open

Comments

@thadk
Copy link

thadk commented Dec 6, 2013

On my last project I used this generator as a basis to parse out and follow Brian Mann's proposed Marionette app structure from his elegant-but-huge Rdio app (vid) (slides) that is now featured on Marionette's homepage. _Be prepared for the thought bomb._ Much is only covered in the audio.

The main difference from what we have here and over on this generator fork that adds modules is that his Marionette components are laid out and scoped by AppModules.
As Brian Mann says, individual AppModules and isolated (Bower or otherwise) Components are the gateways to essentially all internal app interaction.

Here was my fairly successful folder structure:

app/
  scripts/
    apps/ - app modules container folder

      first-app-module/
        app-first-app-module.js - the AppModule definition and an initializer for the router, controllers, and a primary layout.
          => see fork elycruz/generator-marionette for this generated file. Name can begin with "app-"
        first-app-module-new.js - the first verb-oriented controller
        first-app-module-list.js - the second verb-oriented controller
        first-app-module.js - the single marionette router for this app module
        composite/ - Marionette CompositeViews for this AppModule
        collection/ - Marionette CollectionViews
        item/ - Marionette ItemViews
        layout/ - Marionette LayoutView including the default one
          first-app-module-layout.js  - default subregions for the AppModule
          another-controllers-layout.js

      second-app-module/
        app-second-app-module.js - the AppModule definition with an initializer for the router, controllers, and layout. Name begins with "app-"
          => see fork elycruz/generator-marionette. Name can begin with "app-"
        second-app-module-new.js - the first verb-oriented controller
        second-app-module.js - the single Marionette router for this app module
        composite/ - Marionette CompositeViews for this AppModule
        collection/ - Marionette CollectionViews
        item/ - Marionette ItemViews
        layout/ - Marionette LayoutView including the default one
          second-app-module-layout.js - default subregions for the AppModule
          another-controllers-layout.js

    entities/ - model and collection definitions
    application.js - primary app with highest level region creation and an initializer for 
    communicator.js - boilerplate messaging bus definition for requiring as needed.
    init.js - grunt generated bower_component includes and other custom theme_component requirejs definitions
    regionManager.js
    main.js - App.start()

  styles/ - SASS or LESS stylesheets
  templates/ -- hbs or jade templates 
  theme_components/ - manually managed components
  bower_components/ - automatic components

server/
  app.js -

test/
  SpecRunner.js - the test framework's own init.js
  spec/
    apps/
      first-app-module/ - AppModule structure is more explicitly separated in generated test folder
        controllers/
        routers/
        views/
          layout/
          item/
      second-app-module/
        controllers/
        routers/
        views/
    entities/

_Any comments? Is this a decent way to implement scoped AppModules productively that we could consider implementing in the mainline generator?_

I feel like Brian Mann's pattern reflects the best thinking from Ember.js and other parts of the javascript/rails ecosystem and it is nice to work with that within Marionette.

(We used this structure with a standard backbone backend PaaS API implemented with Kinvey rather than Rails as BM advocates.)

Brian Mann's outer structure:
The big structure

Brian Mann's inner structure:
The detail structure

@thadk
Copy link
Author

thadk commented Dec 6, 2013

I created an example gist of my module
and I reworked it from the Readme.md, perhaps slightly more readable:

Directory structure

  • app/ --> client side files
    • /bower_components --> bower installs
    • /vendor_components --> theme or other custom resources
    • /images
    • /scripts
      • /entities --> model and collection definitions
        • a-model.js
        • a-collection.js
      • /apps
        • first-app-module/
          • app-first-app-module.js --> the AppModule definition and an initializer for the router, controllers, and a primary layout. See fork elycruz/generator-marionette for this generated file and my gist of module. Name can begin with "app-"
          • first-app-module-new.js --> the first verb-oriented controller
          • first-app-module-list.js --> the second verb-oriented controller
          • first-app-module.js --> the single marionette router for this app module
          • composite/ --> Marionette CompositeViews for this AppModule
          • collection/ --> Marionette CollectionViews
          • item/ --> Marionette ItemViews
          • layout/ --> Marionette LayoutView including the default one
            • first-app-module-layout.js --> default subregions for the AppModule
            • another-controllers-layout.js
        • second-app-module/
          • app-second-app-module.js --> the AppModule definition and an initializer for the router, controllers, and a primary layout. See fork elycruz/generator-marionette for this generated file. Name can begin with "app-"
          • second-app-module-new.js - the first verb-oriented controller
          • second-app-module.js - the single Marionette router for this app module
          • composite/ - Marionette CompositeViews for this AppModule
          • collection/ - Marionette CollectionViews
          • item/ - Marionette ItemViews
          • layout/ - Marionette LayoutView including the default one
            • second-app-module-layout.js - default subregions for the AppModule
            • another-controllers-layout.js
      • init.js --> require configuration
      • main.js --> application starting point
      • application.js --> application file
    • /styles --> scss files
    • /templates --> handlebar templates
  • server/ --> node server files
  • test/ --> unit testing
    • SpecRunner.js - the test framework's own init.js
    • spec/
      • apps/
        • first-app-module/ - AppModule structure is more explicitly separated in generated test folder
          • controllers/
          • routers/
          • views/
            • layouts/
            • items/
        • second-app-module/
          • controllers/
          • routers/
          • views/

@Golodhros
Copy link

+1 to this!

@j0hnsmith
Copy link

+1

3 similar comments
@swilliamsui
Copy link

+1

@markbrouch
Copy link

+1

@ghost
Copy link

ghost commented Jan 23, 2014

+1

@jcurtis
Copy link

jcurtis commented Jan 24, 2014

🍍

@sometxdude
Copy link

+1

I've built a fairly big project with this generator, and one of the major pain points is the proliferation of files into a handful of folders. I was scrolling endlessly to find what I needed.

@elycruz
Copy link

elycruz commented Mar 5, 2014

About the folder structure of topic:

I'm currently building parts of an app using requirejs and backbone.marionette and the methodology that I've currently landed at is as follows:

  • modular-app-1
    • src
  • modular-app-2
    • src
  • modular-app-3
    • src

In each modular app I reference modules in the other modular apps via alias paths (in require.paths config); e.g.:

// From within some other app other than above apps
require.config({
  paths: {
     // ...
    ma1: '../modular-app-1/src',
    ma1_tmpl: '../modular-app-1/templates',
    ma2: '../modular-app-2/src',
    ma2_tmpl: '../modular-app-2/templates'
    // ...
  }

Now included module calls look like ma1/modules/HelloWorldModule.

Here's an example of running all three apps from another app:

// If you've added initializers to your modules they will automatically initialize when 
you call their app starts.  There by allowing you to compose the apps as you 
please and still have them exist separately from each other (I can vouch for this, 
builds nicely, and allows you to really modularize your apps even have separate 
builds/distros of each (if necessary)!)

define([
    'ma1/application',
    'ma2/application',
    'ma3/application',
    'this-apps-path/application',
    'ma1/modules/SomeModule',
    'ma2/modules/AnotherModule',
    'ma3/modules/AnotherModule',
    'this-apps-path/modules/TestingModule'
],
    function (ma1_app, ma2_app, ma3_app, app) {
        $(function () {
            ma1_app.start();
            ma2_app.start();
            ma3_app.start();
            app.start();
        });
    });

The only thing to remember with this paradigm is that each modular app will have to use a path alias for itself (makes app's paths unique within modular-app-sphere): modular-app-1 is using ma1/..., modular-app-2 is using ma2/..., and the includer app is using it's own path (this-apps-path). Then all app'ed up composition apps have to do to use other apps is define their path aliases in their require paths config; e.g., (example above)

So I agree with @thadk having a feature like this in generator-marionette (or any framework generator-...) would greatly help development flow and also help dev's in wrangling their application architectures more easily. 👍

@elycruz
Copy link

elycruz commented Mar 5, 2014

I'll will put this feature into the roadmap for my branch of generator-marionette.

@rbouajram
Copy link

+1

1 similar comment
@jeffreycahyono
Copy link

+1

@thadk
Copy link
Author

thadk commented Jul 21, 2014

I have been lurking in Marionette 2.0's gitter chat room (https://gitter.im/marionettejs/backbone.marionette) and I noticed this new starter kit:
https://github.com/thejameskyle/marionette-starter-kit

It isn't as automatable as this example and doesn't use real App modules, but in lieu of a full upgrade for generator-marionette, it could be a good starting point for new projects. The author is responsive.

One bonus is that it uses Browserify instead of requirejs, though it hasn't gone the whole way of using Gulp rather than Grunt.

@ivadenis
Copy link

ivadenis commented Feb 3, 2015

For app modules I would also include templates, unit tests and css in there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests