reusing backend modules in frontend - javascript

I have a simple express application, with a server module and some client code.
My application source files were originally organized in two directories (simplified):
│ package.json
│ readme.md
│
├───client
│ client.js
│ index.html
│
└───server
server.js
colors.js
The color module (server/colors.js) is, for the purpouse of this SO question, a commonjs module that exports a single value
const color = "white";
module.exports = { color };
server/server.js contains an express application that, among other things, uses the color defined in the module, and uses the express.static middleware to serve the files in the client directory.
const color = require('./colors').color;
...
app.use(express.static(path.join(__dirname , '..', 'client')));
The client code is inserted in the <head> of index.html as a module
<script defer src="client.js" type="module"></script>
So far so good, the server starts, serves from client directory all the client files mounted at its root route.
Now, I want to reuse the server colors module also from my client code.
So I create a new directory shared and I move the colors.js source file there.
│ package.json
│ readme.md
│
├───client
│ client.js
│ index.html
│
├───server
│ server.js
│
└───shared
colors.js
Then, I change my server.js to import from the new location
const color = require('../shared/colors').color;
and, to reuse it in the client, I add a virtual path in the server, mounting a new express.static() path
app.use('/shared',express.static(path.join(__dirname , '..', 'shared')));
everything is good so far, the server requires the module, and serves both client and shared directories.
Now, to use the module in the client, I import colors in client.js
import * as colors from './shared/colors.js';
but the browser throws an error ReferenceError: module is not defined
How can I solve this error? or, what is the correct way, and best practice, if any, to reuse backend code from the frontend?

Related

Typescript: resolve relative import path when using symlinks

This seems like a dumb question, but I struggle to find the answer.
The situation
Here is my folder structure:
myProject/
├── module1/
│ ├── config.ts
│ └── init.ts #symlink
├── module2/
│ ├── config.ts
│ └── init.ts #symlink
└── symlinks/
└── init.ts # the real not duplicated file
The file init.js import local files like so:
import config from './config'
// ...
The problem
The problem is that typescript throws Cannot find module './config' or its corresponding type declarations
I tried playing with typescript option preserveSymlinks but it didn't solve my problem
I know about other ways to achieve my goal but it's overkill for just one file and it doesn't solve relaying on a relative path (like creating a npm module, creating a function and pass relative file content as parameter or even generating files at runtime...)
=> I am working with typescript in a monorepo.
Is it possible to use symlinks this way? If no, are there other (simple) alternatives?

Is an API and Router two separate things?

