1

I have simple html file, that includes css like this:

<link rel="stylesheet" href="./css/style.css" />

I uploaded this html file and css file too google cloud storage, and set permissions to public.

In my application, written in node js, I want to serve this html file when user access my root page.

In my application I have following code:

public async getPublicFile(opts: IGetFileOpts): Promise<File> {
    const bucket = this.storage.bucket(opts.bucket);

    return bucket.file(path.join(opts.type, opts.fileName));
}

@Get()
public async serveFile(@Res() response: Response) {
    const file = await this.storageService.getPublicFile({
        organization: organization,
        fileName: 'index.html',
        type: 'resources',
    });

   file.createReadStream().pipe(response);
}

This works as expected. It will server index.html from bucket. However, since this html file have relative link to css file, it will not load css file since it cannot find it.

How can I fix this, so that also css file will be served? Currently I am running this on local computer, but it will be deployed to Google Compute Engine.

I found this link for AppEngine https://cloud.google.com/appengine/docs/standard/go/serving-static-files

Here in AppEngine I can define some handlers like this:

handlers:
  - url: /favicon\.ico
    static_files: favicon.ico
    upload: favicon\.ico

  - url: /static
    static_dir: public

  - url: /.*
    secure: always
    redirect_http_response_code: 301
    script: auto

but as I understand this will not work on local machine.

Also, how do ecommerce companies solves this issues? For example, every shop can have different theme that can be customizable. So I understand that every tenant has own bucket and in tenant bucket, this customizable theme is saved correct? So how I assume that the should have similar issue like me. How do the cope with this situation and how do the handle it?

golobitch
  • 1,466
  • 3
  • 19
  • 38
  • 1
    Actually if you change the documentation link you shared for the Node.js examples, there is a whole section on how to serve files for local development, with a `.css` example using `express.static` to apply it, here is the [link](https://cloud.google.com/appengine/docs/standard/nodejs/serving-static-files#serving_files_for_local_development) for the specific section, so it's possible for both production and local development. Of course this is for AppEngine, not Compute Engine, but it's a possible alternative, would this suffice? – Ralemos Jan 14 '21 at 13:48
  • 1
    If your css directory is accessible over http or https you can add a new `` tag on the server-side while returning response to change the base url of the page. That way the html is served by the app engine and the static assets are pulled from the cloud storage. Read more about `base` tag [here](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base). – Prasanth Jan 19 '21 at 10:55

1 Answers1

2

You are currently trying to reach bucket static css file from an index.html served on your google app engine url. This just can't work out of the box.

There are many options to solve this:

  • Serve your index.html from the same bucket in public where are your other static files likes css. This has also the benefit of beeing served as CDN which is more efficient. (this is the way I recommand if possible, the only case you cannot do this might be when you want to compute serverside html things in the index.html file before sending it back to the client, but there are great chances this can be done client side)

  • Build absolute pathes to your css ressources in the index.html "on the fly" or "statically" so the link tag might look like :

<link rel="stylesheet" href="https://bucketurl.com/css/style.css" />
  • Serve all your content with your app programmatically with a special route that will serve static content by reading files from bucket like you do with your index.html. This should let you keep relative pathes for other static files.
utopman
  • 581
  • 4
  • 13
  • Can you please elaborate on the first point? So if I want to server some stuff from the database, I would need to serve index.html and then this index.html should call backend onPageLoad or something like that. Correct? – golobitch Jan 19 '21 at 19:49
  • Yes that's it, in this case you have to do some frontend http calls to some api (ajax requests) to interact with backend apps. Doing such queries can return whatever data you want, like json. in this case raw data come from API instead of html beeing generated from backend and sent back to the client. You will shortly want to use a frontend framework to handle common stuff like hydrating template from json backend data. I would recomand vue js, but react, angular ... will do the stuff. Doing this might lead you to build a SPA (Single Page Application) with all benefits and drawbacks it have. – utopman Jan 19 '21 at 20:23
  • You might also want to stick to minimal frontend code and load html chuncks from your backend if you go in this direction. but it is quite dirty in 2020 (it was ok in 2000' ^^). It also greatly depends on what is your "customer" target. Do you need rich frontend interaction ? does some raw html form are enough? Also note that diving in frontend apps is a quite an endless , exciting and rewarding topic (for me). Did I answered your questions ? – utopman Jan 19 '21 at 20:27
  • Yes you did, and I will accept your answer, except I have follow up question regarding this comment. I asked in my question how do ecommerce platforms solve this issue? For example...I have multi tenant application, and every tenant will have different webpage theme. How do the serve different webpage theme based on tenant? Also if this was ok in 2000 and not now, do you have any suggestion how to do this better in 2020? :) – golobitch Jan 19 '21 at 21:36
  • 1
    I am not sure to well undestand your question but, doing multi tenant app is more complex. It greatly depends on how you split your tenant. let say you have a tenant per subdomain : 1) it is harder to serve them all from static bucket, and I think you will want to handle this by putting a reverse proxy in front of your cdn to handle subdomains or something like this, but this is out of scope of this topic. You might also more simply have a login landing page that when a user logs in the tenant context is loaded and theme data will load accordingly eitheir on SPA or Server Side page rendering. – utopman Jan 19 '21 at 23:24
  • Your question if I understand it well is related to your global app architecture and it really depends on what is your business domain. You probably won't organize your app for end user the same way you will do it for experienced software engineer public (it is like comparing facebook and jsfiddle.net/). The required context to address such design may be very large and complex. I cannot state it all on a comment. So, if you have additional question out of the scope of this one, I advice you to post another question on the right forum with enough context to have an appropriate answer. – utopman Jan 19 '21 at 23:28