Cache misses for lazy loaded resources (using dynamic imports) - javascript

In a Vue.js project created with Vue CLI (internally using webpack), I implement code splitting and lazy loading with dynamic imports like so:
import(/* webpackChunkName: "my-feature" */ "./my-feature.js");
As a result I get the expected set of files:
dist/myApp.umd.min.js
dist/myApp.umd.min.vendors~my-feature.js (my-feature dependencies)
dist/myApp.umd.min.my-feature.js
The Vue application is built as a library and then used for an existing web site. What I do is include myApp.umd.min.js in <head> (common to all pages), and then in <body> request code I need for that page (for example myApp.umd.min.my-feature.js). Dependencies (myApp.umd.min.vendors~my-feature.js) are automatically requested by the earlier script.
Problem
When I navigate to a page, that uses the Vue app (and specifically my-feature), all 3 of the above files are loaded. That is expected for the first visit, but if I move to a different page and then return, only the first file (myApp.umd.min.js) is loaded from cache. The other ones are loaded from server every time I visit the page.
What approach to take for the lazy-loaded scripts to come from cache once already loaded? Thank you!

So far I have not found anything better than including all the scripts, I need on the page, in its <head> section. Moreover only using <script> tag helped; <link href="..." rel="preload" as="script"> was useless.

Use a version parameter for the script url.
There's a code snippet that showcase this:
<script type="text/javascript" src="myApp.umd.min.js?v=123"></script>
Also this is a valid solution:
<link rel="preload" href="myFont.woff2" as="font"
type="font/woff2" crossorigin="anonymous">
From docs:
A rel value of preload indicates that the browser should preload this resource with the as attribute indicating the specific class of content being fetched. The crossorigin attribute indicates whether the resource should be fetched with a CORS request.

Related

How to make prefetch link work with JavaScript file?

I'm trying to use prefetching (via a link with rel="prefetch") for a JavaScript resource in an html page. In Chrome, I see the prefetch request get kicked off with a "Type" of "javascript". If I subsequently try and fetch the same JavaScript resource by inserting a script tag into the page, I'd expect this to be fetched from the browser cache, rather than a new request being fired off to fetch the resource from the CDN. However, this is not the case. I see a new request being made with the "Type" of "script". I'm assuming that the issue is related to the mismatch in type between this request and the prefetch request.
Is there a way to force the prefetch request to use a type of script or some other way to avoid the JavaScript file being fetched again?
I've tried using an "as" attribute value of "script", but that seems to have no effect.
I'm aware that rel="preload" is an alternative option. This works, but the usual advice seems to be that preloading is only appropriate for resources you're about to use and prefetching is a better choice for resources you will use after navigating elsewhere in your web page. Chrome also warns if you use preload and don't use the resource within a few seconds.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<link rel="prefetch" href="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.8/angular-cookies.js" />
<script type="text/javascript">
setTimeout(function() {
const scriptElement = document.createElement("script");
scriptElement.src = "https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.8/angular-cookies.js";
document.head.appendChild(scriptElement);
}, 2000);
</script>
</head>
<body>
</body>
</html>
See above for example repro code. I'd expect the script tag inside the setTimeout to use the already fetched resource, but instead I see a new request being fired off.
I figured this one out, finally. You're likely seeing this happen because Disable Cache is on in Chrome dev tools: Disabling Chrome cache for website development
This doesn't just disable previously-cached assets – it also means that something like this would download an asset twice:
<script src="foo.js">
<script src="foo.js">
With that checkbox unchecked, you should successfully see your asset getting cached:
That all being said, it is very important to note that in my testing, Chrome is not smart enough to realize that a prefetch and a regular download for the same resource is happening at the same time – it won't attempt to cache one for the other. So if your prefetching takes longer than your setTimeout millisecond value, you will see duplicate downloads!
This is certainly because what you and I are doing here is in some ways an abuse of prefetching. It's supposed to be a way to download resources used for the next navigation. C'est la vie!
Is there a way to force the prefetch request to use a type of script or some other way to avoid the JavaScript file being fetched again?
I've tried using an "as" attribute value of "script", but that seems to have no effect.
Just as a final note, the type differences of script and javascript are to be expected. This is Dev Tools trying to tell you that one of the files is going to be executed and the other is merely getting downloaded.

How to use CSS and JS resources in a routed page in Odoo?

