Nodejs Micro service architecture share models in a common project - node.js

I have somewhat large node application and planing to change it to Micro Service Architecture as follows.
Service1
--controllers
--services
--package.json
Service2
--controllers
--services
--package.json
CommonService
--models
--helpers
Can I have all models and other common helpers in separate project and refer them rather than keeping them in all projects.

So to be clear. You can do this two ways.
First you can create in git micro service with all helpers/services that you need. Then just add it in package.json like this
"yourModuleName": "git+ssh://git#github.com:yourName/yourModuleName#Branch",
Second way looks similar. You can create npm module(https://www.npmjs.com) add in in package.json like this
"yourModuleName": "yourModuleNameFromNPM",
Then in your main core module just do
const yourModuleName = require('yourModuleName');
Dont forget to run npm install
And you're done.
Hope this helps.

Related

Type-graphql with lerna --- Error: Cannot determine GraphQL output type for id

I have recently moved from yarn/workspaces to lerna/npm, and in that move I have unearthed an unexpected problem. I know get:
Error: Cannot determine GraphQL output type for id when generating my schema
I am using type-graphql along with typeorm (a wonderful combo)
My package structure looks like the following
/app
/packages
/utils (common functions)
/data (my TypeORM entities, repos, factories, decorated with type-graphql)
/server (my type-graphql server) deps on #app/data
/server-test (tests my server) also deps on #app/data
after I do a:
lerna clean
cd app/packages/server
npm run start
I now get Error: Cannot determine GraphQL output type for id
both data and server's package.json refer to "type-graphql": "^0.17.4"
======
Note in: https://github.com/19majkel94/type-graphql/issues/69
#19majkel94 states the following:
The last error Cannot determine GraphQL output type for id basically
comes from getGraphQLOutputType and convertTypeIfScalar which performs
if type instanceof GraphQLScalarType. The problem is that separate
project has separate node_modules so GraphQLScalarType !==
GraphQLScalarType.
From my experience there's always too much problems from separating
things to projects/modules than the benefits of this. I would
recommend restructuring your app to don't need this.
So that seems a bit nuclear for me to forgo lerna, and modularization. I would love to see if there is a way to make this work.
Just use dependencies hoisting, so all your packages will use the graphql module from the root node_modules.

How to deploy NodeJS multi module/package project? (frontend & backend)

I tried to create a multi module/package project with npm today.
The structure is as following:
root
|
|____ backend <-- npm package containing all routes
|
|____ frontend <-- npm package containing all js/html/css files
|
|____ dist <-- merged output from backend & frontend
|
|____ build_and_run.sh <-- shell script to invoke npm in both - frontend and backend and run the final application in "dist/"
The frontend should be in the "dist/static" directory.
Both - the frontend and backend are using different dependencies and compiling steps (TypeScript, VueJS etc.), so the differentiation between frontend and backend currently makes the most sense to me.
My problem is the deploying of both modules/packages into the final directory.
Copying the files isn't a problem, but deploying dependencies into the "dist" directory is (e.g. express).
The second goal is to create a Docker file, but this option shouldn't be neccessary for running the server.
If someone has a better structure or solution fitting my needs, I would definitely appreciate to hear it.

How to organise file structure of backend and frontend in MERN

I have backend based on express + mongoose. File structure is:
- /models
-- item.js
- /node.modules
-- ...
- server.js
- package-lock.json
- package.json
And regular create-react-app based folder for front-end:
- /src
-- /assets
--- index.css
-- /components
--- Somecomponent.js
-- /containers
--- App.js
-- /reducers
--- somereducers.js
- /node.modules
-- ...
-- index.js
-- registerServiceWorker.js
- .gitignore
- package-lock.json
- package.json
I want to use it in proper way together. I wanted to organise it this way:
- /client
-- /src
...
-- index.js
-- registerServiceWorker.js
- .gitignore
- package-lock.json
- package.json
- /server
- /models
-- item.js
- /node.modules
-- ...
- server.js
- package-lock.json
- package.json
At this stage I stuck. I can make it if client folder inside server folder or if server folder inside client.
1. But how to make it run when two folders are siblings?
2. What should be package.json and where node.modules should be (whether both server and client should have it's own package.json and modules?)
The most basic structure would be to have a root folder that contains frontend and backend folders. Since you're talking about the MERN stack, you would have a package.json inside of your NodeJS backend environment and a package.json for your React side of things. Backend server and the frontend client are two totally separate things, so yes, they both have their own node_modules folders. On the backend, you'll probably have installed something like Express for your Node runtime, Mongoose for a more convenient way to talk to your MongoDB, etc, and on your frontend, you'll have your React as your frontend framework, Redux for state management, etc. Additionally, depending on what you have already listed inside of your package.json files, when you run npm install separately it will be installed in those two folders. If you want to install additional packages, just run npm install + "the name of the package" (without the '+' and without the quotes) inside of that particular folder where you need it (backend or/ and frontend).
I hope this was helpful. Check out the pics, especially the 2nd one.
App structure
Folder structure
UPDATE:
In development, I suggest installing two additional things:
npm i -D nodemon
npm i -D concurrently
Note: The -D flag will install them as devDependencies.
nodemon is going to track every file change and restart the backend server for you. So, it's obvious that it should be installed inside of the "backend" folder. All you have to do is go inside of the package.json file (backend) and add a new script. Something like this:
"scripts": {
"start": "node app.js", // in production
"dev": "nodemon app.js", // in development
}
concurrently allows you to start both your frontend and backend at the same time. I suggest initializing a new Node project inside of the top-level root folder -[folder which contains both, your frontend and backend]. You would do that with the npm init command, and after that, install the concurrently package there.
Now, go open your newly created package.json file inside of your root folder and edit the start section, like this:
"scripts": {
"dev": "concurrently \"cd backend && npm run dev\" \"cd frontend && npm start\" "
}
What this will do is go inside of the backend folder and run the dev command (the same one we just configured), so that will start nodemon. Additionally, it will also go inside of the frontend folder and run the default start command -which is exactly what we want.
If you kept the folder structure, installed all the dependencies (including the additional two I mentioned above), changed the package.json file inside of your root folder, you'll be able to start them both with a simple command:
npm run dev // make sure you're inside of the root folder when doing so :)
Adding to the accepted answer, the folder structure division inside the frontend and backend is more useful if it is based on business logic rather than tech logic.
Dividing the whole stack into self-contained components that preferably don't share files among them is the best way to make your app more testable and easy to update. This in the smallest possible way is what commonly known as microservice architecture.
Bad Design : difficult to update and test:
Good Design : easy to update and test:
Use Structure as per your requirement, like based on the project scope or depth. But make sure to keep the endpoints and models separate, so initially have a setup like such
src/
controllers - for the endpoints
models - for the schema
server.js - or index.js

Conventions for app.js, index.js, and server.js in node.js?

In node.js, it seems I run into the same 3 filenames to describe the main entry point to an app:
When using the express-generator package, an app.js file is created as the main entry point for the resulting app.
When creating a new package.json file via npm init, one is prompted for the main entry point file. The default is given as index.js.
In some programs I have seen, server.js serves as the main entry point as well.
Other times, still, it seems as though there are subtle differences in their usage. For example, this node app directory structure uses index.js and server.js in different contexts:
app
|- modules
| |- moduleA
| | |- controllers
| | | |- controllerA.js
| | | +- controllerB.js
| | |- services
| | | +- someService.js
| | +- index.js <--------------
| +- index.js <-------------------
|- middleware.js
+- index.js <------------------------
config
+- index.js <------------------------
web
|- css
|- js
server.js <----------------------------
What are the differences, if any, between these three names?
Even though you can call the files anything you want, there's an advantage to calling the entry point index.js or server.js
Why index.js:
When you issue npm init it will set the main entry point of the module to index.js. Some people don't change it, so they end up naming their main entry point index.js. It means there's one less thing to do.
Why server.js:
If your node package is not going to be consumed by another package, but rather is a stand-alone app, then if you call your main entry point server.js, then you can issue npm start and start your app. npm start will run your server.js file by default. To change this behavior, supply a start script in package.json. If a start script exists, npm start will run that script instead.
app.js is just a convention -- the only advantage to it is that some IDEs, such as Visual Studio Code will default to app.js as the entry point of a program you debug. That way when using the most common framework, Express, which creates an app.js file, "it just works"
It's pretty simple!
If your application is to be used in other applications: index.js
If your application is NOT to be used in other applications: server.js or app.js
As stated earlier the reasons being, when invoking npm start, if not defined in package.json, looks automatically for server.js. And when including another module into your application, it looks for index.js.
Extra:
I also tend to only use index.js as a file name when this is automatically found somehow. This makes me aware if the file is invoked directly or indirectly.
When using npm init it makes the default index.js.
Where I work, we didn't really settle on a format, so we have some apps with index.js, some with server.js.
Also, in some we have a config.js file at the root level, others are in a config folder (so require(config/config.js).
We even have one where server.js is in a server folder.
The trouble comes when we want to automate our deployment process. It becomes like technical debt when we have to make a bunch of minor modifications for each service.
That said, pick a format that makes sense to you and stick with it.
In fact all are just names and you must be consistent in your own work as pointed out by #Oka in a previous answer.
The only valid point here is that modular nature of node may play an important role in your decision, as pointed out in Folders as Modules section of NodeJS documentation there are 3 ways in which a folder may be passed to require() as an argument and the second and a common one is to automatically load the index.js file from the folder, this is how a lot of NPM packages are built and as it is simple and standard according to automatically loading NodeJS feature. It seems the best choice if you are developing an NPM package.
In the end, as others pointed out, you can choose any of the three, or even another one, but stick to your decision. My decision was to always use index.js based on the mentioned fact above.

is it possible to have multiple modules defined in tsconfig?

Ok, so I'm making a angular2 app with a node server. I've followed the 5min tutorial so I'm using "system" as the module system. However I am using a simple node express server instead of the way they have in the tutorial. I am writing this in typescript as well, but it is also compiled to "system" style of importing modules. And when running the server I get System is not defined.
How do I fix so System is defined when starting the server?
Is it not recommended to use "system" as the compiler option "module" in the tsconfig-file, when writing a node server?
Can I compile the server code with eg "commonjs" and the angular front end with "system"?
How do I do the configuration of module loading (the small script they have in the index.html) if I would not use "system" in the front end either?
I would recommend to split front-end and back-end applications into different projects and make them communicate through a REST service. I mean the server application will provide the service and the front application will consume it using AJAX.
This way you will be sure that there won't be conflict between the tools you use. For example the use or not of SystemJS. You'll be free to use SystemJS in the Angular2 application as described in the 5min tutorial of the angular.io website and commonjs for the Node / Express application.
The following article describes how to do that:
Angular2 TypeScript Gulp and ExpressJS - http://blog.edenmsg.com/angular2-typescript-gulp-and-expressjs/
As #Thierry Templier suggested, you need to split your code into /client and /server to be more maintainable and structured, if you didn't do that yet.
You can create two tsconfig.json files, put one into /server and other into /client folder.
/server
tsconfig.json ( with module: commonjs )
/client
tsconfig.json ( with module: systemjs )
When you are invoking tsc from shell, you use --project command:
tsc -p ./server <-- /server/tsconfig.json is loaded
tsc -p ./client <-- /client/tsconfig.json is loaded

Resources