Angular / Express hosting - linux

I want to run angular on a linux box without needing node or express. I've created a website but not sure what tech is what, haha. I'm assuming I have a simple web server using express server, see code below.
var express = require ('express');
var app = express();
var path = require('path');
app.use(express.static(__dirname + '/'));
app.listen(8080);
console.log('Magic happens on port 8080');
I start this using the node server command. And the rest of the code is angular-ui.
Do I need to use express (and host this on a node compatible server), or can I just run this thing on a linux box without express? If so, do i need to replace my server.js file (above) with something else? or... Currently it's not working on the linux box, but works locally just fine.
**Edit: I tested an angular 'hello world' app on my shared server, it worked fine. When I run the full angular app on the shared server I get the following error:
Uncaught Error: [$injector:modulerr] Failed to instantiate module routerApp due to:
Error: [$injector:nomod] Module 'routerApp' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
** edit: In answer to #RobertMoskal 's question below, the angular hello world test that's working on the shared server is basically this:
<input ng-model="name" type="text" placeholder="Type a name here">
<h1>Hello {{ name }}</h1>
And the real app is basically something like this, using ui-view and ng-repeat in the html:
var routerApp = angular.module('routerApp', ['ui.router']);
routerApp.config(function($stateProvider, $urlRouterProvider, $locationProvider) {
$urlRouterProvider.otherwise('/home');
$locationProvider.html5Mode(false).hashPrefix("");
$stateProvider
// HOME STATES AND NESTED VIEWS ========================================
.state('home', {
url: '/home',
templateUrl: 'partial-home.html',
// onEnter: scrollContent
})
// ANIMATION AND NESTED VIEWS ========================================
.state('animation', {
url: '/animation',
templateUrl: 'partial-anim.html',
controller: function($scope) {
$scope.animations = [
{ title:'One', url:'http://yahoo.com', bg:'#f8f8f8', width:'160', height:'600', imageAsset:'assets/imgs/web/MyWebsites_1.jpg', paragraph:'some text of some description'},
{ title:'Two', url:'http://google.com', bg:'#f8f8f8', width:'160', height:'600', imageAsset:'assets/imgs/web/MyWebsites_2.jpg', paragraph:'rabbit rabbit rabbit'},
{ title:'Three', url:'http://bambam.com', bg:'#f8f8f8', width:'160', height:'600', imageAsset:'assets/imgs/web/MyWebsites_3.jpg', paragraph:'blahiblahblah'}];
}
})
// GAME VIEWS ========================================
.state('game', {
url: '/game',
templateUrl: 'partial-game.html'
})
// CONTACT VIEWS ========================================
.state('contact', {
url: '/contact',
templateUrl: 'partial-contact.html'
})
});

You need some web server to server your angular app as a "static" asset. This can be apache or nginx or any number of web servers. Most linux distributions make it easy to install them.
You can also go super lightweight with the built in python web server:
cd /var/www/
$ python -m SimpleHTTPServer
You can even host your application for free on github.
In all cases you you just need to make sure that the web server is serving your assets from the correct path. The above python example example you might have your app entry point in /var/www/index.html and it would be served as http://localhost:8000/index.html.

Related

express app is not sending index.html file to client

