I've started using workers for my sites. The purpose of workers on my sites: mostly inject some code(html/js/css) in different locations of HTML page. It can be some config data, or some legal text and etc.
So what I do now, is create a config in KV for each website and based on user country/language injecting above html/js and etc.
Below is a Store Class (Singleton pattern), that holds all the info from config, but doesn't work in workers, by doesn't work I mean, after first request, the data is persistent, and after some time it gets updated:
For example 1st request URL: /about
On Second request URL: /es/about/
By output console.log(event.request)
will show /es/about
, but Store.request
outputs: /about/
any workaround for this, to force refresh of data, I thought becuase i don't do it in constructor, but by calling custom method should do the trick but, it doesn't.?
Below is some code example.
import { Store } from "@helpers/store";
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
});
//HTML Rewriter Class
class Head {
element(el) {
el.append(`
<script id="config">
var config = ${Store.export()};
</script>`, {
html: true
});
}
}
async function handleRequest(request) {
let store = await Store.make(request);
const response = await fetch(request);
let html = new HTMLRewriter();
html.on("head", new Head());
return html.transform(response);
}
//src/helpers/store.js
class Store {
constructor(){
this._request = null
this._config = {}
this._url = null
}
async make(request){
let config = {}
this._request = request;
const domain = this.url.hostname.replace(/www\./g, "");
const country = request.headers.get('cf-ipcountry')
const website = await WEBSITES.get(domain, "json"); //WEBSITES is KV namespace
const { license, lang } = website;
this._config = {
country,
domain,
license,
lang
};
return this;
}
export(){
return JSON.stringify(this._config)
}
get request(){
return this._request;
}
get url(){
if(!this._url){
this._url = new URL(this.request.url)
}
return this._url;
}
}
export default new Store()
A single instance of your Worker may handle multiple requests, including concurrent requests. In your code, you are using a singleton instance of
Store
to store metadata about the current request. But if multiple requests are handled concurrently, then the second request will overwrite the content ofStore
before the first request completes. This may cause the first request to render its HTML using metadata from the second request.It seems like the use of a singleton pattern isn't what you want here. Based on the code, it looks like you really want to create a separate instance of
Store
for every request.