This seems like a really simple thing to do, yet I am having trouble finding the right architecture to do this.
Here's the scenario:
We have an API route api/templates that should, in theory, happen in every single route/page of the App. It fetches all the different templates and all the data in the app belongs to one of those templates. These are dynamic and can change over time, so they are not an 'importable JSON'
Every page should get these assets on load, but...
once it's loaded, and you start navigating through pages, the app should NOT re-fetch them on every single page navigation
We will implement a socket notification to alert an already-loaded client when templates change in the database
The problem is that, since this is needed on every page, SSR still needs to be able to access this on every page and our SEO policy requires server side rendering to send these pages fully rendered to client.
So, what we are looking for is:
to have a somewhat 'conditional' getServerSideProps that, if it is a full reload, it fetches that, but, if it is already in the client's memory, it skips that
we have looked into SWR, which, in theory, would work, but it still makes the API call as an after-thought, helping on the client side, but defeating the objective of not actually making the call, so that the backend is not 'burdened' with an unnecessary call
Honestly, this looks like a very 'common' pattern, yet I have completely failed to achieve a proper solution within the NextJS app environment. Maybe it's an "anti-pattern" and we shouldn't be doing this?
Related
Have PHP/mySQL/JS-JQuery based web site that records finish times for racers, then sends the time back to the server. The server inserts the finish time in the db, Calculates the finish place based on a handicapping formula. Stores that and send the finish place back to the web page and it is updated on the screen.
It uses Jquery Ajax calls so the page doesn't get reloaded at all.
Everything works fine if the data connection is good.
If the data connection is bad my first version of this page would put a message up that the connection was bad.
Now I am trying to make it a bit smarter, so I have started with the HTML5 feature that tells the browser if it is on or offline(i realize this may not be the best way yet but it works for concept testing)
When a new finish time is recorded(or updated) and we are offline the JS just adds a class of notSent to the tag of the finish time. The finish place and all of the finish places would normally come from the sever are greyed out indicating the data is no longer valid(until it can communicate with the server).
When the browser finds itself back online, A simple jQuery each loop on each notSent class starts re-sending the AJAX requests and if they all get completed it processes the return finish place information and display it as up to date.
It also disables all external links on the page when the browser is offline. This keeps the user from losing the data entry page by accident by clicking a link that will give them a page not found button.
So my last issue, is the browsers reload and close buttons, if the user click these when it is offline they will lose the data entry screen and are out of luck until the connection comes back.
Can I disable these functions as well? A quick Stack-overflow search of this indicates it can be done but most answers give the old, "you really shouldn't and if you think you need to you should rethink your design." warning.
So rethinking my design I start learning about;
HTML 5 local storage (decide I don't need it, since my data is stored already in a input box)
App-cache Manifest for controlling the cache of the page so if reloaded in the browser off line if would get that cached version. After much reading came to the conclusion that this could work on a static page but not mine where the data is updated all the time. Then found that most browsers are deprecating this anyways.
Service Workers seems to be the possible future for contorlling offline caching, but not all browsers support it, it is pretty cumbersome to learn and still very new.
Now I am stuck, Leaning towards preventing browser reloads and defering learning service worker till more support and better examples for a dynamic content pages like mine.
Bottom line- am I missing something here? Is there a easy solution?
I think the best option is to use PouchDB to sync between the client and server and use Background Sync to awake a Service Worker when you regain connectivity. If Service Worker is not present in your browser, it can sync the next time your user open the browser.
You have a similar example of deferred requests explained in the Service Worker Cookbook,
I am building a Drupal 8 site and am new to the twig templating engine. For one specific content type I would like to make a call to an external restful api and render some of the returned data as fields in the twig template.
I have an internal id to call out to the API and I would like to embed in the template:
The api call
set a number of variables from the call
render the result (with some logic if it does not exist)
Is this something that is easy to do with twig and drupal 8?
As a secondary question, is this secure?
The alternative at this stage is to write small Drupal 8 module but as there is no user input on the page, just rendering from the returned api call, I thought it would be easier to have it all in one place.
In Drupal 7 it was possible, but a poor design, to put arbitrary PHP into the template. In Drupal 8 it was made hard to do intentionally. You should not attempt to execute arbitrary PHP in your Twig files or make remote API calls that late in the processing of a request.
You should call the API and gather the data before you reach twig. You should create a custom module that handles that API interaction and places the response in a field, block, or another structure for rendering in the appropriate context (often a custom block works well for things like this, but exactly which approach makes the most sense depends on your project). You should also keep in mind that any page requiring a remote API call is likely to be slow unless that API call is very simple and very very fast. The BigPipe module can help you address those kinds of speed issues, but involve an additional learning curve.
If you want the browser to handle the API call, you will want to create a div (or similar markup) to place the results, and attach the JavaScript to the structure and make the actual API call after most of the page load is complete.
As for security: it is as secure as you make it. Drupal will provide some help to avoid the most common security mistakes, but you can still do things that would make it insecure (like sharing data with an untrusted third party or assuming the response data is always safe).
I have a Meteor game of heads or tails that keeps the stats of a user in their profile. The stats eg. wins and loses are changed using Meteor methods like incrementWins and incrementLoses.
Is there a way to prevent the users from calling these methods on the console?
I didn't find any precise answer to the question so I'll add one.
Is there a way to prevent the users from calling these methods on the console?
The short answer is no.
As long as you have the Meteor variable available on the client, it's not possible to restrict a user to use if from browser console. Meteor allows the client side to use Meteor.call function in any conditions, therefore even if you restrict its usage somehow, it will affect your whole application, not just browser console.
You can, however, make your methods more secure. As you know, you can make your code run either on client side, server side, or both. If you put your methods on the server side, the client side will never know what exactly happens as the methods are executed, nor would it be able to influence it or intercept control anyhow.
On the other hand, if you put your methods in the lib/ or both/ folder (or simply root folder of your app), the methods will run both on client and on server. Insecure part of the code (like bulk removing collection items or manipulating Meteor.users collection) won't be executed on the client side. But you may want to put something that would change UI state or show any messages, ironically, on the browser console. Think twice before applying this practice.
I personally think you exaggerate the meaning of ability to run something on the browser console. First, only a small group of users actually do that (but if they do, expect smallest holes in your app to be exploited). Second, Meteor is well secured in this part, it doesn't allow a user to run insecure code (unless insecure package is added, which is by default as you create a new app). And third, most of the time, as your methods get executed, the data will be updated reactively, this is what Meteor takes care of out of the box, so you don't need to worry about refreshing UI after app state change, etc.
Every newly created Meteor project has the insecure package added by default. This is the package that allows us to edit the database from the client. It's useful when prototyping, To remove this package, go to your app directory and run:
meteor remove insecure
I have to make a navigator menu for a web application (based these: java, tomcat, jsp, oracle db) that will be present in everything once the user is logged in. The point is that almost every person connected, has different privileges so each person would see a diferent navigator menu. This is one of my first web developments so I'm not very strong on the concepts of how things are communicated from the client to the server and vice-versa and therefore, what is the best to do, however some of my considerations have their pros and cons.
Making a filter to load the menu in every request. This would query the database which is painful to it because in few cases, things are going to change (or at least, not very often); however, when there is a change, it would load immediately.
Making an iframe to load the menu once and control the second iframe from this one (i think this is the most discouraged, but is still an option and has the advantage of not making the same request to the server everytime you click something). When there is a change, reloading would load the new data.
Making the menu to stay as an object in the session. This will query the db once the user logs in. Changes will be loaded in every connection (or by making a button to reload). But this approach would put things in the server memory which I think is one of the worse ideas. (not sure about what I say here, I'm I wrong?)
As I said, I'm too new to this so I don't know about anything else I can do. For what I know, I can't write a file to the client (xml for example) so it is the data source for the menu and delete it daily or so. I can write a file in the server with the data so I don't need to query from the db (but still this is a request to the server), but this brings other problems, changes of data would not be refreshed (unless of course, I make something to it which require more time and more things to mantain) and I don't know if this would be faster than just accessing the db.
How are this things best implemented? consider the cost of development, mantainance, performance (reducing requests of the same information on every click), user perceived lag and others that my maturity on this subject don't see yet. Any recommendations on books about web design?
Edit:
I'm planning to use jsTree for the visualization and making the menu sublevels to load on ajax requests.
I would forget about the second option and go with the simplest, stateless option: the first one. Databases are fast!
If it appears that this takes too much time or puts too much load on the database (but I doubt it: loading the provileges of a user should be very fast), you could always go with the third option. Sure it would store the menu (or just the privileges) in the session, but the session can also be written to the disk or the database if necessary.
Don't pre-optimize.
I have a module that supplies a block. The block is set to BLOCK_NO_CACHE, and its content is pulled from a function. It lets a site admin create a 'message' to display on the site, kind of like CNN, where a breaking update is displayed at the top, and a user can close it by hitting X. When they close it, the action is written and UUID written to their cookie so they don't see that message again.
I am getting reports from Boost users that when someone closes a message, it closes it for everyone. I assume this is because Boost is caching the page and serving a cached page after someone closed the message.
How can I make my module work for people using Boost?
I thought maybe hook_boot might work, but, then again I am not sure if there is a better way to address this.
hook_boot will not do it. Once that page is in the cache no PHP is run. You need to have that block be loaded via AJAX because the state of that block is dependent upon a cookie.
http://drupal.org/project/ajaxblocks and http://drupal.org/project/ajaxify_regions
are 2 projects that easily do this.
Also it would be hard to get breaking updates out if the page is cached. You will have similar issues for varnish users as well.