I'm quite new to node.js, and pretty new to Javascript (I don't count simple animations with jQuery as js). As a web-developer, I'm moving from PHP/MySQL to Express/mongo.
I like the idea of things being neat - as long as there isn't a noticeable loss in performance. As node is so rapidly developing, I'm finding it hard to find specific opinions and answers to my routeing methods for the current version of node (Most posts I find seem to be irrelevant and older than 2 years).
|- app.js
|- routes
|- blog.js
I'm using blog.js as the gateway for all blog-related stuff. This includes registering GET and POST requests with a function, and handling page-rendering.
This is all fired up with one call.
My app.js has the following:
... //basic express installation
var db = ... //mongoose database connection
require('./routes/blog')(app, db, '/blog'); //starts the blog up
blog.js looks like this:
var db = null;
var basedir = null;
module.exports = function(app, _db, _basedir){
db = _db;
basedir = _basedir;
app.get (basedir, pages.home );
app.get (basedir + '/show/:id', pages.getBlog );
/*app.get(basedir + '/*', function(req, res) {
res.redirect(basedir);
});*/
};
var pages = {
home : function(req, res) {
// whatever
}
, getBlog : function(req, res) {
// whatever
}
}
I know this works - my question, is if this is conventional? Is it something that isn't recommended? Is it memory-wasteful? Why do people place app.gets in app.js rather than an external file? What are the current mainly used routeing methods (I develop multiple small applications all on the same server, hence my wish for my app.js to be as minimal as possible).
The way you've outlined is perfectly acceptable, and in my mind, preferred to just having one big app.js file with all your routes and everything else in it.
Many people take the separating of code much further than what you've outlined, especially when trying to follow MVC and MVC-like patterns.
For example, here's a boilerplate project I'd been working on that might even go a little overboard on separation. It's not a finished product, just something I was playing with that took some of the different bits I liked from other boilerplates, frameworks, etc. I've learned some things since then and I might adjust it at some point.
NemoJS - My node/express/mongoose/jade/stylus/twitter_bstrap boilerplate project
One thing to keep in mind is the more you separate it, the more difficult it CAN be to track down problems. Not a good enough reason for not staying organized though. Which is essentially what our goal is, right?
Related
I am looking at some code from someone else for learning purposes. The way they're mounting routes is vague to me.
app.use('/dist', express.static(path.join(CURRENT_WORKING_DIR, 'dist')))
// mount routes
app.use('/', userRoutes)
app.use('/', authRoutes)
app.use('/', postRoutes)
The confusing part for me is how they're using '/' and using app.use. I'm used to doing it with app.get() and on top of that you specify the route instead of putting '/' everywhere. How does this work? Is this better practice?
The repo I'm looking at is https://github.com/shamahoque/mern-social/tree/master/server
Writing routes directly can be confusing and difficult to manage if there are large number of routes. So according to MVC pattern, the application is divided into modules/logical blocks based on functionalities they perform. For example, a simple hospital management system can have authentication, billing, payroll , medical-stock , patients etc modules (imaginary). If you are building application using MVC pattern, the common practice is to write controller for each of the module. Express provides something called middleware also called as Router to attach these controllers to respective API routes (Imagine it as a sort of map that connects each route to respective controller).
Once you define routes for each of these modules through middleware, you use those routes with your application. These routes handle requests and send parameters to controller to process.
You can learn how to use Middleware and Routers here : https://www.tutorialspoint.com/expressjs/expressjs_routing.htm
Regarding quality of code, dividing the code into modules and using routers to connect them is less tedious for others to understand. It also provides a good view of the application and it becomes easier to add new modules / functionality.
You can read more about building production-ready express app here :
https://www.freecodecamp.org/news/how-to-write-a-production-ready-node-and-express-app-f214f0b17d8c/
I am trying to write a small app with Electron that needs a database. Currently I'm testing PouchDB, but that shouldn't really matter.
For better code quality I created a class that is going to handle the common database requests - it should be the only way to access the db.
Not sure, if I understood the main/renderer process concept correctly, but I think the main process should take care about db access. So this is my current configuration:
main.js
import Database from './database'
export const myDB = new Database()
database.js (obviously only a stub)
export default class Database {
hello = () => {
console.log("Hello World")
}
}
Root.js (one of the ui components [using react])
const remote = require('electron').remote
const main = remote.require('./main.js')
...
<button onClick={() => main.myDB.hello()}>Test</button>
My question: Is this a feasible solution for code structuring or am I getting something completely wrong? My JS experiences are just using some jQuery effects and Node experience is missing completely. This is just a small hobby project, so I just wanted to start coding ;)
You have it at the right end, the database related code should be executed in the main process.
main.js is what would be the main process, but it seems to be missing the code that creates a browser window (which in turn creates the renderer process). Take a look at the example of Electron here, the magic happens at createWindow().
Root.js is executed in the renderer process, it can only communicate with the main process through 'remote' or 'ipcRenderer' - the latter being a bit more secure. A bit more information about remote can be found on electron.rocks. You are doing it the right way, in terms of code structure.
The main process is responsible for creating and managing BrowserWindow instances and various application events. It can also do things like register global shortcuts, create native menus and dialogs, respond to auto-update events, and more. Your app’s entry point will point to a JavaScript file that will be executed in the main process. A subset of Electron APIs (see graphic below) are available in the main process, as well as all node.js modules. The docs state: “The basic rule is: if a module is GUI or low-level system related, then it should be only available in the main process.”
^Quoted from somewhere
So title says it all. Never seen anyone use this syntax.
const app = require('express')()
I like to keep the main js file lean and have everything in modules so all I have there is 15 lines including comments.
Google didn't help and haven't found an answer here.
Is it bad practice to invoke express as you require it?
In general, your code should be the simplest and clearest way of reliably meeting your requirements. Any code that follows those simple guidelines will not be considered a bad practice in pretty much anyone's book.
There may be other influences on the desired coding style such as team style guidelines, coding style already present in the file/module/project and certain things you may want to do for testing, debugging or reuse. But, since you don't mention any of those influences, I will assume they are not present here.
So, with that first paragraph in mind, as long as you don't need access to the express module elsewhere in this module, then doing:
const app = require('express')();
is indeed the simplest and clearest way of accomplishing your goal and should not be considered a bad practice - in fact it should be considered a good practice.
On the other hand, if you were doing this:
const app = require('express')();
....
const mainRouter = require('express').Router();
....
const subRouter = require('express').Router();
....
app.use(require('express').static('public'));
Then, you'd have simpler and less redundant code (and perhaps a little faster since there are fewer function calls) if you loaded the express module into its own variable which you could then use everywhere else in that module:
const express = require('express');
const app = express();
....
const mainRouter = express.Router();
....
const subRouter = express.Router();
....
app.use(express.static('public'));
Something to consider is that the express module exposes some other functionality that you might want to make use of later (e.g. express.static). In your case you would have to require express again to gain access to it:
app.use(require('express').static());
Other than that there is no reason it's "bad practise". It just depends on what you intend to leverage from the module.
This is not a bad practise rather this is a short version of following code :
var express = require('express');
var app = express();
Simply put, to create an identifier for reuse and better communication to readers.
More thought just about require()
Since require() takes the responsibility to load and cache modules, some argues that it should be placed before app initialization. I see many example codes follows this style. However I think it really depends on how the package/code quality is ensured in the specific project.
Is it okay for a site to use Express for handling the routing when using Server side rendered React templates rather than React Router?
I am looking to use Fluxxor similar to this example for my components and stores/actions. Then I was planning to use Express router to handle the page routing server side, and on each route render the desired component to string. In this basic example below my app.js is a simple todo example using Flux but in production it would likely be a top level component appropriate for the routed page. e.g. /products would be a product component, with its subcomponents.
Here is my basic server.js file
var express = require('express');
var React = require('react');
var App = require('./app');
var app = express();
var port = 4580;
// include my browserify bundle.js
app.use('/public', express.static(__dirname + '/public'));
app.get('/', function(req, res) {
/* each route will render the particular component to string. */
var markup = React.renderToString(App());
res.send(markup);
});
// I will seperate my views out like this
// app.get('/products', product.list);
// app.get('/users', user.list);
// app.get('/products:id', product.list);
My basic server side render approach is here if that helps.
So as I was saying, Is it okay to use Express for the routing, as I am finding React Rouuter to be quite complex, and it just seems easier to have routes on the server, and to render each page with its components server-side.
Am I losing anything else here other than the complexity of handling the routing in Express rather than React Router? As I think I can handle that, but want to make sure I haven't messed up the point of server side rendering with React by just using Express to render to string based on different routes.
Just to be clear, I'm okay with the issues which React Router aims to solve, and understand that I will be doing something similar to what was suggested in the React Router overview as being problematic in the long run.
// Not React Router API
otherRouter.route('/', function () {
React.render(<DashboardRoute/>, document.body);
});
otherRouter.route('/inbox', function () {
React.render(<InboxRoute/>, document.body);
});
otherRouter.route('/calendar', function () {
React.render(<CalendarRoute/>, document.body);
});
While one level of shared UI like this is pretty easy to handle, getting deeper and deeper adds more complexity.
I am basically assuming that I can handle this complexity okay, whether that is true or not, I guess I will find out in time.
Sounds like you are trying to make your website isomorphic—rendering static markup on the server, attaching event listeners on the client.
The approach I use for my projects is embedding client-side javascript in the server-rendered string, so that the same props are passed down and re-rendering is not required on the client.
It seems to be very complicated to explain with only a few snippets of code, so check out this template I created for this purpose. There's also a tutorial about this topic here.
In express, I can something like this to have a static server, with directory index pages:
app.configure(function() {
app.use('/mystuff', _express.static(__dirname + "/whatever/stuff"));
app.use('/mystuff', _express.directory(__dirname + "/whatever/stuff"));
});
I would like to modify the directory index pages, by giving them different css, adding some javascript, and maybe altering the html. I prefer use as much of the existing functionality if possible, but if it is easy to just replace the whole directory middleware with my own code, that's an option. Not sure where to start with this. Of course, I don't want to actually edit code in the express or connect modules.
BTW, one reason for this is to workaround a bug I mentioned here: How do I set up static serving in Express with an arbitrary start path?
As you said in your comment, the express.directory functionality comes from Connect middleware; however, there doesn't seem to be a way to set a custom file.
As an alternative solution, you could fork Connect, change the files (located at lib/public/directory.html and lib/public/style.css), use your fork as a dependency, and do:
var connect = require('connect');
app.configure(function() {
app.use('/mystuff', connect.static(__dirname + "/whatever/stuff"));
app.use('/mystuff', connect.directory(__dirname + "/whatever/stuff"));
});
Instead of the express ones. I just tested this (by editing the files in node_module), and it worked.
EDIT:
Actually, you could probably just grab directory.js from connect and modify it and put it in your app and require() it, and then use yours instead. I haven't tested this, but I can't see why it wouldn't work.