How to load css files for ejs files (express app)

I’m currently doing a express app and trying to deploy to netlify with the help of serverless lambda-functions for the back end. I’m using ejs files instead of html files and i could render the ejs files but im having difficulty rendering the resources like css, js and images specify in the ejs files. (i’m not sure what path should i include). Here is my directory hierarchy.

Without the serverless approach, I originally just specify express.static(path.join(__dirname, ‘public’)) as express will find the css js images in the public directory. However, with netlify, it always does ‘http://localhost:9000/.netlify/functions/[name]’ and I’m not sure how to load my css, js and other media files.

The errors are as follows:
GET http://localhost:9000/.netlify/functions/css/style.css net::ERR_ABORTED 500 (Internal Server Error)
GET http://localhost:9000/.netlify/functions/css/swiper.css net::ERR_ABORTED 500 (Internal Server Error)
GET http://localhost:9000/public/resources/profile.png 500 (Internal Server Error).

These are the paths i specify in my index.ejs file

<link rel="stylesheet" href="css/style.css"></link>
<link rel="stylesheet" href="css/swiper.css"></link>
<link rel="stylesheet" href="https://unpkg.com/swiper/swiper-bundle.min.css"/>

<script src="https://unpkg.com/swiper/swiper-bundle.min.js" defer></script>
<script src="js/action.js" defer></script>

I’m only able to embed one media file apparently. Sorry if it’s not clear.
Thanks in advance

When you’re running everything locally via the express server it makes sense that the relative file paths work, since all the files are accessible.

When you are deploying to Netlify files are being sent to two different spots.
The static files are going to the CDN and the functions logic is being deployed to a serverless function.

There is an included_files configuration that can be used to deploy other files to the function, which you can see here (File-based configuration | Netlify Docs), but as you’re talking about the CSS & JS (which are ultimately loaded by the client - not the function), it wouldn’t make a lot of sense to serve them from the function (unless they were being generated dynamically by the function).

As per how you’re just pointing to the swiper-bundle.min.css at another url, one way you could solve for it would be to determine the Netlify URL of your project and then change all the relative references to point to that location so that the files are loaded from the CDN e.g.

<link rel="stylesheet" href="https://your-project-name.netlify.app/css/style.css"></link>
<link rel="stylesheet" href="https://your-project-name.netlify.app/css/swiper.css"></link>
<link rel="stylesheet" href="https://unpkg.com/swiper/swiper-bundle.min.css"/>

<script src="https://unpkg.com/swiper/swiper-bundle.min.js" defer></script>
<script src="https://your-project-name.netlify.app/js/action.js" defer></script>
1 Like

Hi nathan,
Thanks for the quick response. However, I didn’t quite get what path should i specify for my local server running on port 9000. Based on the directory hierarchy, would it be ‘http://localhost:9000/dist/public/css/style.css’ for example? I tried this but it didn’t work. I also tried doing

<link rel="stylesheet" href="/dist/public/css/style.css"></link>
<link rel="stylesheet" href="/dist/public/css/swiper.css"></link>
<link rel="stylesheet" href="https://unpkg.com/swiper/swiper-bundle.min.css"/>

but it didn’t work.

Thanks again.

I can only see what you’ve posted, but if you check lines 19 - 20 in the index.js screenshot you’ve posted, you’ll see that you’ve told your express server that your static path is dist/public, so it’s going to be trying to serve files from that location.

When you’re running locally, all the requests are going through express.
Since you’ve changed the reference to /dist/public/css/style.css, when it tries to load it, it’s going to look for the file at /dist/public/dist/public/css/style.css which doesn’t exist.

Getting it going locally is a combination of what you tell express your static paths are, and then what the paths are in the templates.

If the only reason you’re deploying a function is to try and run express to serve the site, that’s not a particularly good reason to use a function. I’d just create a build script that builds everything to static files and then deploy the static bundle.

*Edit, sorry I’d originally misread the path.join

1 Like

Thanks for the response.

the localserver is not from express by doing app.listen(), but it’s from the scripts inside package.json

"scripts": {
    "start": "./node_modules/.bin/netlify-lambda serve src",
    "build": "./node_modules/.bin/netlify-lambda build src"
  },

This is what i get when i get from ‘http://localhost:9000/.netlify/functions/index’.

The ejs files are rendered but based on what u said, if i run the server with express, then express will find the files inside /dist/public/, but since it is run by using the ‘./node_modules/.bin/netlify-lambda serve src’, I’m confused about the paths now.

Previously, I just tried to test it locally with app.listen(), but now I’m just trying to deploy my site by using lambda-functions which I didn’t even use it, and I’m quite confused now. You said about creating a build script to deploy my express app? How does that work?

If you’re serving via the function, but haven’t provided any indication of what the function is doing, then I can’t really advise.

What is the code within functions/index.js?
Are you able to provide access to a public repo so we can help debug?

Hi @PatrisiaPvP

I wonder if you have looked over the following Support Guide which points out that running app.listen() will not work on Netlify.

Functions are served from a single location, while static files (as @nathanmartin has already pointed out) are served from the global Netlify CDN, so having a single function rendering a site defeats the reasons for using Netlify in the first place.

Here is the repository: GitHub - Interesting2/Deploy-netlify-test

The index.js inside functions is actually automatically generated. So does that mean I couldn’t deploy what I originally written in express js?

Hi Coelmay,
Previously I only did app.listen() to test locally. I then searched how to deploy website to netlify and it shows the serverless approach so I removed the app.listen(). However, I’m actually quite confused how to deploy with lambda-functions because i already wrote the routes using the mvc architecture inside the source folder.

The netlify-lambda package is intended to be used for the creation of functions, not entire sites.

In particular netlify-lambda serve is deprecated and you should probably be using the netlify cli and netlify dev.

Based on the script you have for netlify-lambda serve src, which is running via an express server created by the netlify-lambda package, it’s likely it isn’t even serving any of your static files.

I downloaded the repository and get stuck as npm install fails on nodeJS v.16.13.1 (and node v14.18.2) due to an error with libpq likely related to Continues deployment of functions with postgresql - #29 by hrishikesh.

For my situation, I don’t think serverless lambda-function is the right way to deploy my website right? So is there any other approaches to keep all my files as it is, and deploy it ? I saw that I could deploy static files using netlify and express with heroku.

I also had that problem previously, and I solved it by installing postgres

For my situation, I don’t think serverless lambda-function is the right way to deploy my website right?

How you host your website depends on how you want to create it.

As you have it created currently, serverless functions wouldn’t be how you would host it.

Following a Jamstack methodology you only want to use serverless functions for the dynamic parts of a site that cannot be reasonably pre-rendered to static.

So is there any other approaches to keep all my files as it is, and deploy it ? I saw that I could deploy static files using netlify and express with heroku.

If you want to host your site “as is” running your own express server, then yes, Heroku would be an option.

Thanks for your time nathan!

Then I think I would attempt to use the netlify + heroku approach for now.

No worries.

The easiest way to get it going initially will be to deploy the entire package to Heroku.
It’ll mean you can immediately replicate what you have going locally.

To deploy to Netlify I’d refactor it so that it doesn’t try to use its own express server to serve content.

You have a build script that generates your static content, then you handle any dynamic functionality or custom API’s via serverless functions. The serverless functions don’t need you to run an express server, they’re already a request/response model. E.g. You actually can use them to “on the fly” build some content into an ejs template and send it back… you just wouldn’t run express.

1 Like