I have a Node.js with Express.js app. I have folders like such:
src
/models
/router
/store
/api/v1
index.js
My router folder has a file called index.router.js which contains my app's routes e.g:
import UserAPI from '../api/v1/user.api.js'
expressRouter.post('/register', function async function (req, res) {
await UserAPI.registerUser({
EMail: req.body.EMail,
Password: req.body.Password,
Name: req.body.Name
});
The above is a route to an API so it went into my index.router.js file. To perform an API action on this endpoint, I created another file for API functionality called user.api.js and it would contain something like:
async function registerUser({EMail, Password, Name}) {
// Import method from model file and perform DB action
});
As the application has grown I have come to wonder whether I have made it too complex and created an unecessary layer with a separate file of user.api.js which could possibly be refactored to be part of index.router.js.
What I do not understand is what is the standard practice of file structuring an API for scalability and should the API endpoints be in a separate file/folder of api/v1, api/v2 or should they be part of the router?
One thing that could be advantagous of having separate api files is resuability. Because it only contains functions and no routing, the functions could be reused across many different router files.
You have basically re-invented the MVC design pattern.
It's not overly complicated. It is considered good practice and encouraged.
C
Traditionally, what you call Routers is usually called the Controller. The job of the controller is simply to handle routing, handle argument parsing (request body, query parameters, is user logged in etc.) and sometimes handle validation. This is exactly what Express is designed to do. And Express allows controller functionality like authentication and validation to be refactored into middlewares.
Note: Sometimes you will see tutorials on the internet where people separate controllers and routes. My personal recommendation is do not do this. Express routing has been designed to be perfect for writing controllers. About the ONLY reason to separate them is if you have two different URLs that do the exact same thing. In my opinion that is better handled by a redirect.
M
Traditionally what you call API is called the Model. The model is your traditional collection of objects or data structures that you learned to program with. The model is what performs the application logic. Normally classes or modules that implement models are not labeled with anything. For example a user model would not be called UserAPI or UserModel but simply called User. However, what you name things is just a convention. Stick with what makes sense to you.
V
The final part of MVC is the View. In Express the view is simply res.json() or res.render() with its associated HTML template. This part is 99% already written by Express developers - you just need to tell the view functions what to send to the front-end.
Your architecture is good
There are very good reasons for separating the model (API) from the controller (router). First is that it allows you to solve your problems without polluting your core logic with parameter parsing logic. Your models should not need to worry about weather the user is logged in or how data is passed to it.
Second is that it allows you to use your model (API) logic outside of Express. The most obvious use for this is unit testing. This allows you to unit test your core logic without the web parts of the code. I also usually write utility scripts that I can use to do things like create a new user, dump user data, generate authentication token so I can use it with Postman etc.
For example you can create a script like:
#! /usr/bin/env node
// register-user.js
import UserAPI from '../api/v1/user.api.js'
UserAPI.registerUser({
EMail: process.argv[2],
Password: process.argv[4],
Name: process.argv[3]
})
.then(x => {console.log(x); process.exit()})
.catch(console.error);
Which you can then execute on the command line to create new users without needing to run the server:
$ ./register-user.js myemail#address.com 'My Name' 123456
It looks like your software is already structured according to MVC. Keep it that way. It will make maintaining and modifying the software a little easier.
API and router are two different things and even from different worlds.
Most of the applications are composed of two basic building blocks, UIs and APIs. UIs is supposed to be for humans and APIs for machines. You can have 0-n UIs and 0-n APIs. There is no rule for that.
For example UI you might have a webpage for common visitiors, application for paying visitors or those who bought your product and application for administrators. Those are three separate UIs. If one is malfunctioning, others are working.
The other example are APIs. There can be separate API for each of these UI. Also there can be APIs for third parties or other microservices of your own system. And again, if one API doesn't work, it doesn't impact others.
Router is the design pattern for URL control. Or a specific implementation of the design pattern if you wish.
While both UIs and APIs might require URL control, the same pattern can be used in both parts of the application system. But it doesn't mean it should be in the same folder. Things for building blocks should be in separate folders. Router, unlike the model, is not a common thing you would share among building blocks.
The folder structure you present here, Im sure you have seen it somewhere on the interent. But I do not consider it mature. I would consider something like that more mature:
├── model
├── website-ui
│ ├── routers
│ ├── templates
│ └── index.js // this is router
├── website-api
│ ├── user
│ │ └── index.js // this might be a router (API dependent
│ ├── item
│ │ └── index.js // this might be a router
│ └── index.js // this is router
├── index.js
└── main-router.js // this is router
Usually you don't even do main-router like that, because this responsibility goes often to load balancer outside of Nodejs. But everyone must start somewhere. This implementation is easy to upgrade later.
Do not confuse multiple APIs with API versions. In the best case scenario, you never want API versions, ever. You would proceed like this:
├── website-api
│ ├── user-old
│ │ └── index.js
│ ├── user
│ │ └── index.js
│ ├── item
│ │ └── index.js
│ ├── index-v1.js
│ └── index-v2.js
or that:
├── website-api-v1
│ ├── user
│ │ └── index.js
│ ├── item
│ │ └── index.js
│ └── index.js
├── website-api-v2
│ ├── user
│ │ └── index.js
│ ├── item
│ │ └── index.js
│ └── index.js
You can't tell now. And you shouldn't care. When you do changes in API, you do them backward compatible. If you can't do that anymore, it means you have done some critical mistakes in the past or large business changes comes in. This is not predictable.
One thing that could be advantagous of having separate api files is resuability.
Yes, but you can't tell now.
Regarding to your other questions. Stick to the SOLID rinciples. Each part of the code should have one specific purpose.
When I see your router folder, I have no idea what is there. Well I know routers, but routers of what? There can be everything, yet nothing. Thus not easily extensible = bad.
When I look at my structure, I can more easily predict what is in there.
You should design your architecture regarding to the purpose and not the specific implementations. Lets say you have two APIs because you have two purposes. Are they both REST or GraphQL? Can I share code and remove duplicities? Not that important. Sharing code is actually very dangerous if not done properly. Shared code is the worst part to refactor and it often doesn't provide as many advantages.
... I have come to wonder whether I have made it too complex...
Depends, is it a 14 days project? Yes you did. Is it for a year or more? You should go even deeper.

I am trying to access a folder outside of the current directory of my folder in express js

Their is two folders inside my folder one is made up for front-end and one is for back-end
project
├── back-end
│ ├── public
│ └── routes
│ ├── Calling.js
│ └── index.js
└── front-end
├── public
└── src
└── Components
└── Contact.js
from back-end am trying to call front end file by using sendFile()
app.get('/', function(req,res,next){
res.sendFile(path.join(
__dirname,
'../back-end',
'/front-end/src/Components/Contact'
))
})
while am running (npm start) the folder is not switch back to front-end,It is considering as a folder of back-end and showing no such file directory
Here is the error message
ENOENT: no such file or directory, stat 'D:\Project\back-end\routes\front-end\contact-form\src\Components\Contact'
I fixed this isuue by using
res.sendFile(path.format({
dir: 'D:\\Project\\front-end\\src\\Components',
base: 'Contact.js'
}))
Here I used
(path.format({dir:'path_of_file',base:'name_of_file'}))
Path.join does not combine the contents of two files, it combines two filesystem paths into a single path.
If you want to combine the contents of both files, you must read the contents of each file separately and then concatenate them together.
You want FS.readFile( path, options ).

Nodejs: Good practice to just use the index.js to EXPORTS?

I am seeing a pattern on some code I have inherited. Each directory has its JS file but there is also a index.js that actually exports items from the other JS file or files.
I presume this is done so you can see exactly what you are exporting, as the main exports are in index.js and the main code is in the other js file or files.
Is this correct? What is this pattern called ?
Should I continue using this pattern.
Let's say I have the following directory structure:
MyApp
├── app.js
├── test.js
├── package.json
├─┬ controllers
│ ├── index.js
│ ├── signIn.js
│ └── signOut.js
└─┬ views
├── index.js
├── signIn.js
└── signOut.js
Placing the following code inside the index.js files...
// index.js
module.exports = {
signIn: require('./signIn')
, signOut: require('./signOut')
};
...allows you to require an entire directory like...
// test.js
describe('controllers', () => {
// ~/controllers/index.js
const controllers = require('./controllers');
it('performs a sign-in', () => {
...
});
it('performs a sign-out', () => {
...
});
});
The alternative is to require each file individually.
Having an index.js in a directory is not required. You may require a file in a directory without an index.js all the same.
// app.js
const signOut = require('./controllers/signOut.js')
However, it gets tedious as your app grows. I use a package like require-directory as typing out each file in a directory is also tedious and somewhat error prone.
// index.js
module.exports = require('require-directory')(module);
/*
This yields the same result as:
module.exports = {
signIn: require('./signIn')
, signOut: require('./signOut')
, ...
};
*/
ES6 CommonJS Module syntax
Given these two common types of structures...
MyApp
│ // files divided per type (controllers, components, actions, ...)
├─┬ actions
│ ├── index.js
│ ├── signIn.js
│ └── signOut.js
├─┬ components ...
├─┬ reducers ...
├─┬ pages ...
│
│ // files divided per component
├─┬ components ...
│ ├── index.js
│ ├── SimpleComponent.jsx
│ ├── AnotherComponent.duck.jsx // redux "duck" pattern
│ ├─┬ ComplexComponent // large complex logic, own actions, stylesheet, etc.
│ ...
├─┬ pages ...
│ ├── index.js
│ ├─┬ App
│ │ ├── index.js // not necessary here, matter of habit
│ │ ├── App.jsx
│ │ ├── actions.js
│ │ └── reducer.js
│ └─┬ Dashboard
├── another.js
...
You can simply import files in another.js like this
import {signIn, signOut} from './actions'
import {App} from './pages'
import {ComplexComponent} from './components'
instead of this (without index.js files)
import {signIn} from './actions/signIn'
import {signOut} from './actions/signOut'
import {App} from './pages/App/App' //notice the redundancy here
import {ComplexComponent} from './components/ComplexComponent/ComplexComponent'
More reading
ECMAScript 6 modules
import - JavaScript | MDN
Babel transpiler - brings the new imports to your browser now
Structuring React projects
React Redux "Ducks pattern" - a single file approach for components
The other answers provide a lot of great information, but to try and specifically answer your question 'Should I continue using this pattern", I'd say no, at least most of the time.
The thing is, this pattern requires extra effort, as you have to maintain those extra index.js files. In my experience that effort is greater than the effort to simply write one-directory-longer import statements. Plus, you can get the same functionality you'd get from having an index.js without one, by using a module like require-dir.
All that being said, if you are making a library that will be consumed by a large number of people, like a critical module in a large programming department, or a public NPM module, then the effort of an index.js becomes more justified. As long as you have enough people using your modules, your users will (cumulatively) save more time from you adding them than you will lose maintaining them.
I will directly dive into your question on whether to use this pattern or not (as other answers are not sufficient for this).
Assuming that each directory in your code represents a standalone module (doesn't rely on another module to work). Using this pattern will give these advantages:
Better and more organized imports
Separation between internal/external definitions of each module (similar to using private/public on an interface/API)
The problems with this:
It can be very tiresome to keep loose-coupling of the different modules (JS/TS is not pure OOP)
Requires active refactoring to modules definition - more circular dependencies.
Loads more code to memory (even if unused) - though I'm not sure how bad this can be as there are optimizations that usually fix this problem when bundling production code.
Circular dependencies are very problematic, importing the whole module/directory using index.js will import all of its parts (that are declared in index.js) so if you have:
-- moduleA
├-- comp1A // needs comp1B
├-- comp2A
└-- index.js // export both comp1/2
-- moduleB
├-- comp1B
├-- comp2B // needs comp2A
└-- index.js // export both comp1/2
Example case - comp1A needs something from comp1B while comp2B needs something from comp2A
When importing the specific files (without index.js - import something from './moduleB/comp1B') you won't have circular dependencies.
But if you use index.js (import something from './moduleB') you will have circular dependencies.
My recommendation is to use index.js in the right places, and to keep those maintained! Using index.js with small modules will be perfect, but with time they will grow and should be divided. index.js is very bad to use in common/shared/utils/misc/core (whatever you call it when you want to put uncategorized and unrelated code that is used across your whole project) module.
What about this?
module.exports = {
...require('./moduleA'),
...require('./moduleB')
}
(moduleA.a will be overridden by moduleB.a)

OpenShift unable to find css and js files

When running my openshift app none of the CSS or javescript files are loading.
I have specified the directory in the server.js:
app.use(express.static(__dirname));
In the index.html I have specified the location of the folders:
<link rel="stylesheet" href="style.css" type="text/css" media="screen">
<script src = "controllers/controller.js"></script>
The structure of the folder looks like:
mytest
├── README.md
├── controllers
│   └── controller.js
├── deplist.txt
├── index.html
├── node_modules
├── package.json
├── server.js
└── style.css
When I open the website and open the developer console in chrome I get the following errors:
http://mytest-jamestreasure.rhcloud.com/controller.js 404 Not Found
http://mytest-jamestreasure.rhcloud.com/controllers/controller.js 404 Not Found
I'm not aware of anything else that needs to be added.
Link to the my openshift: http://mytest-jamestreasure.rhcloud.com/
Your construct for defining static content access seems to be correct. Make sure that you are using it with your app context though, e.g.:
myApp.app.use(express.static(__dirname));
Such a problem could be revealed either locally when trying to run the server.js or using rhc tail mytest to check the OpenShift remote logs.
I would also recommend using a dedicated directory for static content that is meant to be used publicly, rather than exposing everything:
app.use(express.static(__dirname + '/public'));
The issue was because of the following warning, which I was ignoring:
Warning: express.createServer() is deprecated, express
applications no longer inherit from http.Server,
please use:
var express = require("express");
var app = express();
It meant I had to change:
self.app = express.createServer();
to:
self.app = app;
This was in the self.initialise = function()

Categories

Resources