I’m using Odoo controller to create a web page and make it public to customer so he doesn’t need to login.
In this page I’m trying to use CSS and JS libraries which exists in files inside the module (static folder).
The problem is that the page can’t reach these resources because it searches for them in the domain of the URL not in the filesystem (ex. http://localhost:8069/mywebpage)
I tried to inherit the template and the qweb design and inject the files but I got the same problem.
<template inherit_id="..."> <xpath expr="." position="inside"> <link rel="stylesheet" href="...">
The only solution I have found is copy/paste the source code of the JS libraries and CSS inside the template which is not a practical solution.
How can I make the routed page access the CSS and JS resources inside Odoo module?
Just put the module path of your assets resources, like:
<link rel="stylesheet" href="/your_custom_module/static/src/css/file.css">
And be sure the file will be there, the same for js script definition.
Also you should include in your posts the exact info and value that you are using, not .... It doesn't help you into get a response using ..., it just makes things difficult.

Aurelia and Webpack, Common Chunks and SPA Config-Generate-Index-Html Setup

I have a common chunks question. I am currently using https://www.npmjs.com/package/html-webpack-plugin along with the common chunks but currently in my HTML without adding anything, app.css is loaded automatically. How can I prevent the autoloading of that resource? Also, my other bundle, about.css is also automatically being injected into the HTML. This happens before I even use an import or require statement.
I can restrict which chunks get loaded via
require('#easy-webpack/config-generate-index-html')
({minify: false, overrideOptions:{
chunks: ['app',
'aurelia-bootstrap',
'aurelia',
'common']
}}),
My goal is to be able to load only the page specific styles and the page specific JS and then when the user navigates to another page, dynamically import the required resources.
Without adding anything, app.css is loaded automatically. How can I prevent the autoloading of that resource? Also, my other bundle, about.css is also automatically being injected into the HTML. This happens before I even use an import or require statement.
For example:
<link href="common.css" rel="stylesheet">
<link href="about.css" rel="stylesheet">
<link href="app.css rel="stylesheet">

How to get the host protocol in import JSP

I am having two JSP files in my main application whereas one is MAIN.jsp and another one is CSS & JS import.jsp file.
MAIN.jsp is the main page of main application.The import.jsp file will import the CSS and JS of partner application in MAIN.jsp file which is used for support the few functionality with main application as partner.
But all the application (Main and Partner) are deployed in same server. So basically the host name of both the application will not change but context root alone will get change.
i have used jsp import tag to import the import.jsp in MAIN.jsp like mentioned below code.
MAIN.jsp
<html>
<head>
<c:import url="resourceImport/import.jsp">
</head>
<body>
</body>
</html>
import.jsp
<html>
<head>
<link url="http://hostName/DifferentContext/example.css" rel="stylesheet" type="test/css">
<script type="text/javascript" src="http://hostName/DifferentContext/sample.js" > </script>
</head>
<body>
</body>
</html>
Currently i have hard coded the partner HTTP URL in import.jsp for load all the resource in MAIN.jsp file. But moving forward we are planing to run the application in HTTP and HTTPS environment.
So how can i make it dynamic way of getting protocol in import.jsp file. I have tried following methods to get the protocol dynamically but its not working.
Method 1:
Removing Protocol and make it relative URL
<head>
<link url="//hostName/DifferentContext/example.css" rel="stylesheet" type="test/css">
<script type="text/javascript" src="//hostName/DifferentContext/sample.js" > </script>
</head>
Method 2
Removing Protocol and Host name and make it relative URL
<head>
<link url="//DifferentContext/example.css" rel="stylesheet" type="test/css">
<script type="text/javascript" src="//DifferentContext/sample.js" > </script>
</head>
So could you please anyone help me to get resolve this issue.
If there is anything that makes it worth to use https (and these days there is), I'd opt for less hassle and just go https everywhere.
No more worries, no accidental information leak and protocol change. Easier maintenance and no later update will inadvertently bring back a wrong protocol link.
Check HSTS as an option to force compliant browsers to not bother with any http connection attempt in the future.
That being said, relative links are another way to stay in the same protocol and probably beneficial: You rarely want to hard code domain names into your applications - Depending on the programming style that you're using in your app, you might want to use page-relative links (../DifferentContext/example.css) or server-relative (/DifferentContext/example.css). Protocol relative is fine as well, but hardcodes the domain name.
Yet another option is to make that location completely configurable. This way you can decide later (provided that you've changed all occurrences to the configured value): ${config.theOtherAppBaseUrl}/example.css. With this, you can try out all the different options yourself and within 10 minutes. And change your mind later, when you come to the conclusion that it's worth to go https everywhere.
(Note: You have an issue in your question's code: The last link refers to //DifferentContext...., which would assume that DifferentContext is a hostname - this is a protocol relative URL)

web application root operator and script tags

Is there any way to use ASP.NET's 'web application root' operator ~ in a script tag? If not, is there any way to mimic such behavior?
My application uses nested master pages for different sub directories; A content page uses its directory-specific master page, which uses the root master page. I'd like to be able to include my <script> tags in the root master page, so I'm not repeating code all over the place, but since I don't necessarily know the depth of the path for any given content page, I can't reliably provide paths to the scripts folder.
I considered using paths in the form /scripts/jquery.js, but since the Visual Studio development server starts the application in a subdirectory of the server root, this will not translate well to the live server. To illustrate:
<!-- dev server path -->
<script type="text/javascript" src="/my_project/scripts/jquery.js"></script>
<!-- live server path -->
<script type="text/javascript" src="/scripts/jquery.js"></script>
You can, of course see the issue. Since I am not the only developer on the project, I have very little control over what happens in the "go live" process; otherwise, it could just be a matter of removing /my_project in the "go live" process.
There are some possible cases on that.
1) For large project use the local iis5.1 or other local iis, and not the VS web that runs.
2) You can avoid the first spash and use relative paths... eg:
<script type="text/javascript" src="scripts/jquery.js"></script>
<script type="text/javascript" src="../scripts/jquery.js"></script>
so you do not force him to start from beggining.
3) You can place a literal control there and just render the script tag on Page_Load with the correct path every time
4) and you can just render the src on page
<script type="text/javascript" src="<%=ResolveUrl("~/scripts/jquery.js")%>" ></script>
I am using the 1 and 3.

Categories

Resources