How can I use handlebars in Google Cloud Functions? - node.js

I have a node.js + espress + handlebars app that works fine on localhost. However, when I deploy it to Google Cloud Functions, my public directory, containing client-side javascript, css and jpg's etc., does not seem to be found or accessible.
When (in Chrome DevTools) I try to inspect the client code .js that is referenced in my handlebars main template, I get a message Your client does not have permission to get URL /ClientCode.js from this server.
What do I do wrong; anyone any ideas how to solve this?

Related

MIME type issues with Google Cloud App Engine

I'm hosting a NodeJS application on google cloud app engine. Utilizing Vite & Vue3 alongside Vite's native SSR. Currently, the application works fine with the google subdomain: <domain>.appspot.com. However, when I try using the domain I mapped to ie: domain.com, it shows this error:
Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.
Sometimes it seems to work randomly, however, most of the time it creates the mime type error. This occurs for both JavaScript & CSS files which are served as files with HTML content.
Similar Issue: Mismatched MIME type with Google App Engine
This is my first time posting here so please let me know if there's anything else I need to add.
Some Notes
I've noticed that the mime type issue only occurs for the index page (so domain.com/) and not for pages like domain.com/test.
Running the production server (building & serving) doesn't have any issues
Since I'm using Vue Router, I've noticed that first loading the page as domain.com/test and then moving over to domain.com works. So there's no mime issue when vue renders the index page.
I'm also using express.static to serve static files, and not use the App Engine handlers configuration. I've tried switching from express to serving static from app engine but that also didn't work that well.
Edit
After some investigation, seems like the files are not being found. I'm going to assume this is an issue with how Google Cloud is fetching the files. Will continue to update.
I seem to have solved it. It was an issue with Google Cloud's caching the "index" route.
res
.status(200)
.set({ "Content-Type": "text/html" })
.set({
etag: false,
lastModified: false,
})
.end(HTML);
^ I used that code when serving routes now so it'll ensure google cloud doesn't cache the page and try to fetch old css/js files.
Reference: Google App Engine, index.html cached after deploy in express/react app
I have also found that today my app stopped providing a correct Content-type header when downloading a PDF preview with use of express. So, with the simplest
return res.writeHead(200, {
'Content-Disposition': `inline;filename=filename.pdf`,
'Content-Type': 'application/pdf'
}).send();
I get text/html when request it regardless it is totally fine on the local debug machine and it actually worked yesterday. Probably, it is some update on the App Engine side?

How to use routes in Shopify app built using Shopify CLI , React and Shopify App Bridge

I have a problem with using routes in my application, it is a template built using Shopify CLI, React and Shopify App Bridge guided by this documentation here.
Every route I trigger does get sent to the _app.js file within my project as I can log most of the output in the console, but I can't get it to actually include paths of subpages in my apps like https://{apphost}/custompage will not navigate to custompage but an error handler and the custompage gets included in the query. The route and pathname fields of the props return
{
...
router: "_error",
pathname: "_error ",
...
}
instead of
{
...
router: "custompage",
pathname: "custompage",
...
}
I expected the above to be the result but it isn't. But the custompage url does however appear in the asPath field like this asPath: "/custompage?hmac={hmac}&host={host}&shop={shop}" pretend everything in {} has actual information.
The query field gets the fields it needs as it does on a working page. So the main issue is just routing.
With this in mind I have concluded that maybe I have issues on my side and triggering the server side routes handler, but I do not know where to start redirecting to exact pages instead of the index page that came with the boilerplate code. And I looked on their documentation but they skip most parts that are required to actually explain handling routing with their boiletplate codes. I do not want to edit major functions because I am worried they might stop the whole app from working but I need to be able to handle routes on the app without getting the An unexpected error has occurred. error when trying to route to subpages. Even extensions to whitelisted urls within my app trigger that error, so I think I need help with adding routing to the app or server.
Can anyone help me figure out what I am missing?
I am still new to Shopify but I can say that working with Shopify is a nightmare.
I am not sure if this is the final solution but for now this works: make sure that all the files you are trying to route to have the same naming as your path.
If you are routing to https://{appURL}/subpath then your JS file should be subpath.js . I currently can only get it to work if the file is in the same folder as my _app.js. If I move the file from ./subpath to /dir/subpath then I need to change the extension to https://{appURL}/dir/subpath in my Shopify app settings. It seems to operate relative to the _app.js file's location so keep that in mind.
If you used the Shopify CLI and shopify node create to create your app then this could help with your routing 400 headache.

