hplush / slowreader

Web app to combine feeds from social networks and RSS and to help read more meaningful and deep content
https://dev.slowreader.app
GNU Affero General Public License v3.0
161 stars 37 forks source link

Improvements for preview server configuration #154

Closed easing closed 7 months ago

easing commented 7 months ago

Changes


Generating Nginx locations from router definition can be flaky for complex routes, so I've slightly adapt you suggestion of how it can be done and decide to export router RegExps and use NJS for requests validation.

You wrote in #137:

In another hand, I do not want to always return app’s HTML. Server should return proper HTTP status 404 on unknown page request.

According to web design basics, it's a good practice to have non-default 404 page.

Nginx now returns index.html with 404 status if route is not supported by app and not-found.svelte template will be rendered. We can use static 404.html instead, but from my point of view handling not founds in app is easier for developers and gives smoother user experience.

Small note

At debugging I discovered that nanostores/router creates too wide RegExps for patterns like /feeds/add/:url? causing path /feeds/add-random-bug to be treated as 200 instead of 404, but it's mimics application behaviour (feed adding form will be shown at this path) and seems to be 'technically' correct.

Checklist

ai commented 7 months ago

We can use static 404.html instead

Yes, let’s create 404.html and 500.html with just 404 and 500 text (we will add content later)

At debugging I discovered that nanostores/router creates too wide RegExps for patterns like /feeds/add/:url? causing path /feeds/add-random-bug

Wow, it is a bug. Can you send PR to nanostores/router if it is easy to fix?

I've slightly adapt you suggestion of how it can be done and decide to export router RegExps and use NJS for requests validation.

Do we call JS on /assets/* requests?

It is not the best performance way, honestly. But I am not 100% against it since we may move this JS check to Node.js server later, when we will add sync server.

But what was a rational reason of not having simple :param, :param? convert? What is the complexity of that way, can you explain with example?

easing commented 7 months ago

Wow, it is a bug. Can you send PR to nanostores/router if it is easy to fix?

Surely, I'll try to fix it.

Do we call JS on /assets/* requests?

Nginx will try to serve static first and only when no file at requested path was found it will pass request to @js location. So JS will called only for missed assets. But we can define location /assets/ {...} and avoid JS check for /assets at all. Also caching for assets can be added this way. Should we do it in this PR?

location /assets {
  expires 1y;
  add_header Cache-Control public;
}

But what was a rational reason of not having simple :param, :param? convert? What is the complexity of that way, can you explain with example?

:param substitution should work with current route set, but nanostores/router allow us to define route with RegExp and callback (without path pattern). So I prefer not to go this way, because it limits us on how routes can be defined in application.

Also, when creating location RegExp with :param convertation, we should handle cases like | in path pattern and duplicate part of router logic, so our locations will be out of sync with real router regexes if something will change in nanostores/router.

I thinked about dumping regexes from router to Nginx config locations, but for /^\/path\/(.+)$/.source JS returns ^\\/path\\/(.+)$ string which will not work in Nginx as we want. Removing \\ or replacing it with single \ is not clear in JS and smells a little bad. And even it can do the job with current routes, there are no garantees that code will work in future when new patterns will be added.

So I choose a more strainforward way to just run checks in JavaScript against the real router rules.

PS: Not important in this case, but Nginx locations order matters and I argue to avoid Nginx locations generation if it's possible.

ai commented 7 months ago

Should we do it in this PR?

Nice idea. But also add ui/assets

ai commented 7 months ago

but nanostores/router allow us to define route with RegExp and callback (without path pattern)

We are not planning to use this feature, so it is OK

So I choose a more strainforward way to just run checks in JavaScript against the real router rules.

Sure, let’s keep JS way.

ai commented 7 months ago

Hm, preview server doesn’t work for some reason

https://preview-154---staging-3ryqvfpd5q-ew.a.run.app/welcome

easing commented 7 months ago

Hm, preview server doesn’t work for some reason

Looks like wrong (default or maybe old) version of Nginx config is used for preview: our custom 404.html is on server but standard error pages rendered instead of it. https://preview-154---staging-3ryqvfpd5q-ew.a.run.app/404.html

Can you check /etc/nginx/nginx.conf in running container? Does it include recent changes?

Or maybe there is a way for me to pull this preview-154 docker image for investigation?

ai commented 7 months ago

Looks like wrong (default or maybe old) version of Nginx config is used for preview

Yes, it is my mistake. We deploy from main branch by sending artifacts of web/dist/, but not Dockerfile and routes.

I will fix it separately (need to think about security).

In this case I am waiting for cache changes, and we are ready to merge.

Really smart way to deal with the case.

easing commented 7 months ago

Really smart way to deal with the case.

Glad to hear such comment to my first commit to open source. Thanks.

I've add caching for /assets and /ui/assets and also enable gzip with minimal compression level. Initial transfer reduced from 251Kb to 82Kb.

With max compression we can save additional 12Kb but CPU will be significantly loaded because responses are compressed on the fly. For max performance without CPU load we should create .gz versions of assets on build phase but maybe 12Kb doesn't worth it.

easing commented 7 months ago

I've update PR title and description to reflect all changes that has been done

ai commented 7 months ago

Thanks. Amazing work.