Setting up Express with Angular - javascript

I can setup Angular in my web app using ASP/Visual Studio rather easily, but I want to get into the Node world, more specifically Express. I'm not truly understanding a basic route handler for Express, that will support the paradigms that Angular has.
For example, when setting up an Express file, there's a million examples, but almost all of them use Jade for templating, and I'm against Jade's syntax and have no desire to utilize it.
So far, I have this for my Express server (I have commented out some questions regarding my decisions made so far):
var express = require('express'),
path = require('path');
var app = express();
var env = process.env.NODE_ENV || 'development';
// 1) Is this really necessary if I'm going to utilize Angular routing for views?
app.set('views', path.join(__dirname, '/app/views'));
app.use(express.static(__dirname + '/public'));
// 2) I'm assuming this is the desired pattern for utilizing Angular.
// A catch-all handler that serves up an html file, which will then
// hand off the rest of the routing to Angular?
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname + '/public/index.html'));
});
const PORT = 3000;
app.listen(PORT);
console.log('Listening on port: ' + PORT);
The questions I have are:
Is app.set('views', ...) necessary in an Angular app through Express or is it really intended for a Jade/EJS templating workflow? If it's useful to Angular, what path should I point it to? My Angular views? Or just the static html file that will serve as the container to all angular views?
I'm assuming app.use(express.static(...)) is still needed for ensuring Express can serve up public static resources, like css/javascript.
Is an app.get('*', ...) { res.sendFile('path/to/index.html') } route handler the accepted pattern for serving up one html file, which will contain all necessary Angular usage?
For Angular, is it normal to only have one html file for the entire of your application, and then just use Angular's routing and controllers/views to handle the rest?

Is app.set('views', ...) necessary in an Angular app through Express or is it really intended for a Jade/EJS templating workflow? If it's useful to Angular, what path should I point it to? My Angular views? Or just the static html file that will serve as the container to all angular views?
If you need to render a view on the server side and then send it to the client, you need this. Otherwise (in your case) no. You can just send the file to the user or generate a user-specific output based on the parameters that user has sent to the server. It could be anything, HTML file, json or just simple text.
I'm assuming app.use(express.static(...)) is still needed for ensuring Express can serve up public static resources, like css/javascript.
You are right. If you need to serve the static content as well, the best way is to use express.static, however you can catch the requests and serve the content by yourself.
Is an app.get('*', ...) { res.sendFile('path/to/index.html') } route handler the accepted pattern for serving up one html file, which will contain all necessary Angular usage?
If for each and every other requests that the previous routes didn't catch, you need to send the exact same file, yes it is fine.
Remember if you need to serve other HTML files as templates and they are not in the same directory as you pointed in express.static to, the client could not have access to html files. I'll discuss it in a bit.
However, I believe it is a good practice to define all the routes and not just put a * to catch them all. It is better to define a pattern at least, it would be easier to maintain the code later on.
For Angular, is it normal to only have one html file for the entirety of your application, and then just use Angular's routing and controllers/views to handle the rest?
Depends on your application. In most of the cases yes.
I've done several big angular projects, I only have one route that actually serves the main html file, and one that serves static files (pictures, js, css). I also have a route that points to the templates directory which should be served as static contents. Those are the templates that AngularJS need to work with.
For the communication between your angular app and the server, you'll probably need other routes as well. You could create RESTful API end-points to create a communication layer for the client and the server.
I usually have these two lines in the server code to keep the all the templates in the same folder. It makes it easier to manage and define work flows:
app.use(express.static(path.join(__dirname, 'public')));
app.use('/templates', express.static(path.join(__dirname, 'templates')));
For communication between the server and the client:
app.post('/login', function (req, res) {
// deal with login information ...
res.send({
done: true,
errors: []
});
});
app.post('/search', function (req, res) {
// do the search ...
res.send({
done: true,
results: []
});
});
Remember if you use * at some point in your app, the other routes that you defined after that, will never catch the request.
And
I'm against Jade's syntax and have no desire to utilize it.
Yes, me too! But there are other options as well, I personally prefer ejs. If you are using express-generator you can just pass -e switch and it'll create everything compatible with ejs.
$ express -e
Also, take a look at here.

Related

How to speed up react app being sent to the client Azure

