Uncaught ChunkLoadError: Loading chunk | Module Federation webpack 5 while loading CDN module - webpack-5

Implemented Module Federation for Host and Remote Application.
For the Remote application, federated module is uploaded on a CDN.
While accessing the federated module on localhost, Host application is working fine but while accessing the module using CDN link, getting an error. Error exists during Lazy Loading of the federated module:
Uncaught ChunkLoadError: Loading chunk 531 failed.
Below is my module federation configuration in webpack (Host app):
**new ModuleFederationPlugin({
name: 'common',
filename: 'common',
remotes: {
sampleAppModule: sampleApp#http://CDN-link/remoteEntry.js
// sampleAppModule: sampleApp#http://localhost:8000/remoteEntry.js (this works fine)
},
shared: [sharedDependencies],
})**
Able to see the federated module on CDN link by directly accessing it.
Also, successfully getting 200 status while fetching remoteEntry.js file but error comes when lazy loading the remote module.

This exception can arise when the public path of the remote module is misconfigured, so even if the app can access to the remoteEntry, then it fails to find other chunks because it tries to fetch them from a wrong location. Using code splitting you need to set a Dynamic Public Path on remotes. Webpack can automatically determine the public path when setting an Automatic publicPath. If that is the case, you just need to update the webpack configuration of your remotes like this.
webpack.config.js
module.exports = {
...
output: {
...
publicPath: 'auto',
},
};
If the error appears intermittently, another cause of this exception is misconfigured CDN cache. It's common to configure Webpack using output filenames depending on content hash in combination with long expiration time for cached content on CDN. This configuration optimizes performances because user browsers will cache static assets locally and use those files for subsequent requests.
When using Webpack Module Federation, the remoteEntry.js represents a stable entry point for the remote module. For this reason its name won't change on subsequent builds, even if its content changes. It is updated at every build because it contains a "map" of other files, whose names are dynamically generated with content hash. So, this file should never be cached, allowing the browser to download new files when a deploy occurs.
You can avoid to cache the remoteEntry.js by setting for it a Cache-Control header like Cache-Control: max-age=0 on the server. It's very important to set this header only on the remoteEntry.js file and not setting it as the server default, otherwise every file will be not cached.
Alternatively, if you can invalidate CDN cache for this file, you can set Cache-Control: max-age=0, s-maxage=<time> and invalidate the CDN cache for remoteEntry.js at every deploy. This header allows caching only on shared caches, like the CDN. That way your CDN can serve requests to remote entry, avoiding to request it to the server.

Related

AWS S3 / Cloudfront deployment - certain paths aren't updating on static website

