I'm rather new to web development all together. I'm trying to get a node.js/express/mongo project off the ground. I'm coming from a C/C++ background, and the module organization paradigms seem a little strange to me.
Currently, in my server.js, I create, connect, and initialize my mongoDB object using mongoose, then pass around this object query, insert ect on it. Doesn't seem like something I should be doing inside server.js.
Is the proper way to loosely couple Mongo from my project by creating a separate module (ex. database) where I do all the initialization, options, ect, and return a mongodb instance through this new module?
I've never undertaken a project of this size (or type) before, and just don't know how to best organize everything..
Any advice from those people much more experienced than me would be appreciated
Many ways to do it. Here's some ideas.
Yes, you'll want to have a routing/handlers setup of some kind so that different modules have the ability to call different services and/or decouple.
Below is a fairly standard node.js / express structure:
├── server.js
├── config
│ ├── development
│ ├── production
│ └── staging
├── handlers
│ ├── customers.js
│ └── stores.js
├── node_modules
│ ├── assert
│ ├── ejs
│ ├── express
│ ├── forever
│ ├── mongodb
│ └── mongoskin
├── package.json
├── README.md
then in server.js, you can import your handlers like so:
// import route handlers
var customers = require('./handlers/customers'),
stores = require('./handlers/stores');
and then inside your handlers, you'll be able to declare functions:
exports.addCustomer = function(req, res) {
// ....
};
which in server.js you can use for routing:
app.post('/customers/add/:id, metrics.addCustomer);
so then you've got a basic framework. Just defining the database connections outside of the exports.XXX functions in the handler files is fine because those functions will have access, but not anything in server.js so you won't pollute your namespace.
var url = config.user +":"
+ config.pass +"#"
+ config.host +"/"
+ config.database;
var mongo = require('mongoskin').db(url);
where you might load the config object from a JSON file.
hope that helps.
Related
I have created the following project structure using NestJS
.
├── app.controller.ts
├── app.module.ts
├── app.service.ts
├── config
│ ├── config.controller.ts
│ ├── config.module.ts
│ └── config.service.ts
├── handlers
│ ├── handler1.ts
│ ├── handler2.ts
│ └── handlers.module.ts
├── main.ts
└── producer
└── producer.ts
Both the handler files wiz. handler1.ts & handler2.ts look something like this:
export const handler = async (args) {
...
...
}
I've ConfigModule in which I've registered ConfigService as a provider. What I want to do is I want to somehow use ConfigService in handler1.ts & handler2.ts. Now mind you, these handlers are not classes, but just normal function expressions. I know if they were classes, I could have injected ConfigService in the handler's constructor using Dependency Injection. But, unfortunately, declaring these handlers as classes is no more an option now. The reason behind that is that these handler files are being consumed by producer.ts and producer.ts reads the entire file and expects an exported function.
I went through the NestJS documentation and found about property-based injection, module-ref, but they were of no help. I also found this link which I think is very close to my problem, But after going through the comments I found out this is not possible.
I don't have much liberty in changing the existing code but I'd still like to know what options do I have here. A solution that would require fewer changes and solve my problem. Thanks!
Note: File handlers.module.ts is serving no purpose in this scenario.
I am using the following folder structure for my express CRUD application. I use it to have ideal manageable code of each file containing not more than 70 lines of code. What are your thoughts on the folder structure?
.
├── bin\
│ └── www
├── common\
│ ├── enums\
│ │ └── logTypesEnum.js
│ └── validators\
│ └── studentNameValidator.js
├── config\
│ └── db.js # config file for database connection
├── models\
│ └── log.js # contains model data for model 'log'
├── routes\
│ ├── log\
│ │ ├── index.js # handles all routes for /log/ endpoints and requires files in the directory and also contains middleware code
│ │ ├── insert.js # handles all routes for /log/insert endpoints
│ │ ├── remove # handles all routes for /log/remove endpoints
│ │ └── exportCSV.js # handles all routes for /log/exportCSV endpoints
│ └── student\
│ ├── index.js
│ ├── insert.js
│ └── remove.js
├── public\
│ ├── javascripts
│ ├── images
│ └── stylesheets
├── views\
│ ├── log\
│ │ ├── index.jade
│ │ ├── insert.jade
│ │ ├── remove.jade
│ │ ├── exportCSV.jade
│ └── student\
│ ├── index.jade
│ └── insert.jade
└── app.js
I am not sure why you decided on the number 70 unless you read somewhere that 70 makes some sort of ideal microservice which your structure does not allow for anyways.
As to the directory structure. I have come to the conclusion that internal directory structures are usually based on the programmer or team leader. It is more of a matter of what makes sense in your head as you see the visual design and implementation of your code.
That said, IMHO, overly complicated or let us say overly structured directory structures in Node and say for instance PHP cause an inordinate amount of moving up and down directory trees in order to access code, classes or just plain functions. Not to mention that it becomes jibberish for those who may come after you to maintain the code.
So use the directory structure you feel at home with. But make it clean and not complicated. Do not try to pigeonhole every aspect of every call and function into a specific 70 line definable directory structure. (again no clue where that number came from).
Clean, simple and sensible.
Those would be the best rules to follow IMHO.
Edit based on OP questions below:
Clarity of code is not defined by the amount of lines. When I test coders, no matter what language they specialize in, put some code up on the screen and ask them to translate that code line for line into plain English. First this actually tests the candidate ability. And second if the code is clear and good, then any other coder should be able to read it and clearly understand what is going on in the code. (Actually it tests both the original coder and the candidate.)
So clear code is not about lines. It is about excellent coding practices and the ability to make your code do what you envision.
Microservices has become sort of a buzzword. But essentially it simply means "focused". It means that you are creating a module to do a specific task So each module in your system does a specific task or tasks essential to your system and only focuses on that task. I think that may be actually what you are striving for. There are quite a few really good articles out there on Node and Microservices.
I have a folder structure like so:
.
└── client
├── components
└── routes
├── index.js
├── Login
│ ├── index.js
│ ├── assets
│ ├── components
│ ├── container
│ └── modules
└── UpdatePassword
├── index.js
├── assets
├── components
├── container
└── modules
I would like to see if anyone is importing files from the UpdatePassword folder to the Login folder and vice versa.
Basically I'm following a fractal project structure where I want components that are related to the UpdatePassword or Login route to only exist in their respective folders. Shared components would exist in the client/components subdirectory. To maintain a structure like this, I would like to write a test that fails when an 'unacceptable' imports or require is used. I.e. if a file in UpdatePassword imports from Login/components.
Is there a way to test or check whether an import is coming from specific folders?
Try madge: I usually run it as madge --image /path-to-folder/dependencies.png routes (There is also a exclude option if you need it)
You'll get a visual graph which shows you dependencies between files.
I have no idea about native way to do it.But you can wrap "require" function:
function myRequire(fromPath, requiredPath) {
//code to judge whether or not can load requiredPath from fromPath
var can = ...
if(can) {
return require(requiredPath);
}
else {
throw new Error(`you can not load ${requiredPath} from ${fromPath}`);
}
}
I have a Node.js project with this basic folder structure:
├── project
├── client
├── app
├── assets
│ └── css
└── components
├── about
├── categories
├── home
├── navbar
└── posts
├── common
├── model
└── util
├── server
├── api
├── model (deprecated for ../common/model)
├── conf
└── db
server is an Express API, client is an Angular2 App using this API. I use Gulp to build a dist folder which is being deployed to AWS Elastic Beanstalk.
Important: In dist, Client lives in app folder, while Server is in the root.
Everything was working fine until I decided to share some code between Server and Client (that's the point in Node.js I thought...). I've created a common folder in project's root with, among others, a post model (/project/common/model/post.ts)
In Server's /project/server/server.ts I replaced:
import {Post} from './model/post'
for:
import {Post} from '../common/model/post'
And it works.
But in Client's /project/client/app/components/posts/post-list.component.ts I replaced:
import {Post} from './post'; // Model was in the same folder here...
for:
import {Post} from '../../../../common/model/post';
and it compiles fine but then, when I try to reach Client in my browser, I get:
zone.js:101 GET http://127.0.0.1:3000/common/model/post 404 (Not Found)
(index):24 Error: Error: XHR error (404 Not Found) loading http://127.0.0.1:3000/common/model/post
I've checked and my Gulp's build task is correctly moving the compiled (transpiled) common files to dist/common.
Any hint on how to proceed to solve this? Thank you so much!
Presumably common has to be accessible from the browser, but is your webserver serving up files in the common folder?
In your express configuration you'll likely have something like this to serve up static content:
app.use(express.static(__dirname + '/public'));
But did you do the same for the new common folder you have?
In Cloud9 Express IDE example I see in folder/file routes/users.js - please tell me why this is in separate file -what is the intention of users.js as a distinct file? :
/*
GET users listing.
*/
exports.list = function(req, res){
res.send("respond with a resource");
};
ok Im trying to answer that one myself (feel free to chime in):
The basic Express set up folder structure according to Expressjs.com looks like this:
├── app.js
├── bin
│ └── www
├── package.json
├── public
│ ├── images
│ ├── javascripts
│ └── stylesheets
│ └── style.css
├── routes
│ ├── index.js
│ └── users.js
└── views
├── error.jade
├── index.jade
└── layout.jade
It is suggested and not obligatory. However for noobs like me this helpful website says:
If you are getting started with Express it is recommended that you use the structure from the generator.
Edited:
In the particular folder structure generated in Cloud9 Express the file /routes/users IS intrinsic to a typical Express-Jade setup.
Basic routing tutorial here answers what each of these files is doing