In my application i have the client in one folder and the server in another. I successfully deployed the application to azure web apps, this can be found at: https://wulfdevpage.azurewebsites.net/ However, it takes nearly 15 seconds for the page to respond and render the client, (this is just the basic react-app client for now, but ill build this out further soon.) my problem is simply that it takes way to long for the server to respond with the application.
here is my folder structure
--client
- build
// - (other parts of the react app)
--server
- [other folders, like controllers, models etc.]
- server.js //entry point
in my server.js file this is how the build folder is served up.
// Set static folder
const __dirname = path.resolve();
app.use(express.static(path.join(__dirname, "public")));
if (process.env.NODE_ENV === "production") {
app.use(express.static(path.join(__dirname, "/client/build")));
app.get("*", (req, res) =>
res.sendFile(path.resolve(__dirname, "client", "build", "index.html"))
);
} else {
app.get("/", (req, res) => {
res.send("API is running...");
});
}
This works, but again, it's taking nearly 15 seconds from the initial request to the client reaching my computer to make this work. I know a simple solution would be to just move the client to something like azure static web apps but I really don't want to go this route, I'd rather keep them all in one place for convenience's sake. There simply must be a quicker way to serve up the client.
The major cause of performance of initial load issue is adding too many components into a single bundle file, so it takes more time to loading of that bundle files. To avoid this kind of issue, we need to structure our components in an optimized way.
To solve this react itself has a native solution, which is code-splitting and lazy loading. Which allows splitting bundle files into a smaller size. Refer here
The performance issue fix with some configuration changes. If you haven't done this already, please check below once
Enable HTTP/2
HTTP/2 brings major changes to our favorite web protocol, and many of the changes aim to improve performance and reduce latency on the web
Turn Off the Application Request Routing Cookie
Turn off the routing cookie in the Configuration blade to improve performance and resiliency.
Keep the App Service Always On
To prevent the idle shutdown, you can set the Always On flag in the App Service Configuration blade.
Use local cache
In App Setting create the app with a key of WEBSITE_LOCAL_CACHE_OPTION and a value of Always. You'll then have a d:\home folder pointing to a local cache on the machine and populated with a copy of your site content.
Use App Service diagnostic to fetch more details on the issue
Refer here for more info

Static Routing in Express.js returning 404 Error

I'm trying to create routing for different pages of my website, using express.js.
When going to 127.0.0.1:8080, it loads the index.html page fine, however, when I go to 127.0.0.1:8080/questionaire, it comes back with a 404 error and doesn't load questionaire.html. I thought that using the line:
app.use(express.static('client', { extensions: ['html'] }));
meant that this would be possible, however, it doesn't work. If there is a better way to do this then fixing the solution, inform me please.
Directory
client
-- index.html
-- index.js
-- questionaire.html
-- questionaire.js
svr.js
viewapi.js
svr.js
'use strict';
const express = require('express');
const app = express();
const view_api = require('./viewapi');
app.use(express.static('client', { extensions: ['html'] }));
const api = require('./api');
app.use('/view', view_api); // routing to api which will get data in form of JSON
app.listen(8080);
I just tried your setup and loading questionare.html worked fine for me. Did you receive any other errors from the Express server when you tried to load the page? I'm asking because I'm not sure what the contents are inside viewapi.js so when I tested it, I didn't have that file.
However, to answer this:
If there is a better way to do this then fixing the solution, inform me please.
it's good practice to separate the assets that you serve (html, css, js, images, etc.). For example, you could create sub-folders inside your client folder and put your static files in the appropriate folder.
You can also find examples and better documentation here: https://expressjs.com/en/starter/static-files.html

How to serve singular static files in express without exposing full '/static' folder?

I am creating a very simple project that uses JWT. I am serving everything via express, I do not have a frontend and backend. What I want to do is serve SPECIFIC html files based on the user's authorization (serving on https://localhost:3000 entry point server.js)
People keep recommending to use (server.js):
app.use(express.static('static'))
but this of course does not work as I can access ANY of those files by going to https://localhost:3000/whatever.i.want.
I have also tried (server.js):
app.use( '/secret' , authMiddleware, function(req,res){
if(auth){
res.sendFile(__dirname + '/static/secret.html')
}
});
but gives 404s on my stylesheet and script, as well as some weird MIME type error
Refused to execute https://localhost:3000/script.js as script because "X-Content-Type: nosniff" was given and its Content-Type is not a script MIME type.
It works if I add:
app.get( '/styles.css' , function(req,res){
res.sendFile(__dirname + '/static/styles.css')
});
app.get( '/script.js' , function(req,res){
res.sendFile(__dirname + '/static/script.js')
});
But do I really have to do this for every single stylesheet and script I use? There has to be a better way!!!
1.) What is the best way that people do this? Specifically, is it possible to create authorized web-apps without using a frontend and serving all your static files from the backend?
2.) Is it necessary that your static directory is publicly accessible? Meaning you can only cast authorization constraints on certain endpoints, then use a script file that calls those endpoints? Which would still allow you to view the base HTML, just not any results of the API calls. Which in effect works but is gross.
File system
server.js
/static
/blah.html
/secret.html
/secret.css
/secret.js
If you want to selectively serve assets from the express server, you could do something like this:
let secrets = ['secrets.html', 'my_diary.html']
app.use((req, res, next) => {
let shouldBeAuthorised = secrets.some(s => req.url.includes(s))
if (shouldBeAuthorized)
// check they are authorized to be served this content
else
// just serve the content, carry on... no need to worry
})
app.use(express.static('static'))
My use of req.url.includes is very shaky, and with a more complicated list of files, could result in you requiring authorization for files that aren't explicitly in the blacklist... but the basic structure of the above code should achieve what you're looking to achieve.
You can solve this by having a folder called public, which you can put all the css, js in that folder. And use static middleware to serve the public folder
app.use(express.static('public'))
Then there is another folder called secret, which you will build routes, validate JWT token and serving html files based on user permission

