Much easier to reason about which specific functionality is located where. If we need to add a feature to contacts, all the biz logic is in once place. No more hunting down and editing files used for multiple features.
Two key things we are doing. First, we use relative imports within a module/functional area and absolute imports across modules. This is helping us future proof code so we can eventually get rid of /imports
if lazy loading becomes the default in the future.
Secondly, we are using index.js files to import all public apis and re-export them, which makes it really easy to use the functionality somewhere else. For instance, /imports/api/contacts/index.js
contains this:
// Initialize all key files and re-export contacts public facing api
export {default as Contacts} from './Contacts.js';
export {
contactsAddMethod,
contactsEditMethod,
contactsDeleteMethod,
contactsUndeleteMethod
} from './methods.js';
export {contactFormSchema} from './schema.js';
If I need to add the ability to add a new contact in my foo module I know exactly where to look for what APIs I can use and how to import them like: import {Contacts, contactsAddMethod, contactFormSchema} from '/imports/api/contacts';
We are really liking the additional productive we are getting with ES6 and this new app structure.
We are also just about to have all our code pass AirBnB ESLint rules with the following rule variations we added:
'rules': {
// The total number of characters allowed on each line of code including indentation
// http://eslint.org/docs/rules/max-len
'max-len': [2, 120, 2, {'ignoreUrls': true, 'ignoreComments': false}],
// Require constructors to use initial caps
// http://eslint.org/docs/rules/new-cap
'new-cap': [2, {'capIsNewExceptions': ['Match', 'Match.ObjectIncluding']}],
// Require a space after unary operator ! and not before new
// http://eslint.org/docs/rules/space-unary-ops
'space-unary-ops': [2, {
'words': true,
'nonwords': false,
'overrides': {
'new': false,
'!': true
}
}],
// Disallow reassignment of function parameters, but allow modifying the properties of parameters
// http://eslint.org/docs/rules/no-param-reassign
'no-param-reassign': [2, {'props': false}],
// Dangling commas on multiple lines are not required
// http://eslint.org/docs/rules/comma-dangle
'comma-dangle': [2, 'only-multiline'],
// Allow quoting properties as needed
// http://eslint.org/docs/rules/quote-props
'quote-props': [2, 'as-needed', {'keywords': true, 'unnecessary': false, 'numbers': false}],
// Wrap the function expression for immediately-invoked function expressions (IIFE)
// http://eslint.org/docs/rules/wrap-iife
'wrap-iife': [2, 'inside'],
// No space after or before a curly brace wrapping an object or import
// http://eslint.org/docs/rules/object-curly-spacing.html
'object-curly-spacing': [2, 'never'],
// Put a blank space before line comments except at beginning of an object or block
// http://eslint.org/docs/rules/lines-around-comment
'lines-around-comment': [2, { 'beforeLineComment': true, 'allowObjectStart': true, 'allowBlockStart': true }],
}