I have a component that calls a module with
< ?php
$modules = JModuleHelper::getModules('modulename');
foreach ($modules as $module) {
echo JModuleHelper::renderModule($module);
}
? >
This is called multiple times inside a foreach statement, however I noticed that if I put a rand() or microtime() inside the module it seems like it's only executed once and then copied over to the other calls (like a cache?). Why is that? I need unique ids inside that module. Is there a way to override this and force a different content for every module rendering?
It could depend on the cache or on the module's implementation.
At the global level, you can disable caching in the global configuration; or you can prevent cache from being used in the individual module's configuration.
You should set cache to "conservative", not progressive, as the latter could indeed mess up copies of the same module on a single page.
Finally, cache is implemented in the module code, so it is ultimately functioning on the assumption that all developers implement all cache strategies correctly; which is true for most extensions, but not all.
Related
I'm using React 17 with cra-template-pwa to create a PWA. One of my UI libraries has several hundred static image resources that all get preloaded in the PWA (and I don't use most of them). This causes a long delay in enabling the PWA, and even causes Lighthouse to crash. I'm looking at various approaches to fixing the problem, but for a quick fix just to run lighthouse, I'd like to just disable precaching. I haven't been able to find concrete info how to do this. Any advice?
The cleanest solution would entail using the exclude option in the workbox-webpack-plugin configuration, but that requires ejecting in create-react-app.
Something you can do without ejecting, though, is to explicitly filter out entries from the injected self.__WB_MANIFEST array before passing the value to precacheAndRoute().
Your service-worker.js could look something like:
import {precacheAndRoute} from 'workbox-precaching';
// self.__WB_MANIFEST will be replaced with an
// Array<{url: string, revision: string}> during the build process.
// This will filter out all manifest entries with URLs ending in .jpg
// Adjust the criteria as needed.
const filteredManifest = self.__WB_MANIFEST.filter((entry) => {
return !entry.url.endsWith('.jpg');
});
precacheAndRoute(filteredManifest);
The downsides of this approach is that your service-worker.js file will be a bit larger than necessary (since it will include inline {url, revision} entries that aren't needed), and that you'll end up triggering the service worker update flow more than strictly necessary, if the contents of one of your images changes. Those unnecessary service worker updates won't actually harm anything or change the behavior of your web app, though.
Background:
I'm building an SPA (Single Page Application) PWA (Progressive Web App) using Vue.js. I've a remote PostgreSQL database, serving the tables over HTTP with PostgREST. I've a working Workbox Service Worker and IndexedDB, which hold a local copy of the database tables. I've also registered some routes in my service-worker.js; everything is fine this far....
I'm letting Workbox cache GET calls that return tables from the REST service. For example:
https://www.example.com/api/customers will return a json object of the customers.
workbox.routing.registerRoute('https://www.example.com/api/customers', workbox.strategies.staleWhileRevalidate())
At this point, I need Workbox to do the stale-while-revalidate pattern, but to:
Not use a cache, but instead return the local version of this table, which I have stored in IndexedDB. (the cache part)
Make the REST call, and update the local version, if it has changed. (the network part)
I'm almost certain that there is no configurable option for this in this workbox strategy. So I would write the code for this, which should be fairly simple. The retrieval of the cache is simply to return the contents of the requested table from IndexedDB. For the update part, I'm thinking to add a data revision number to compare against. And thus decide if I need to update the local database.
Anyway, we're now zooming in on the actual question:
Question:
Is this actually a good way to use Workbox Routes/Caching, or am I now misusing the technology because I use IndexedDB as the cache?
and
How can I make my own version of the StaleWhileRevalidate strategy? I would be happy to understand how to simply make a copy of the existing Workbox version and be able to import it and use it in my Vue.js Service Worker. From there I can make my own necessary code changes.
To make this question a bit easier to answer, these are the underlying subquestions:
First of all, the StaleWhileRevalidate.ts (see link below) is a .ts (TypeScript?) file. Can (should) I simply import this as a module? I propably can. but then I get errors:
When I to import my custom CustomStaleWhileRevalidate.ts in my main.js, I get errors on all of the current import statements because (of course) the workbox-core/_private/ directory doesn't exist.
How to approach this?
This is the current implementation on Github:
https://github.com/GoogleChrome/workbox/blob/master/packages/workbox-strategies/src/StaleWhileRevalidate.ts
I don't think using the built-in StaleWhileRevalidate strategy is the right approach here. It might be possible to do what you're describing using StaleWhileRevalidate along with a number of custom plugin callbacks to override the default behavior... but honestly, you'd end up changing so much via plugins that starting from scratch would make more sense.
What I'd recommend that you do instead is to write a custom handlerCallback function that implements exactly the logic you want, and returns a Response.
// Your full logic goes here.
async function myCustomHandler({event, request}) {
event.waitUntil((() => {
const idbStuff = ...;
const networkResponse = await fetch(...);
// Some IDB operation go here.
return finalResponse;
})());
}
workbox.routing.registerRoute(
'https://www.example.com/api/customers',
myCustomHandler
);
You could do this without Workbox as well, but if you're using Workbox to handle some of your unrelated caching needs, it's probably easiest to also register this logic via a Workbox route.
We have an old Yii application along with new Symfony one.
The basic idea is simple - I need to check if there is a route matching in Symfony application then it is cool, if not then bootstrap Yii application and try to handle the request with it.
The main idea to not instantiate AppKernel (and do not load autoload.php - since there is two different autoload.php for each project) before I am sure there is route matching.
Can I do it somehow?
We've done this before with legacy applications.
There are two approaches you can take.
Wrap your old application inside a symfony project (recommended).
Unfortunately this will indeed load the symfony front-controller and kernel. No way around that. You need to make sure that symfony can't handle the request and to do that the kernel needs to be booted up.
Use sub-directories and apache virtual hosts to load one application vs the other as needed.
Given option 1,
You can either create your own front controller that loads either symfony or yii by reading routes (from static files if using yml or xml, or annotations which will be more complex) OR EventListener (RequestListener) that listens to the HttpKernelInterface::MASTER_REQUEST and ensures that a route can be returned.
Creating your own front controller is the only way that you can make it not load the symfony kernel, but it will require you to write something that understands the routes in both frameworks (or at least symfony's) and hands off the request appropriately.
Event listener example:
public function onkernelRequest(GetResponseEvent $event)
{
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return;
}
... Code to continue normally, or bootstrap yii and return a custom response... (Can include and ob_start, or make an http request, etc)
}
public function getSubscribedEvents()
{
return [
KernelEvents::REQUEST => ['onKernelRequest']
];
}
As you see, the kernel needs to be booted to ensure symfony can't serve the route. Unless creating your own front controller (as stated above).
A third approach would be to create a fallback controller, which would load up a specified URL if no route was found within symfony. Although this approach is generally used for legacy projects that lack a framework and use page scripts instead of proper routes, and definitely requires the use/help of output buffering.
The EventListener approach gives you the opportunity to create a proper Request to hand off to yii, and using what is returned to create a Response as proper symfony object (can also use ob or other options).
Thank you.
This is an alternative to vpassapera's solution -http://stovepipe.systems/post/migrating-your-project-to-symfony
I have a big ZF2 project using a lot of modules.
We need to find a way to automatically PREPEND an Optional custom route to every existing route in all modules, using code from only One module.
And it needs to work with the Url view helper.
In every module I have the default route which is basically :
/ModuleName[/:controller[/:action]]
But my new module (Company) needs to add a Company context to every route like so :
[/company/:company_id] /ModuleName[/:controller[/:action]]
As you may have understood, the /company/id part is Optional, and I need a default company_id.
I do not want to add this route in every module's config file.
I tried adding a route in the Company module's config file, but I quickly understood that we cannot define the MODULE parameter inside the route definition, since Zend2 uses namespaces instead.
Also, we will need to do the same thing for langs.
At the end, we will need something like this :
[/:lang][/company/:company_id]/ModuleName[/:controller[/:action]]
Without changing the current config files in any other existing module.
Anyone has The solution for this ?
thank you !
I have solved my problem, and will share it here if anyone needs it.
I will only explain the big idea without posting any line of code since it strongly depends on the way you built your project, and also, it is better to implement it your own way to understand it better, cause if you copy-paste it without trying to understand it WILL break your whole project.
That said, if you cannot understand this explanation, you cannot implement this anyways.
First of all, I have a BaseModule that every module class extends from, and this BaseModule implements the getConfig() method itself automatically and it is final so no module can override it.
If your project is not built like that it will NOT work and you can stop right here.
In this BaseModule I have a STATIC method called prependRouteSegment(), which basically adds key=>array to a PRIVATE STATIC array variable.
In my case, the key is the route and the array is the default params for this route.
Then, in the getConfig() method, after fetching the config file and before returning it as the config array, I can edit anything I want.
So basically I edit all the existing 'Segment' routes and concatenate my routes from the static variable and the original one, then I add my default params.
But there is one more thing that is very important, you need to actually set the custom routes from each Module BEFORE zend executes every module's getConfig() method.
To do so, first create a STATIC method initCustomRouting() that you can override in any module, then, say my first loaded module is Application, simply parse the list of modules in the __construct() method of your Application module and call this initCustomRouting() statically on each module.
Then, if a certain module needs to prepend a custom route to any existing route, you simply implement in this module the initCustomRouting() method and inside of it you call the prependRouteSegment() static method with your custom route and default params.
That's it !
Dont forget that you cannot use params in a Literal route, and you may not want to prepend something on a hostname route, so in my case I only add the routes to every 'Segment' routes, I simply compare the type when I loop through.
Hope this will help someone !
I am writing an application where there are a bunch of handlers.
I am trying to see if i should package these handlers within the same apache module or have a seperate module for each handler.
I agree this is a generic question and would depend on my app, but i would like to know the general considerations that i have to make and also the trade-offs in each of the approach.
It will be really good if somebody can tell me the advantages/disdvantages of both approaches.
You have not specified if all these handlers need to perform some interrelated tasks or are they going to work independently of each other.
I would go for keeping the related handlers in the same module, and rest of them in their own module. I believe it makes the configuration of the server easy (we can easily load/unload a module as required) and the code base remains well managed too.
For instance suppose we needed two handlers that share some data, then we could keep then in the same module:
static int my_early_hook(request_rec
*r) {
req_cfg *mycfg = apr_palloc(r->pool, sizeof(req_cfg));
ap_set_module_config(r->request_config,
&my_module, mycfg);
/* set module data */ }
static int my_later_hook(request_rec
*r) {
req_cfg *mycfg = ap_get_module_config(r->request_config,
&my_module);
/* access data */ }