For Express.js 4.x, is it possible to use express.static twice?

I would like to show a custom 404 page (containing html, css, img, and ico). I know my 404 folder works when I replace the first public static homepage. However, I believe I am either not using routes the right way or it is not possible to set up two static folders.
I do not want to use template view engines at all. I want everything to be rendered on the frontend.
My project looks as follows:
404
--index.html
--error.css
--404.jpg
bin
--server.js
public
--index.html
routes
--index.js
package.json
app.js
app.js
...
var index = require(./routes/index); //works
...
app.use(favicon(__dirname + '/public/content/images/logo.ico'));
app.use(logger('dev'));
app.use(jsonParser);
app.use(urlencodedParser);
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public'))); //love it
app.use('/', index); //this is fine
...
index.js
var express = require('express');
const path = require('path');
var router = express.Router();
router.use(function timeLog(req, res, next) {
console.log('Time: ', Date.now());
next();
});
router.use('/', express.static(path.join(__dirname, './404'))); // HALP!
module.exports = router;
I've played around with the directory (trying to use '404' vs './404'). I am testing this by entering "localhost:3000/error". So if my path is '/error', it should still use the parent path: '/'. The documentation states that as long as my route is placed last, it should still work. I tested it without express.static and used an anon function that prints error on console.
Is it impossible to use express.static() twice?
Moving some of my comments into an answer since this led to your solution.
For Express.js 4.x, is it possible to use express.static twice?
Yes, you can use express.static() as many times as you want. It is middleware and, if it does not find a file matching the request, it just calls next() and allows the middleware chain to continue. So, you can have as many of them as you want and they will each get to search for a matching file in the order you register them.
I would like to show a custom 404 page (containing html, css, img, and ico). I know my 404 folder works when I replace the first public static homepage. However, I believe I am either not using routes the right way or it is not possible to set up two static folders.
You are mistakenly trying to use express.static() to implement a custom 404 page. That is not what it does. The usual way to implement a custom 404 page is with the last middleware handler in the chain. When that gets hit, nothing else has found a match for the current request, therefore you send your custom 404 page.
That typically looks like this:
app.use(function(req, res, next) {
res.status(404).sendFile(localPathToYour404Page);
});
See the "How do I handle 404 responses" section of this Express starter FAQ.
And, here's an article on custom error pages that shows some other examples.
https://github.com/jekku/users/blob/master/server.js#L41
Here's how I route my static files on an ExpressJS app. I usually don't do it in the routes, but I consider it as an 'initialization' process. It is possible to use ANY middleware twice or even more - as much as you want, keep that in mind.

Filesystem Module in Parse Web Server

I am currently attempting to use Parse Web Hosting to setup a website for my iOS application. I am attempting to show a PDF file in the web browser located within my website directory. I am using express and heres whats going on so far
var express = require('express');
var app = express();
var fs = require('fs');
// Global app configuration section
app.set('views', 'cloud/views'); // Specify the folder to find templates
app.set('view engine', 'ejs'); // Set the template engine
app.use(express.bodyParser()); // Middleware for reading request body
app.get('/terms', function(request, response){
fs.readFile("/public/terms_conditions_hotspot.pdf", function (err,data){
response.contentType("application/pdf");
response.render(data);
});
});
app.listen();
So when I navigate to mysite.parseapp.com/terms, I get a 500 error.
But to make sure everything is setup correctly, I used Parse's boilerplate code to render a hello message when you navigate to mysite.parseapp.com/hello.
app.get('/hello', function(request, response) {
response.render('hello', { message: 'Congrats, you just set up your app!' });
});
This seems to work fine. Anyone know what the issue is?
My goal is migrating my Django Web app to using Parse Web Hosting instead mainly because Parse supports SSL and supplies free certs, which makes building this application cheaper (free). Although, my Django Web App's purpose is to deal with Stripe Connect redirects and used oAuth2, which may be problematic with the migration, seeing as Parse may not support certain modules or whatever. I just feel Parse is very limited with their services but I am anxious to see what I can do with it.
EDIT
So I ran console.log(error) and it returned:
Object [object Object] has no method 'readFile'
readFile is definitely a method that fs ('filesystem') contains. So maybe the module 'fs' in Parse isn't up to date or refers to a different module?
What the deuce?
Parse doesn't appear to use NodeJS (fs is a Node module) even though they offer Express.
See: https://www.parse.com/questions/loading-nodejs-packages-to-cloud-code

Categories