So my express app has a small Node server setup so it can serve up the index.html file when the home route '/' is hit. This is a requirement of using the App Services from Azure, there has to be this server.js file to tell the server how to serve up the client, and i had a previous implementation of this working, however i wanted to change my file structure. previously i had, the client React app in a folder client and the server.js in a folder server along with all of the conrtollers and routes. i've since moved the server API to its own application as there are other apps that depend on it. and i moved the client up one directory into the main directory. Everything was working fine till the other day when all of the sudden when you hit the home route / it will not serve up the index.html file. if you hit any other route it works, if you even hit a button linking back to the homepage, it works, but it wont serve up the app from the / and i cannot for the life of me figure out why, on my development server there are no errors in the console. and im most definitely targeting the correct directory and place for the index. but its like the server isnt reading the route to serve up.
if (process.env.NODE_ENV === 'production') {
console.log('running');
app.use(express.static(path.resolve(path.join(__dirname, 'build'))));
// no matter what route is hit, send the index.html file
app.get('*', (req, res) => {
res.sendFile(path.resolve(path.join(__dirname, 'build', 'index.html')));
});
} else {
app.get('/', (req, res) => {
res.send('API is running...');
});
}
So here im saying if the NODE_ENV is in production make the build folder static, and then whatever route is hit. (Note: i also tried this app.get with other route formats such as /* or / all have the same issues. however in my previous iteration when the client and server where deployed in the same location, /* is what i used.) The .env varialbes are setup correctly, as when the server is ran, itll console log running.. but even if i put a console log inside of the app.get() its like its never hit unless i access the route from something else first.
for example, if i place a console log inside of app.get that states hit whenever the route is hit, hitting / directly does nothing, but if i go to /login itll serve up the correct html on the client and console log hit in the terminal...
If you are having server files inside the client react app, then we are basically accessing file which are not inside our server file. So, we can serve static files using the following code:
const express = require("express");
const app = express(); // create express app
const path = require('path');
app.use(express.static(path.join(__dirname, "..", "build")));
app.use(express.static("build"));
app.listen(5000, () => {
console.log("server started on port 5000");
});
Now in your packages.json of the client react app change the name of start tag under scripts tag to start-client. Then add this following tag to the scripts tag:
"start":"npm run build && (cd server && npm start)",
Basically, this will build the react app and start the server.
It should look like this :
Also in the packages.json of your server add the following tag under script tag
"start":"node server.js"
So when you run the following command npm start it should look like this :

Error trying to render the index.html that ng build generates with node and express

I want to deploy an application that I perform with the MEAN stack on Heroku, but I encounter 1 problem.
I have this folder structure, my node server, with a public folder, where is the dist / fronted folder and all the files generated by Angular's ng build --prod, it works when I start the server and browse normally, but if I refresh the page or write a route myself, I get these errors:
Errores
Sorry for my English.
If your are building a MEAN stack, you probably have a server.js or index.js or app.js as an entry point to your application. An SPA by definition manages all the routes within the router configuration. But if you try to refresh or type a route yourself, it is like you were trying to access that folder on the server (ex: www.mywebsite.com/about, here the folder about might not exist on the server, it is just known by your Angular app)
My suggestion is that you try to add this fix to the app.js (or server.js or app.js) file, so all unexisting routes or refresh go back to your index.html:
// Check your port is correctly set:
const port = process.env.PORT || 8080;
// Is saying express to put everything on the dist folder under root directory
// Check the folder to fit your project architecture
app.use(express.static(__dirname + "/dist"));
// RegEx saying "capture all routes typen directly into the browser"
app.get(/.*/, function(req, res) {
// Because it is a SPA, all unknown routes will redirect to index.html
res.sendFile(__dirname + "/dist/index.html");
});
app.listen(port);
This guy shows full deploy on Heroku with Angular: https://www.youtube.com/watch?v=cBfcbb07Tqk
Hope it works for you!

How can I deploy / serve a react-based excel office addin?

I am writing an office addin using office-js with React. My addin sideloads and works alright but I'm running into issues deploying it.
Steps to reproduce:
Create a trial react app (addin) using the instructions here: https://learn.microsoft.com/en-us/office/dev/add-ins/quickstarts/excel-quickstart-react and https://github.com/OfficeDev/generator-office.
Sideload the addinusing npm start and everything works well when served via the dev server -- everything works well!
Try serving the add-in statically in one of the two ways (I made sure the manifest is updated appropriately):
HTTP: npm install -g serve and then serve -s dist
or
HTTPS using a server like express:
express = require("express");
https = require("https");
const PORT = 3000;
const SERVER_ROOT = "dist";
var fs = require('fs');
var server=express();
var staticOptions = {
dotfiles: 'ignore',
etag: false,
extensions: ['htm', 'html'],
index: false,
maxAge: '1d',
redirect: false,
setHeaders: function (res, path, stat) {
res.set('x-timestamp', Date.now())
}
}
server.use(express.static(SERVER_ROOT, staticOptions));
var sslOptions = {
key: fs.readFileSync('certs/server.key'),
cert: fs.readFileSync('certs/server.crt')
};
https.createServer(sslOptions, server).listen(PORT, function(){
console.log("Server started.");
console.log("Listening on port:" + PORT);
});
On loading the add-in, the task pane is blank.
Firing up a debugger or the F12 IE Chooser tool throws the exception:
0x800a139e - JavaScript runtime error: Office.js has not fully loaded.
Your app must call "Office.onReady()" as part of it's loading sequence
(or set the "Office.initialize" function). If your app has this
functionality, try reloading this page.
6.Opening the html page on a web browser complains that React and ReactDOM are undefined (happens in index.tsx, but I think eventually the modules get loaded) and then subsequently throws the same exception "Office.js is not fully loaded".
-- In case it helps, I'm using react 16.2.0 and I'm on Office 365 desktop, version 1807, build 10325 (monthly channel).
-- Also, is there a way to avoid hosting on a server and just using a manifest (in a shared folder) pointing to another shared folder? I'm thinking browserify or something similar (but browserify didnt work either and I guess webpack might be the reason). [I did see the documentation about deploying addins, but they are not very helpful in this case].

How to setup gulp browser-sync for a node / react project that uses dynamic url routing