Node.js (MERN) Serving static files and API's

Im currently building a simple app using the MERN stack to learn. What Ive done so far:
-User Registration and Login (API)
-TODO List (API and Frontend with static files)
Ok, Everything works good and as expected, except for one thing.
I attempt to use my API's for any request, but at the same time I want my whole app to work rendering in a web browser (TODO list). So, the process I've followed is:
-Start node instance
-npm run build (To build react project files)
I did a research on how to use React build in node project and I did the following:
app.use(express.static('myproject/build'));
app.get('/*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'myproject', 'index.html'));
});
Good! So when I go to http://localhost:4000, it renders my index file and it actually works with my Login API, but I have some API's that are only available for consuming data and not rendering UI.
So, my problem is that when running the app, if I go to: http://localhost:4000/api/users/getdata
I get an error saying: Error: ENOENT: no such file or directory pointing the index.html
Ok, if I uncomment the code I posted before, then of course my app is not rendering UI, but my routes from API's work normally.
I know this might be setup/configuration process, but Im trying my best to understand this. If somebody could assist me with this problem please.
The hierarchy im working goes as follows:
myproject (contains models, routes (API's), middlewares, index.js)
frontend (inside folder 'myproject') (build, src (Components))
I did what #MaxAlex suggested. Changed the code from:
app.get('/*')
to
app.get('/')

ExpressJS static file serve always serves the same file

I have a expressJs setup which looks like this:
// Imports...
const app: express.Application = express();
const port: number = 3001;
const listener = new StatementListenerAPI();
app.use('/listen', listener.getRouter());
app.use('/welcome', router);
if (fs.existsSync('./client')) {
// Running in prod environment with pre built client directory. Serve this.
app.use(express.static('./client'));
}
app.listen(port);
So I have some routers connected to the express app, and at the bottom I declare that the directory client should be served statically. This directory contains an index.html as well as lots of JS, CSS and PNG files. However, no matter which URL I try to access from the express server, it always shows the code of the index.html within the statically served directory. The references to the JS and CSS files used inside the index.html also just return the code of the index.html.
I am using ExpressJS 4.16.3
What am I doing wrong?
Edit: So technically it works if using __dirname + '/client' instead of ./client. What I am now getting is that, when making GET requests from e.g. Postman (therefore "hand-crafting" the HTTP requests), I am always getting the correct results. If I call the resources from within my web browser, it still always shows the website (resolves the index.html). However, now all resources like JS and CSS scripts are being resolved properly, so apperantly Chrome resolves those dependencies properly, I am just wondering why I am still getting the contents of index.html as result when requesting some of the assets or some of the express endpoints via Chrome. API calls via code are working fine, so its only why manual chrome requests show this weird behaviour, at this point I am only asking out of curiosity.
Answer to your original question:
The path supplied to express.static should be relative to the directory from where you launch your node process or an absolute path. To be safe construct an absolute path (ie from the current directory or file). For example:
app.use(express.static(__dirname + '/client'));
Regarding your followup question:
I assume this is because Chrome uses heavy caching and it thinks this folder should return the html file. You can try and reset all caches in Chrome, or just for the page.

Getting 503 status code when index.html tries to load css and scripts [nodejs + express]

I'm using static middleware to serve stylesheets and scripts
app.use(express.static(path.join(__dirname, 'public')));
Everything works on localhost, but once I deploy the app to openshift I get 503 code for each static file the page tries to load.
If I open another browser tab and directly past the URL of one of those files I actually get the file.
P.S.: I am using express-react-views as a view engine.
Basically, I'm using express-react-views as a view engine and it includes Babel.js which uses cache for transpilation optimization. The problem is that it tries to write the cache files in a directory that requires higher permission. To solve I disabled the cache.
process.env.BABEL_DISABLE_CACHE = 1;
I hope this can help other people having the same issue.

Resources