I'm fairly new to AWS and web dev - I have a simple static website at https://iveyfintechclub.ca
I recently refactored the code and made some changes to the project organization. I basically wiped the S3 bucket and reuploaded all new files and folders.
On CloudFront, I have object caching set to use origin cache headers:
my CloudFront distribution behavior config
I also did an invalidation with /*.
On S3, I've set the metadata Cache-Control to max-age=0 for all files.
Two problems are still eluding me:
The old bucket had a blank index.html which redirected to a
nested HTML file. The new bucket has index.html as the landing page.
When I attempt to visit the root URL, I get a 404 error as it still
attempts to reach the old nested HTML path. This doesn't happen in incognito mode (browser cache issue).
2. On the new landing page, I have a script file which is getting a 404
error as its looking for the file on its old path. Inspecting the HTML shows that the new path is in the client. This is happening in incognito mode too. All other resources are loading properly with
new paths, just this one is failing.
I'm wondering if I just have to wait longer or if I'm still missing a configuration.

Purge client browser cache after deploying app to Heroku

My Flask application is hosted by Heroku and served on Nginx and uses Cloudflare as a CDN. There are times when I change static assets (images, CSS, JS, etc.) on the backend that get changed through deployment on Heroku. These changes will not change on the client's browser unless they manually purge their cache. The cache does expire on the client's browser every month as recommended, but I want the backend to manually tell client browsers to purge their cache for my website every time I deploy to Heroku and they load/reload my website after the fact. Is there a way to automize this process?
If you're using the same filenames it'll use a cached-copy so why not provide versioning on your static files using a filter? You don't have to change the filename at all. Although do read about the caveats in the link provided.
import os
from some_app import app
#app.template_filter('autoversion')
def autoversion_filter(filename):
# determining fullpath might be project specific
fullpath = os.path.join('some_app/', filename[1:])
try:
timestamp = str(os.path.getmtime(fullpath))
except OSError:
return filename
newfilename = "{0}?v={1}".format(filename, timestamp)
return newfilename
Via https://ana-balica.github.io/2014/02/01/autoversioning-static-assets-in-flask/
“Don’t include a query string in the URL for static resources.” It
says that most proxies will not cache static files with query
parameters. Consequently that will increase the bandwidth, since all
the resources will be downloaded on each request.
“To enable proxy caching for these resources, remove query strings
from references to static resources, and instead encode the parameters
into the file names themselves.” But this implies a slightly different
implementation :)

How to access the content of /apple-app-site-association in Ember.js?

I am following https://developer.apple.com/library/archive/documentation/General/Conceptual/AppSearch/UniversalLinks.html
How would I get Ember to serve this url https://www.some-url.com/app-app-site-association
Note, app-app-site-association is a file. Unfortunately, Apple chose not to append an extension to this file.
Ideally, accessing this url should render:
{
"applinks": {
"apps": [],
"details": [
{
"appID": "9F32916B95.foo.bar.baz",
"paths": ["*"]
}
]
}
}
The important think here to understand is that if you want to deliver a static file, may it be your /app-app-site-association or just an image on /something.jpg this has nothing to do with ember.
Ember runs in the browser. So the entire ember routing happens in the browser. Thats why you have to configure your webserver in a way that it serves the index.html file when he does not find a file.
So when you enter example.com/something this will trigger a HTTP GET example.com/something. Your webserver then should check if the file something exists, if yes it should respond with 200 OK and the content of that file.
If if does not find the file something it would normally respond with a 404 NOT FOUND. However when you use an SPA as ember you configure your webserver so it will never respond with 404 NOT FOUND but instead return 200 OK and the body of the index.html. (you can see an example configuration in the ember guides, but this will be different for different webservers)
This then will load your ember app (you've included the .js file in the index.html) and ember will check the current url and start the ember routing. This happens in the browser.
So if something wants to make an HTTP request and get the file app-app-site-association, it does probably not want to get your index.html and then run a browser to let ember do anything. It just wants the file directly from your webserver. So your webserver must directly respond with 200 OK and the content of that file. And it will probably do this as I mentioned above if that file just exists.
Now ember projects have a public folder. If you want to have some files alongside your ember application that should just be served by your webserver this is the right place. Whatever you put in it will just be copied to the dist folder. This means when you then deploy your dist folder you will also deploy the file.
However be careful about your webserver configuration. Because the file has no ending it will probably be served as text/plain. If you want it to be served as application/json you need to configure your webserver accordingly.

How do I set up a ServiceWorker on amazon S3?

I am trying to set up the service worker for a SPA I am making. Its hosted on AWS with S3.
Despite the file being in the correct place I still get the following errors
/service-worker.js:1 The script has an unsupported MIME type ('text/js').
https://djwdy6bk7t99o.cloudfront.net/service-worker.js
Failed to load resource: net::ERR_INSECURE_RESPONSE
The service worker specification requires that the response for the service worker JavaScript file used in the registration be served with a "JavaScript MIME type" (e.g., Content-Type: application/javascript) header.
That's what I'd expect the default to be for files served by S3 with a .js extension, but perhaps you've previously overridden the default settings? This answer has some details about changing that setting back.

Setting CORS for static files on ember-cli server

How do I set CORS on requests for fonts files (or any other static resource) on the built in ember-cli server?
This is the error message just for reference:
Font from origin 'http://some-domain:4200' has been blocked from loading by Cross-Origin Resource Sharing policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:61277' is therefore not allowed access.
Add the following to ENV in config/environment.js:
module.exports = function(environment) {
contentSecurityPolicyHeader: 'Content-Security-Policy',
contentSecurityPolicy: {
// ... other stuff here
'font-src': "'self' http://some-domain:4200",
},
}
I tried adding the CSP settings but it was unsuccessful for me. I still got CORS errors for font files being referenced from my Ember app's CSS. In another post I saw someone mention ember-cli-cors which I tried and seemed to solve the issue for me. It just adds CORS headers allowing requests from everywhere to all resources which is exactly what I needed to get all resources to load properly in my local dev environment serving the Ember app assets using ember-cli's built in ember serve command to another local development server running a Python app serving my index.html from Redis(ember-cli-deploy style).