Embed static files on the server

Roadmap Card

Description

Right now npx frontity build generates two types of assets, one for the server and the other for the client.

Server asset:

The server.js file generated by Webpack for the SSR server.

Users have two options:

  1. Start a Node server with npx frontity serve.
  2. Upload the file to a Serverless service.

Client asset:

The static files generated by Webpack for the client. Like JS files, images, and fonts. They are saved in the /static folder.

Users have two options:

  1. Start a Node serve with npx frontity serve and keep the /static folder where server.js can find it. If the server.js file receives a request for a URL that contains static (like https://domain.com/static/some-file.js) it will try to find that file in the /static folder next to it and serve it.
  2. Upload the /static folder to a server and configure the domain so the /static URLs(like https://domain.com/static/some-file.js) serve static files from that folder.

The problem

  1. Node server

If users run a Node server, then everything is fine. They can use their own server, choose a service like Heroku, use Docker…

  1. New Serverless hostings

With servers like Now, Netlify, Firebase… that support both static files and serverless functions, everything is fine too. Users just need to indicate the hosting that any request of the folder /static should return the static assets and any other should run the serverless function. This is usually easy because these hostings are prepared for this type of application.

  1. Serverless functions

Serverless services like AWS Lambdas, Google Functions or Azure Functions are cheaper than the “New serverless hostings” and it’s still easy to upload and run a serverless function, but configuring the rest of the things needed for a Frontity deploy require a deep knowledge of each platform. These are the steps:

  1. Upload serverless function.
  2. Upload static assets.
  3. Configure an external domain.
  4. Configure HTTPS for that domain.
  5. Configure routing so /static goes to static assets and the rest to the function.
  6. Add a CDN on top of the domain.

Configuring this is so complex that is the reason for the birth of what I call here the “New Serverless hostings”.

So using a service like AWS, Google Cloud or Azure is not something we can recommend to deploy Frontity in a decoupled manner.

The PHP Theme Bridge deploy

The requirements for the deployment of Frontity when users want to use the PHP Theme Bridge are lower because they don’t need a CDN or an external domain. They become:

  1. Upload serverless function.
  2. Upload static assets.
  3. Configure routing so /static goes to static assets and the rest to the function.

For the PHP Theme Bridge, it would be ideal to support services like AWS or Google Cloud because they are in the order of 10x cheaper than the other hostings.

But step 3 is still really complicated.

If we embed the static assets inside the server.js function, the only requirement for Frontity would be:

  1. Upload a serverless function.

Which is easy to do.

User Stories

As a PHP Theme Bridge user
I want to avoid having to deploy statics
so that I can use AWS Lambdas and Google Functions easily

Possible solution

I’ve done a proof of concept that successfully embeds plain files (js, txt) and images (png) in the server.js file and then serves it:

Hi @luisherranz, thanks for writing this up! I think you’ve described the problem-space and motivation really well. I was able to get the example repo up and running locally.

How could I try the technique in the example repo in a full Frontity site?

Ideally, that should be added to the framework, but let me see if I can hack something on top of Frontity’s server.

I have updated the repository and now it bundles the Frontity build folder:

I have added a header x-embedded to the assets to make sure they are served by the serverless function.

And I have added maxEntrypointSize and maxAssetSize in Webpack. Right now they are set to 5Mb and the bundle is 1.8Mb so everything is fine. Maybe we can use that to ensure that the final serverless file is not too big (people didn’t include huge images in the bundle).

If you have any problem let me know.

Nice, I’m able to run the commands and see it working locally. I can even load the function with Google Cloud’s local dev tool: https://github.com/GoogleCloudPlatform/functions-framework-nodejs

But when I upload to an actual GCP function I get the error: “Provided code is not a loadable module.”

@luisherranz have you tried uploading to GCP?

I figured it out, kind of. The errors I was getting were using the GCP zip uploader UI functionality. When I switched to the CLI, the upload worked.

Here’s a Pantheon multidev where the static js assets are no longer 404ing. https://pr-8-rogers-funny-words.pantheonsite.io/ https://github.com/stevector/rogers-funny-words/pull/8/files

Though I’m having trouble getting the woff2 files to load now. Do you know which loader they should use? I’ve tried adding them to the url-loader and a file-loader.

Awesome, great work :slight_smile:

I didn’t add support for other than JavaScript files and PNG images, but adding support for all the images and fonts won’t be difficult so I considered this enough for a proof of concept. If you are interested in going further with this let me know.

That sounds good. My team has also made progress on building GCP object storage into our example which could be a better route for many sites.

1 Like