Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular SSR 'Failed to lookup view' on production (Ubuntu, Nginx)

Following up the official Angular tutorial on setting up SSR using Express server: https://angular.io/guide/universal#configure-for-universal

The tutorial would setup paths like this:

...
const DIST_FOLDER = join(process.cwd(), 'dist');
...
app.set('views', join(DIST_FOLDER, 'browser'));

This works pretty well on the local server.

However once deployed at the server (powered by Nginx), getting the error:

Error: Failed to lookup view "index" in views directory "/home/user_name/dist/browser" at Function.render (/var/proj_name/server.js:44670:17) at ServerResponse.render (/var/proj_name/server.js:53701:7) at /var/proj_name/server.js:121:9 at Layer.handle [as handle_request] (/var/proj_name/server.js:46582:5) at next (/var/proj_name/server.js:46330:13) at Route.dispatch (/var/proj_name/server.js:46305:3) at Layer.handle [as handle_request] (/var/proj_name/server.js:46582:5) at /var/proj_name/server.js:45805:22 at param (/var/proj_name/server.js:45878:14) at param (/var/proj_name/server.js:45889:14)

How to handle this correctly so the app works properly both locally (for development) and on the production server?

EDIT:

Have also tried to use __dirname instead:

app.get('.', express.static(join(__dirname, 'browser')));

But this fails both locally and on production server:

Error: Failed to lookup view "index" in views directory "/browser"

EDIT2:

I have managed to make this work by moving browser folder into ~/dist/browser. But I don't want the app to work this way.

Looks like the failing code is in server.ts:

// All regular routes use the Universal engine
app.get('*', (req, res) => {
  res.render('index', { req });
});

When ran locally, the const DIST_FOLDER = join(process.cwd(), 'dist'); returns correct output. However when ran on the real server (Ubuntu, Nginx) it gets: /home/<user_name>/dist/browser instead. Using __dirname didn't help.

So need some way to make sure res.render('index', { req }); gets the correct resource.

like image 809
0leg Avatar asked Sep 13 '18 09:09

0leg


1 Answers

Using the following piece of code

const DIST_FOLDER = join(process.cwd(), 'dist');
app.set('views', join(DIST_FOLDER, 'browser'));

means that the view engine will look for views in this directory: <currentWorkingDirectory>/dist/browser

The current working directory corresponds to the directory where the node process was started from.

So if you want your code to work the same way for local and prod environment (using nginx), you need to make sure that the directory where you start node from is always the parent directory of the dist/browser directory

So you should run node (or pm2) from /var/<project_name>/

like image 83
David Avatar answered Nov 11 '22 12:11

David