How to migrating from "All-In-Packages" to 1.3 modules?

Ah, I see, that’s exactly my approach :slight_smile:

Hi guys,

in “All-In-Packages” I attached all my helpers, classes and toolkits to a global namespace, p.e. MyApp.*.

Right now I have my app itself running well in 1.3 WITH my global-namespace, BUT there is a BUT:

Within tests I am running into problems when trying to export/import like import {MyApp.ClassName.function} from './lib/class.js'.

What do you guys recon to do? What is best-practise?

That syntax is invalid, only single names can be imported:

import {MyApp} from './lib/class.js';

// Destructure
let {function} = MyApp.ClassName;

function();

Yeah - so you recon to keep the global app-namespace and use destructure strategy?

Hmm, well I’d actually recommend to make all of your helpers, classes & toolkits standalone modules which makes them more re-usable.

Ideally default exports should be used instead of named ones and each module should have a single purpose

It took me two weeks to convert my main app from “all in packages” to “all in modules”.
Now i have started to rewrite it from “all Blaze” to all React/Redux/Mantra. I fear it will take me two years !

1 Like

Damn… I thought I had it covered by making my Namspace work with modules - I basically kept my app-folders and have a index.js in each importing the files.

BUT now I am converting unit-tests and this whole “passing thru” of the “MyApp.”-Namespace starts to feel like abusing the modules idea. Unforunatly when keeping the Namespace you end up writing this in EVERY FILE: (especially when you start working on unit tests)

import { MyApp } from '../00_namespace.js'

// ... code

export { MyApp }

Plus Unit-Tests (meaning NOT having the index.js file or a full-app-mode available) forces you to implement imports/exports in EVERY SINGLE file, spinning a major net of imports/exports.

I guess I should do it right and get rid of my “MyApp.”-Namespace by a magor find/replaceby operation.

@vjau: how did you do it? Is your namespace still alive or did you get rid of it?

I didn’t use a namespace in the first place, sorry. I had tried, but found out it was not needed with a “all in packages” approach.

Ah I see. Thanks for the info. :slight_smile:

@vjau can you roughly scetch out what folder/file-structure you end up using?

Before the modules refactoring ?
Each “part” of the app had its own package, including template, template helpers,and business logic.
Refactoring it to modules, i used a folder for each package.
Now i’m refactoring to Mantra/Redux/React, but it’s more a full rewrite that a simple refactoring, only the div/css structure is kept.

1 Like

This is the folder structure that I plan to keep:

/client/main.js // load import/startup/client (following meteor guide)
/server/main.js // load import/startup/server  (following meteor guide)

/imports

/imports/startup/client  // simply includes /imports/app/application
/imports/startup/server  // simply includes /imports/app/application

/imports/usecases/usecase1/index.js (import files in usecase)
/imports/usecases/usecase1/...
/imports/usecases/usecase2/index.js (import files in usecase)
/imports/usecases/usecase2/...
/imports/usecases/usecase3/index.js (import files in usecase)
/imports/usecases/usecase3/...

/imports/app/application // import ALL usecases and BUNDLE them

What do you guys think of that?

How would you guys approach loading the main-application ONLY for logged in users? This should be possible now with modules, right?

I just want to note that Telescope still uses the “all-in-packages” approach (because I want people to be able to meteor add or meteor remove various features of the app) and it works just fine with 1.3. The best part is that I can avoid addFiles most of the time since you don’t need to do it when you’re importing files inside a package.

2 Likes

usecases > application > startup/client & server
Wouldn’t this import your code to both? I think you should omit the extra application importer. Can your usecases go directly under /imports?

Unfortunately, no. It enables lazy evaluation but not lazy/incremental loading/code splitting. That would be a job for a module loader like SystemJS (or webpack)

2 Likes

With “both” - do you mean client & server, meaning that code might end up on both client and server?

My application index.js looks like

import '/imports/usecase1'
import '/imports/usecase2'
// ...

then in my “imports/usecase1/index.js” I do something like

import '/imports/common/' // common stuff for all applications

// import files within "./lib/*"
import './lib/collection.js' // use-case specific collection
// ..

// CLIENT FILES (remember to always load .html first)
//  .. we need to use ``require`` here as it is conditional!
if (Meteor.isClient) {
  require ( './client/router.js' )
  require ( './client/template.html' )
  require ( './client/template.js' )
}

// SERVER FILES
//  .. we need to use ``require`` here as it is conditional!
if (Meteor.isServer) {
  require( './server/publications_and_allows.js' )
}

What do you think?

Ah I see - well, the good news is that migrating to modules lays the ground for using SystemJS.

The remaining questions is: With SystemJS: could we actually “protect” our code, so that only registered users see it?

1 Like

Yeah, but not if you’ve split the code in your usecases into client/server folders, which you have.

I suggest sticking to the import syntax (it’s future-proof!)

Then you can either:

  • Create separate index.js files in each usecase for client/server
// imports/startup/client
import '/imports/usecases/usecase/client/index';
  • Or move environment-specific code under it’s parent folder
// imports/startup/client
import '/imports/client/usecases/usecase/index';
1 Like

Yep, you can choose which code parts to load, and when.

1 Like