I am trying to add BrowserSync to my react.js node project. My problem is that my project manages the url routing, listening port and mongoose connection through the server.js file so obviously when I run a browser-sync task and check the localhost url http://localhost:3000 I get a Cannot GET /.
Is there a way to force browser-sync to use my server.js file? Should I be using a secondary nodemon server or something (and if i do how can the cross-browser syncing work)? I am really lost and all the examples I have seen add more confusion. Help!!
gulp.task('browser-sync', function() {
browserSync({
server: {
baseDir: "./"
},
files: [
'static/**/*.*',
'!static/js/bundle.js'
],
});
});
We had a similar issue that we were able to fix by using proxy-middleware(https://www.npmjs.com/package/proxy-middleware). BrowserSync lets you add middleware so you can process each request. Here is a trimmed down example of what we were doing:
var proxy = require('proxy-middleware');
var url = require('url');
// the base url where to forward the requests
var proxyOptions = url.parse('https://appserver:8080/api');
// Which route browserSync should forward to the gateway
proxyOptions.route = '/api'
// so an ajax request to browserSync http://localhost:3000/api/users would be
// sent via proxy to http://appserver:8080/api/users while letting any requests
// that don't have /api at the beginning of the path fall back to the default behavior.
browserSync({
// other browserSync options
// ....
server: {
middleware: [
// proxy /api requests to api gateway
proxy(proxyOptions)
]
}
});
The cool thing about this is that you can change where the proxy is pointed, so you can test against different environments. One thing to note is that all of our routes start with /api which makes this approach a lot easier. It would be a little more tricky to pick and choose which routes to proxy but hopefully the example above will give you a good starting point.
The other option would be to use CORS, but if you aren't dealing with that in production it may not be worth messing with for your dev environment.

Unable to get connect-livereload to work with express server in gulp task

I am working off of Yeoman's gulp-webapp generator. I have modified my gulp serve task to use my Express server, rather than the default connect server it ships with. My issue is with Livereload functionality. I am trying to simply port the connect-livereload to work with my Express server rather than having to install new dependencies. It's to my understanding that most connect middleware should work fine with Express, so I am assuming connect livereload is compatible with Express 4.
Here are the contents of the relevant tasks in my gulpfile:
gulp.task('express', function() {
var serveStatic = require('serve-static');
var app = require('./server/app');
app.use(require('connect-livereload')({port: 35729}))
.use(serveStatic('.tmp'));
app.listen(3000);
});
gulp.task('watch', ['express'], function () {
$.livereload.listen();
// watch for changes
gulp.watch([
'app/*.ejs',
'.tmp/styles/**/*.css',
'app/scripts/**/*.js',
'app/images/**/*'
]).on('change', $.livereload.changed);
gulp.watch('app/styles/**/*.css', ['styles']);
gulp.watch('bower.json', ['wiredep']);
});
gulp.task('styles', function () {
return gulp.src('app/styles/main.css')
.pipe($.autoprefixer({browsers: ['last 1 version']}))
.pipe(gulp.dest('.tmp/styles'));
});
gulp.task('serve', ['express', 'watch'], function () {
require('opn')('http://localhost:3000');
});
With this simple setup, when I run gulp serve in my cmd everything spins up fine and I can accept requests at http://localhost:3000.
Now if I go and change the body's background color from #fafafa to #f00 in main.css and hit save, my gulp output will respond with main.css was reloaded, as seen in the bottom of this screenshot.
However, my webpage does not update. The background color is still light-grey instead of red.
Is there perhaps a conflict between my express server config and the way gulp handles its files? Is my Express server forcing the use of app/styles/main.css rather than the use of .tmp/styles/main.css? Shouldn't the livereload script handle the injection of the new temporary file?
Thanks for any help.
EDIT:
I was able to move forward a bit by adding livereload.js to the script block of my index file, like so:
<script src="http://localhost:35729/livereload.js"></script>
I am now able to get live changes pushed to the client. Why was this file not getting injected before? How can I ensure this is getting used programatically as opposed to pasting it into my files?
I was able to get past this issue by removing the app.use(require('connect-livereload')({port: 35729})) from my gulpfile, along with a couple of other lines, and having that instantiate in my Express server's app.js file.
My gulpfile's express task now looks like this:
gulp.task('express', function() {
var app = require('./server/app');
app.listen(3000);
});
I added in the connect-livereload just above where I specify my static directory in Express:
if (app.get('env') === 'development') {
app.use(require('connect-livereload')());
}
app.use(express.static(path.join(__dirname, '../app')));
Once I started using this setup, I was getting the livereload.js script injected into my document, and client-side changes are now auto-refreshed just how I wanted.
Hope this helps someone!

Resources