Node.js Architecture
Domains
- We structure code into domains (e.g. users, posts).
- Each domain has it’s own folder.
- Domain folder has subfolders split by technology: models, schema, views, interactors, utils, router, etc.
- Domain has
index.js
file, which exposes domain’s interface. This allows us to easily change the internal structure of the domain folder without breaking other domains which depend on it. - Domain subfolders should have
index.js
which exports modules used outside of that subfolder. This way subfolder structure can change, but imports in other files of the same domain stay the same. In domainindex.js
useexport { ... } from './subfolder'
. - Do not use relative paths when importing another domain, use
import '~/domain'
instead. This prevents imports from breaking if you need to move a file into another subfolder. - Domain names should be in camel-case.
Sequelize
- Define model in the domain and add it to global
models.js
to ensure it is loaded properly. - Import models from ‘~/models’, not directly from domains, this ensures model associations are loaded correctly.
- Define associations in
associate
method, to prevent circular imports.
GraphQL
- Domain’s graphql schema is split into
queryFields.js
,mutationFields.js
andtypes.js
to prevent bloated files. - For non-trivial resolvers use queries and interactors, which can be easily tested.
- Use sequelizeConnection from
graphql-sequelize
to define connections. Those connections will use Dataloader under the hood to efficiently load data. Use connectionDefinitions fromgraphql-relay
only when it is necessary, for example, there is no table for that connection in the database. - Use custom
circularConnection
helper to define circular connections (eg. article has many similar questions and a question has many similar articles). This prevents the issue of not defined graphql types when using circular imports.