what is the best way to pass data to fragments ?
yury-kozlov opened this issue · 13 comments
Hi, we are doing a poc with tailor and trying to initialize fragments with some input data.
Here's a simple example:
- user sends request to index.html?language=1
- we configure tailor to forward query-string parameters as http headers to all fragments
- each fragment receives language and saves it in window.STATE object
- when fragment's script is executed in the browser, the state is initialized, and html is rendered according to the language
The main problem here is that window.STATE can be overwritten by other fragments (although we can solve this by giving unique names)
Do you have any working alternatives besides this approach ?
Since the fragments are considered micro-services they should be stateless. I suggest having only one service that manages state. Which one it is will depend on what kind of application you are developing.
Regarding passing data to fragments the only way is through the headers as you have already implemented.
I suggest having only one service that manages state
If we have one service (=fragment) to manage the state, is it possible to make it loaded first in the browser ?
If you add the attribute "primary" to your fragment this will be the main fragment that determines of the page responds with a 200 or not. It won't necessarily be the first fragment but you can make sure that the rest of the front-end processing doesn't start until this fragment is done loading.
There are front-end hooks that you can use for this as well. https://github.com/zalando/tailor/blob/master/docs/hooks.md
I've successfully used these to wait for the state manager to finish processing and than start the rest of the dependent logic.
One more way to communicate between the fragments are the custom DOM events if you don't want to use the Tailor hooks.
I thought "primary" attribute is only for resolving status code and location of the original request.
I want to implement a common fragment with shared dependencies, including global state manager (for example Redux). The order of loading here is very important.
How can I use front-end hooks to make sure all fragments are executed after this common fragment is loaded and initialized ?
Do I need to implement some deferred logic in each fragment script that will depend on Pipe.onAfterInit event ?
As i want to do something similar. Can you tell me how is it possible to access the headers in the template?
As i want to do something similar. Can you tell me how is it possible to access the headers in the template?
Not completely understood your question. If it's node.js code, then simply call request.headers and make sure you pass them in filterRequestHeaders() function because Tailor blocks all headers except default ones: https://github.com/zalando/tailor/blob/master/lib/filter-headers.js.
Hello thank you for your reply. I want to access headers in my template file to conditional loading a script based on the headers value like
templates/layout.pug
if headers.myheader === 'true'
script(type="script" scr="3rd/party/absolut/url")
I'm not familiar with pug engine. Generally, if it runs as a middleware, you should have access to the current request and headers are part of request/response.
How would you access the request in a "plain" HTML Template?
If your template is generated on the fly, then I guess you are on the server and you should have access to the request (again, I'm not familiar with pug). If it's a static HTML, then you may use window global variables. Those vars you may initialize on server-side (inside a response returned from fragment), but due to the order of loading need to make sure fragment scripts are evaluated on client before those template scripts.
Thanks, that helped for general understanding!
There is another way to do this, If you are the one controlling tailor. You can use handleTag functionality to do something similar.
function handleTag (request, tag) {
const feature = request.headers && request.headers['feature'];
if (feature) {
return `<script src="" ></script>`
}
return ''
}
The feature can also be tuned using tags. Assuming if there is a custom element present on the template and that would help enable/disable a specific feature.