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.jsfile, 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.jswhich 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.jsuseexport { ... } 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.jsto ensure it is loaded properly. - Import models from ‘~/models’, not directly from domains, this ensures model associations are loaded correctly.
- Define associations in
associatemethod, to prevent circular imports.
GraphQL
- Domain’s graphql schema is split into
queryFields.js,mutationFields.jsandtypes.jsto prevent bloated files. - For non-trivial resolvers use queries and interactors, which can be easily tested.
- Use sequelizeConnection from
graphql-sequelizeto define connections. Those connections will use Dataloader under the hood to efficiently load data. Use connectionDefinitions fromgraphql-relayonly when it is necessary, for example, there is no table for that connection in the database. - Use custom
circularConnectionhelper 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.