App structure alternatives after Mantra

Hi everyone,

I have an app with the following stack:

  • structure/spec: mantra
  • view: react
  • methods: MDG’s ValidatedMethod
  • router: flowrouter
  • components: material ui
  • forms: formsy-react (with formsy-material ui)

The app is working and I’m happy with it. In the next version I’m going to add a few new features but I’m thinking about rewriting/refactoring it, because:

  • I’d like to use the dynamic imports but right now every module is inside the clients folder (according to the original mantra spec) so it’ll be a big change
  • I want to switch to react-router because I don’t want to sink with flowrouter.
  • I love mantra-cli and the whole mantra thing was great for me because it forced me to follow a pattern but I’m afraid because it’s abandoned. So I’m thinking about changing to a new HOC pattern/lib.

I’ve tried Redux but it seemed overkill for my project, too much boilerplate. Mantra has boilerplate too but the cli takes care of a lot of things for me (e.g. updating index.js after adding a new module/action/etc).

What would you recommend for me? Stick with mantra just change the file structure (it’s sooo much work without the benefit of leaving an abandoned spec/komposer)? Change to XXX data-loading-container lib/pattern?

I’d be interested people’s answers to this as well.

@csiszi What options are you considering? I may have a look at them too.

i currently use an adopted mantra-structure:


  • /modules <-- mantra modules, was /client/modules
  • /api/ <-- as in meteor guide, contains collections, schemas, methods, … , was /lib in mantra original spec
  • /configs <-- contains context.js, themes, etc.

/imports/modules is already supported by

I am going to update it soon so that you can customize also the api directory

1 Like

How does your client/main.js look like? I’m wondering if importing and loading the modules will cause everything inside them to be added to the bundle.

Or importing the components dynamically in every routes.jsx will solve this?


import { createApp } from 'mantra-core';
import initContext from '../imports/configs/context';

// modules
import coreModule from '../imports/modules/core';
import otherModule from '../imports/modules/other';

// init context

const context = initContext();

// create app
const app = createApp(context);
// ...

So the modules init code is not lazy loaded, but that’s not much code.

As you said, i import components lazyly in the routes.jsx file with

I am thinking about how to lazy load stuff in the mantra-context as well as how to load whole modules lazyly, but routes is still best way to start loading something lazily.

It makes sense, thanks! Fortunately it wasn’t hard to move everything from client/modules to imports/modules.

My only problem is that my linter doesn’t seem to understand this:
const {default: ApStats} = await import('./containers/ap_stats.js');

Do you know what I have to add to my .eslintrc? It say Unexpected token at import.

no idea,

i used

const Home = Loadable({
  loader: () => import('/imports/modules/core/containers/home'),
  loading: Loading,

FlowRouter.route('/', {
    name: 'home',
    action() {
      mount(MainLayoutCtx, {
        content: () => <Home />,
1 Like

I haven’t found out yet if this would work with Mantra, but VeliovGroup/flow-router is now providing a way to support Meteor 1.5 dynamic imports in the router:

1 Like

Our app is React/Material-UI, react-router, and ValidatedMethods. We use Uniforms for forms. We use react-komposer v2 for HOC and react-loadable with Meteor 1.5 dynamic imports to dynamically load views such as our admin code and charts code separately along with some other larger modules. We don’t use Redux. Good luck.


Related question: Anyone has experience about moving from a) FlowRouter to react-router and b) from simple-schema to simple-schema v2 (npm version)? Is it straightforward?

I think I don’t use too many functions from FlowRouter, a couple of FlowRouter.go() and FlowRouter.getRouteName() (apart from the FlowRouter.route()s in routes.jsx files.

I use SimpleSchema's autoValue, DefaultValue, and validator() in ValidatedMethods quite often.

1 Like

What value comes out of dynamic loading? Doesn’t app.loadmodule(…) capture most of those benefits?

Dynamic loading is a really big advance. :slight_smile: