Express.js Project Structure - node.js

I found that Express has an application generator, however the documentation does not explain the purpose of each directory and file. If someone could just give me a short explanation of which files I should be putting where, that would be much appreciated. Here's the generated app structure:
├── app.js
├── bin
│ └── www
├── package.json
├── public
│ ├── images
│ ├── javascripts
│ └── stylesheets
│ └── style.css
├── routes
│ ├── index.js
│ └── users.js
└── views
├── error.jade
├── index.jade
└── layout.jade
7 directories, 9 files

The app.js file is the entry-point of your application.
The package.json file contains all of your dependencies and various details regarding your project.
The bin folder should contain the various configuration startup scripts for your application.
For example, instead of applying all the Express middleware in the app.js file, you module.exports = {} them from their own configuration file and require them in app.js. [additional info LINK]
The views folder contains all of your server-side views.
The public folder contains all of your front-end code.
The routes folder contains all the routes that you have created for your application.
As stated in the official documentation, be aware that this is just one way to organize your code.
You should test it out and see if it fits your project.

This thread gives a deeper answer about the www file specifically: What does "./bin/www" do in Express 4.x?
Basically, running your app from the www file (which calls app.js) allows you to start your app with different configurations. You might have a "www" file representing the way the app should be run when on the web, a "dev" file that you, as the developer, would run, a "test" file you would run when running tests, etc. Read the thread linked above for more detail!

This structure is a standard organization for web-app
public contains all client static files (css, client javascript (ex. jQuery), images, fonts...)
routes contains the main back-end code (server side), which compute data before calling a template engine (see below) or respond to the client (via json of xml).
views contains each page template, see jade template. These files are used by scripts in "route"
app.js contains the express core, such as uri parser, modules, database...
package.json is the project descriptor file (used by npm for dependencies and sharing)
If the application generator provide a full example, don't hesitate to open each file (starting from app.js) to understand the project's organization.

Related

Nextjs application on Azure static web app routing issue

I have build an Nextjs application which display data from database through an API. The data should be displayed as folder structures. If a row in database is marked as folder then it should be displayed as folder otherwise it should be displayed as file. If I click on folder then an API call is made which displays the files and folders inside it. And Likewise there can be multiple folders or folder within the folders.
The application is hosted as Azure static web app. The issue which I am facing is when I am inside a folder and when I refresh the page, I get 404 error. The issue seems to be related the route configuration. I tried by adding staticwebapp.config.json, fallback route but in this case it redirects to home page.
Ideally it should stay on same page with the folder on which I refreshed the page.
Any guidance on how to setup dynamic route on Nextjs/static web app will be helpfull.
Thanks,
Rajesh
As its mentioned in the document that "You can control which requests return the fallback file by defining a filter.
In the following example, requests for certain routes in the /images folder and all files in the /css folder are excluded from returning the fallback file.
{
"navigationFallback": {
"rewrite": "/index.html",
"exclude": ["/images/*.{png,jpg,gif}", "/css/*"]
}
}
The example file structure below, the following outcomes are possible with this rule.
├── images
│ ├── logo.png
│ ├── headshot.jpg
│ └── screenshot.gif
│
├── css
│ └── global.css
│
└── index.html
Also refer to this similar discussion here.

Unable to serve react app using actix files crate

I am trying to serve a react frontend using actix server with the following service :
service(actix_files::Files::new("/app", "./react-front").index_file("./react-front/index.html")
And I have the following structure in react-front which is a react app build using npm run build:
react-front/
├── asset-manifest.json
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
├── precache-manifest.70429bbe96a34ea56e1cb1a6570602b0.js
├── robots.txt
├── service-worker.js
└── static
├── css
│ ├── main.09af38e2.chunk.css
│ └── main.09af38e2.chunk.css.map
└── js
├── 1.e6893027.chunk.js
├── 1.e6893027.chunk.js.map
├── main.dc35c614.chunk.js
├── main.dc35c614.chunk.js.map
├── runtime~main.229c360f.js
└── runtime~main.229c360f.js.map
Visiting /app I am greeted with this, where "Your React App loaded successfully" is the actual text in my index.html and the rest of the files as you can see from the network tab, gets a 404. I have placed this service before any of the routers in my App configuration, and were I to put this service after my routers I would just get this text and a 204 No Content. No more 404 errors for the react js scripts whatsoever.
This leads me to two questions:
1. What effects result from the order in which service for file resources is written for App builder?
2. How can one serve a complete folder such that the browser can obtain all the relevant css and js files necessary to display the react app?
Currently here's how I am dealing with it: I use the crate actix-web-static-files and static-files to embed the contents react-front folder into the final executable and then run it
You can see that this works now. I want to achieve this without using these crates, just actix-files, if possible.
Here's the working code for this :
HttpServer::new(move || {
let generated = generate();
App::new()
.wrap(Cors::permissive())
.route("/book", web::get().to(get_phonebook_handler))
.route("/book/{id}", web::get().to(get_by_id))
.route("/{name}", web::get().to(get_by_name))
.route("/book/{id}", web::delete().to(delete_id))
.route("/book", web::post().to(post_phonebook_handler))
.route("/book/{id}", web::put().to(put_update))
.service(ResourceFiles::new("/", generated))
})
.listen(tcp)?
.run()
.await

Running React app on Passanger

I am trying to run an react app on a server running Passenger. I can run simple Node.js apps no problem but I can not figure out how to run an React app. I am right now just in the beginning so I just created the default React sample project and I am trying to get that to run on Passenger.
I have done npm build but the suggestions for how to run that built app include yarn and serve. How would I configure the Passenger server to host my react app?
Any help on this would be very appreciated.
I know this is an older question now, but I figured out a solution for my case that allows a React app to run using Passenger that doesn't require yarn or serve -s build (which my VPS didn't let me run without being constantly logged in). I was not able to find any clear docs on how to do this anywhere else. The closest answer I found required me to build an express node server to frontend the React app (which I couldn't do for other reasons). I hope this answer helps others that might be searching for a similar solution to their question. I will add that I tested this solution on two different VPS cloud servers (DreamHost VPS and HostGator). Your VPS or server might need a modified setup to make this work.
First you need to create your production ready React app using npm run build (on your local system or your server, but I would recommend your local system). If you don't know how to do this you can look it up from the React docs in Creating a Production Build. The result of the production build should be a build directory. This is your React app encapsulated in a single deployable directory.
On the server running Passenger you will need to setup two directories (if your hosting provider didn't already do this for you) in the root level directory where Passenger expects apps to be run from. Create a public and tmp directory..
├── public
└── tmp
Note: If you are going to be running other node apps from here, then you might need a node_modules or other required directories. But they are not needed if you are just running the React app by itself.
Copy the contents of the build directory from Step 1 into the public directory on your server. The results of this should look something like this.
public
├── static
│ ├── css
│ │ ├── main.########.chunk.css
│ │ └── main.########.chunk.css.map
│ ├── js
│ │ ├── main.########.chunk.js
│ │ ├── main.########.chunk.js.map
│ │ ├── runtime~main.########.js
│ │ └── runtime~main.########.js.map
│ └── media
│ ├── background-image.########.png
│ └── logo.########.svg
├── asset-manifest.json
├── favicon.gif
├── favicon.ico
├── index.html
├── index.tmp.html
├── manifest.json
├── precache-manifest.########################.js
└── service-worker.js
Back at the root directory level, next to the public and tmp directories (not inside the public dir), create an app.js file containing this code:// app.js
// A simple Node.JS app launcher for running with Passenger.
const react_app = require("./public/index.html");
module.exports = {create: react_app.create}; This creates the node app that Passenger needs to connect too. The ./public/index.html in the code is the path to the actual entry point to your React app. But Passenger on many VPS setups is going to look for an app.js file to connect too. In some cases you might have to call this file server.js rather than app.js. This will depend on your hosting providers Passenger setup.
Finally you need to create an empty file called restart.txt inside the tmp directory. This file is used by Passenger on your server to detect when the React app should be "restarted". You simply have to do touch restart.txt from the command line on your server to have Passenger restart your service (at least that's the way it works on my server).
You should now be able to hit your React app from whatever address you have setup for your server.
The final root level directory structure should look like this (if you don't need a node_modules dir):
.
├── app.js
├── public
└── tmp
I would also recommend adding in a .htaccess file (again depending on you hosting provider) that prohibits file directory browsing and the like. Some VPS might require that you modify or add in a .htaccess file to make Passenger work at all. See your VPS specific docs for this info.
NOTE! This entire process is NOT needed if your React app can live on it's own. By that I mean that you can just upload the contents of the React production build process to the public or www or whatever "public directory" your server exposes to the world. The index.html file created in the React build folder is sufficient in many cases to serve up your React app from a web server. 😉
I tried the above answer and it worked to some extent but I found an easier way to achieve this. With this solution you can host your application on an apache or nginx server.
1.Add the homepage key to your package.json file
"author": "Your Name",
"license": "Your license",
"homepage": "https://your-domain.com/"
2.Create a production build with the below
npm run build
3.Copy the content of the generated build folder to your server root directory
4.Create a .htaccess file in the root directory with the content below
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]

How to get the current path of the running Yeoman generator

I have my own Yeoman generator.
I created a sub-generator to create a new view folder.
Basically, the usage is:
open a new terminal
cd into the parent folder
run the yeoman command yo my-generator:view
follow the instructions
This view sub-generator prompt a folder name.
For example:
If I want to create the view authentication on the default views directory.
cd views
yo my-generator:view
The result should be:
views //- Already created by the main generator
├── authentication
│ ├── authentication.controller.js
│ ├── authentication.template.html
Now, if I want to create a sub-view login for the authentication view.
cd views/authentication
yo my-generator:view
The result should be:
views //- Already created by the main generator
├── authentication
│ ├── authentication.controller.js
│ ├── authentication.template.html
│ ├── login
│ │ ├── login.controller.js
│ │ ├── login.template.html
Instead, the current (wrong) result is:
views //- Already created by the main generator
├── authentication
│ ├── authentication.controller.js
│ ├── authentication.template.html
├── login
│ ├── login.controller.js
│ ├── login.template.html
My struggle here is that I don't know how to get the current path when I run the command.
Actually, I just create the new folder with a default prefix path which is app/views/.
This is why Authentication example works.
However when my current path is deeper in the views folder, it will add the new folder at the root of the views folder.
If I could get the current path (of the cmd), I should be able to add this path as the prefix instead of setting a default and not static one.
This is why Login example doesn't works.
Some code example:
$that is the current generator object
$that.viewNameCamel is the name of the folder set by the user
I use a .txt file as template and then create the controller.js file.
const filePrefix = 'app/views/' + $that.viewNameCamel + '/' + $that.viewNameCamel + '.';
const exampleData = {
controllerAlias: 'vm',
otherVar: 'example'
};
$that.fs.copyTpl(
$that.templatePath('controller.txt'),
filePrefix + 'controller.js',
exampleData
);
Tried:
$that.env.cwd
process.cwd()
__dirname
path.js library
Similar:
Issue 1037
Question 28481715
So guys, do you have a clue on how do I get the current folder path ?
Is there an alternative solution here ?
Thanks !
EDIT 1:
The problem here is the .yo-rc.json present on the root directory of the projet.
The file rewrite the path so I should delete it to fix the problem.
However if I delete this file, the user configuration will no longer be saved.
And I need it for later sub-generator usage.
Is there another way to save the user configuration ?
Or once again, is there another way to get the current real path ?
I know this is kinda old but for any one who comes later,
from the documentation https://yeoman.io/authoring/file-system.html
If you want to know from where the user is running yo, then you can get the path with this.contextRoot. This is the raw path where yo was invoked from; before we determine the project root with .yo-rc.json.
from my experience removing the .yo-rc.json would mean that you need to manually check if the path provided is ok, having a fixed root point is something helpful.
Just remove the .yo-rc.json file from your root directory. This is the file that is responsible for locating your root irrespective of where you are in the file system.
I am not sure about the repercussions of removing it but nothing seem to have happened to the generators I built.
Now you can use process.cwd() and it will get the correct working directory.
For your use case to have a prefix app/views, you probably need to write some Javascript to append or not append the prefix based on where you are, which should be trivial.

Runtime error when sharing code between client/server in Node.js app

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?

Resources