Module Federation: remote url with slug possible in webpack.config? - reactjs

I'm looking to use a component from a remote application in my host application using module federation. Is it possible to dynamically change the remote url in the webpack.config file to include slugs which can change during runtime?
Webpack config file
plugins: [
new ModuleFederationPlugin(
{
name: 'MFE2',
filename:
'remoteEntry.js',
remotes: {
MFE1:
'MFE1#http://localhost:8083/remoteEntry.js',
},
}
),
new HtmlWebpackPlugin({
template:
'./public/index.html',
}),
],
From the example above i'd like to change the remote url to extract the component from localhost:8083/[slug]/remoteEntry.js
Not sure if module federation supports including components that are created based on the slug in the url?
Any help is appreciated!!

In short, you can't do that currently, as webpack does its job at build time and urls are baked into the bundles.
Ticket about this feature
There is an open issue on their tracker about this
to make some sort of templating stuff resolved at runtime.
Workaround
There is an official example of using advanced api for dynamic module loading, you completely avoid using "remotes" in your webpack config, and do module loading in your code and compute URLs as you wish.
full example
simplified example

Related

how to merge FCM service worker with workboxWebpackPlugin default serviceworker

I am using FCM in my react app and now I am developing the same app as a PWA. So I added workboxWebpackPlugin to generate its default SW. I need to merge firebaseSW.js and serviceworker.js as they both are running on the same scope. Another challenge I'm having is that firebaseSW.js will be installed only when the user accepts the notification permission but the other service worker will be installed as the app starts running. I will appreciate any hint and guide.
Here is my workboxWebpackPlugin setup
new WorkboxWebpackPlugin.GenerateSW({
clientsClaim: true,
exclude: [/\.map$/, /asset-manifest\.json$/],
// importWorkboxFrom: "cdn",
navigateFallback: "/static-files/fallback.html",
navigateFallbackBlacklist: [
// Exclude URLs starting with /_, as they're likely an API call
new RegExp("^/_"),
// Exclude URLs containing a dot, as they're likely a resource in
// public/ and not a SPA route
new RegExp("/[^/]+\\.[^/]+$"),
],
importsDirectory: __dirname + "/../build/static-files",
swDest: "static-files/sw.js",
}),
and here is my FCM sw setup
importScripts("https://www.gstatic.com/firebasejs/7.2.3/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/7.2.3/firebase-messaging.js");
firebase.initializeApp(FIREBASE_CONFIG);
firebase.messaging();
The most straightforward approach would be to include that FCM code in a standalone JavaScript file, called fcm-sw.js or something like that, served from the same directory as your generated service worker, and then use the importScripts option in the GenerateSW plugin to include it:
new WorkboxWebpackPlugin.GenerateSW({
importScripts: ['fcm-sw.js'],
// ...other options...
}),

How can I modify the sitemap URL in Hugo?

By default, Hugo exposes its site map at /sitemap.xml; due to my proxy setup, I need to expose it at /static-content/sitemap.xml.
My initial approach was to utilize the capability to set the sitemap URL front mater; however, I cannot figure out how create a file in the content directory that will be picked up when rendering the sitemap.
You can configure the sitemap filename in your Hugo config file. I just tried the following in my config.yaml.
sitemap:
filename: static-content/sitemap.xml
And it worked! This is documented in https://gohugo.io/templates/sitemap-template/

users getting my previous bundle

I have a problem with my production website.
when users enter my website after building they getting a white screen.
I saw on the dev tools that the website trying to load the old bundle.js file and I don't understand why (the cashing is off)
This looks like a problem of a running service worker.
service worker is an API that cache your assets and other files so when a user is offline or having a slow network, he can still see your website.
React creates a service worker for you without your configuration by default, so this is the reason users enter your website and getting your previous bundle.
just put this in your app so next time user will enter your website, the service worker will be terminated.
import { unregister } from './registerServiceWorker';
// ....
unregister();
Service Workers, MDN
Service Workers, Google Web Fundamentals
Assuming you're using webpack to generate the builds and want caching (with service workers) to work as well, you can:
Add hashes to your generated bundles. Then, your webpack config may look like this:
{
output: {
path: path.resolve(__dirname, 'dist'),
filename: "[name].[chunkhash].js",
},
}
Read more about it here.
Do not cache your index.html which contains <script> imports of the updated hash-named bundles.
This will enable you to cache your builds easily, and only fetch new bundles whenever there is an update in the hash-names.

How to bundle Web App Manifest and favicons with webpack

Is there a way how to bundle Web App Manifest (manifest.json) and favicons with webpack?
I'm using React. Until now, I included all my favicons, including manifest.json, directly in index.html in public folder (so it didn't go through webpack). However, I needed to dynamically load favicons and so I decided to move the code and favicon images into React application and inject the tags dynamically. But I don't know how to deal with manifest.json because there are paths to favicons and the favicons when included in React app and bundled with webpack have random hashed names.
Any ideas?
You can try to add directly in your webpack configuration
plugins: [
// ...
new HtmlWebpackPlugin({
favicon: 'admin/src/favicon.ico',
inject: true, // Inject all files that are generated by webpack
)}
],

How to parameterize variables in a React Webpack app for different environments?

I'm working on a React web app which was created by create-react-app and I am getting ready to deploy it.
The issue is, for development, the app uses the api instance running on my dev environment (localhost:{api-port}) but for the deployed app this should point to the server api instance (api.myapp.com).
Currently the host is just a variable in my networking component:
const hostname = 'localhost:9876'
I plan on using webpack to generate the static files which will be served by the production front-end, and I would like to continue developing using npm start as set up by create-react-app.
What would be the correct way to set up my project such that the host can be set automatically to the correct value based on whether I'm running the dev server or building for production?
A common solution is to check against process.env.NODE_ENV like this:
const hostname = process.env.NODE_ENV === "development" ? "localhost:9876" : "localhost:6789";
You may need to force the environment variable to be present in your Webpack configuration file using the DefinePlugin like this:
plugins: [
new webpack.DefinePlugin({
"process.env": {
NODE_ENV:JSON.stringify(process.env.NODE_ENV || "development")
}
})
]
An alternative solution might be to use the config package and provide your hostname string as a configuration parameter. config will inherit configurations from files based on the current NODE_ENV. It will start by using configuration from a default.json file, then override it with a development.json, or production.json, depending on your environment.
Note that you'll need for the config files to be copied to your output directory using CopyWebpackPlugin for it to work.
There are definitely many ways you could achieve that. One of those solutions would be to use webpacks's DefinePlugin. In your plugins section in webpack configuration you would add something like this:
new webpack.DefinePlugin({
API_HOST: process.env.NODE_ENV === 'production'
? JSON.stringify('localhost:8080')
: JSON.stringify('api.com')
}),
That creates a global variable API_HOST available everywhere in your codebase, which you can use. You can read more about the DefinePlugin here https://webpack.js.org/plugins/define-plugin/
you could use a relative path when you make any request to your api server instead of calling the full url for your app.
and for your development you could add a proxy property to your package.json file:
{
...
"proxy": {
"/api/*": {
"target" :"http://localhost:9876"
}
}
}
so whenever you make any request that prefixed with /api will be redirected to http://localhost:9876/api this is just in the development but in the production if you make a request prefixed with /api it won't be redirected it will be served normally because the proxy is just available in the dev server coming with create-react-app.

Resources