How to bundle Web App Manifest and favicons with webpack - reactjs

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
)}
],

Related

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

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

.NET Core 2.X MVC, React, Typescript, Webpack Configuration

I am struggling to revamp my .NET Core application and not sure which way I need to proceed. This is an older website that was originally built using Asp.NET and Razor pages and now I am trying to speed it up and update the UI to conform to new libraries and methods (React, Angular etc.).
Since reprogramming the entire UI is not within the time allowed it seemed that React would be a good fit. So I created a new React application using
create-react-app client-app --scripts-version=react-scripts-ts
under an MVC area folder (each area will have to have its own app) and I can serve and build the client via Power Shell and everything works great.
The problem I have is moving the output directory of the generated scripts to the wwwroot folder. I need to be able to load the scripts from the wwwroot since I can't use SPA Services due to routing, filters and other issues with the existing project.
This is my first attempt using React so I figured it would be easy to change the output of the files but I can't seem to be able to figure out how.
I updated tsconfig.json to change the output directory using
"outDir": "../../../wwwroot/areas",
And this doesn't seem to do a thing, the only way I have been able to get any results is by ejecting the React project using npm run eject and I get a bunch of files including the webpack.config.prod.ts and webpack.config.dev.ts files. When I did this I noticed that the directory is coded in the wepack.config.ts.
After looking online for an answer I noticed that some articles recommend using the webpack-cli instead of npm and specifying a configuration file. But when I do this I get a variety of errors saying the config file is not in the root directory so I tried moving it into the ./src directory then I got another error that the entry module couldn't be found because it couldn't resolve the ./src directory but I can't find where it is referencing src from.
Most of the information I can find on this is either obsolete or plain doesn't work. Even the Typescript.org site is still referencing .NET Core 1.X.
I did find this ReactJS.NET but doesn't look like it is very current and the example they have wouldn't load, gave a ton of errors.
Is there an easy way to configure React for this website or am I forced to fall back on old libraries like AngularJS or KnockOut? Can React be set up to be served like this and compliment the UI allowing me to still use the Razor pages?
I was able to get this setup the way I needed to, including Webpack hot-module replacement.
In order to get control over the configuration that is needed I needed to eject the react-client-app by running:
`npm run eject`
This will create a few directories and files under your app root, these contain the webpack configurations for both production and debugging.
For my project I didn't want the static/ folders, in order to change the output of the files, there are several areas in the webpack.config that controls these for example:
webpack.config.js
output: {
...
filename: 'js/[name].js',
chunkFilename: 'js/[name].chunk.js',
...
},
....
// "url" loader works like "file" loader except that it embeds assets
// smaller than specified limit in bytes as data URLs to avoid requests.
// A missing `test` is equivalent to a match.
{
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/, /\.svg$/],
loader: require.resolve('url-loader'),
options: {
limit: 10000,
name: 'media/[name].[ext]',
},
},
...
For some reason, the default React TS template (create-react-app <name> --typescript) doesn't reference tsconfig.json. One of the Keys to get this going was to install tsconfig-paths-webpack-plugin. This uses the paths defined in the tsconfig.json to resolve alias's and paths, this enables you to include modules from custom paths instead of using relative paths like:
import <name> from 'core/common/<name>';
The next item of business was to add a homepage entry in the package.json:
{
"name": "<AppName>",
"homepage": "/<AreaName>",
"version": "0.1.0",
...
}
This will append the homepage value to the paths and point it to the right area. I was originally thinking that I had to manually build the client instead of using Javascript Services (Spa) but this is not the case. Using Spa for different areas really keeps things nice and neat, there is no reason to output to the wwwroot folder since SpaStaticFiles can be set to any root and path. The next step was to update the Startup.cs to add Javascript Services.
Startup.cs
public IServiceProvider ConfigureServices(IServiceCollection services)
{
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
// Adds the path to the React files
configuration.RootPath = "Areas/<AreaName>/ClientApp/build";
});
return services.ConfigureApplicationServices(Configuration);
}
application.UseSpaStaticFiles(new StaticFileOptions
{
// This is the key to getting things working, this is the path of the Area
RequestPath = "/<AreaName>",
});
application.UseSpa(spa =>
{
spa.Options.SourcePath = "Areas/<AreaName>/ClientApp";
if ( env.IsDevelopment() )
{
spa.UseReactDevelopmentServer(npmScript: "start");
}
});
The React app is now served from the Area. There is no need to copy files to the wwwroot since Javascript Servies takes care of this, just reference any files as they were in root, the homepage value will be prepended to the path.
Finally to load the application I initiated the application through a standard Controller/View and used the compiled index.html to grab the required imports to return.
View
#{
Layout = null;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="/<AreaName>/favicon.ico" />
<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no" />
<meta name="theme-color" content="#000000" />
<link rel="manifest" href="/<AreaName>/manifest.json" />
<title>React App</title>
<!-- Webpack Styles -->
<link href="/<AreaName>/css/vendors~main.chunk.css" rel="stylesheet">
<link href="/<AreaName>/css/main.css" rel="stylesheet">
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!-- Webpack Scripts -->
<script src="/<AreaName>/js/vendors~main.chunk.js"></script>
<script src="/<AreaName>/js/main.js"></script>
</body>
</html>
In order to get react-router-dom to function properly with MVC and its routes you need to use the HashRouter instead of BrowserRouter.
Note:
If you use npm run build before launching a development session the production built files will be used not the debug compiled files. This will cause some confusion as nothing will update. To get everything to update when a change is made just remove the ./build directory and launch again.
I hope I included everything if not just post a comment I and will add what I missed.

Issue generating Service worker with sw-precache in react

I have created a react app using create-react-app.
Then I decided I need to edit/update the service worker code as per my need.
I am trying to build the app now using sw-precache (as its supposed to help building the custom service worker and automatically refer to the hashed static files).
This is the config I am using in 'sw-precache-config.js' -
module.exports = {
staticFileGlobs: [
'build/static/css/**.css',
'build/static/js/**.js',
'index.html',
'/'
],
swFilePath: './build/serviceWorker.js',
templateFilePath: './service-worker.tmpl',
stripPrefix: 'build/',
handleFetch: false,
runtimeCaching: [{
urlPattern: /this\\.is\\.a\\.regex/,
handler: 'networkFirst'
}]
}
This is the build command in my package.json -
"build": "react-scripts build && sw-precache --config=sw-precache-config.js",
However, I am facing two issues after the build -
Even though I have mentioned in the config file that the service worker name should be 'serviceWorker.js', the build process is generating two service worker files -
serviceWorker.js and service-worker.js
In the generated serviceWorker.js (build by the build script), 'index.html' file is not being mentioned in the precache (so the service worker is not caching index.html as intended)-
var precacheConfig =
[["static/css/main.d35a7300.chunk.css","5cf96316c6919194ba6eb48522a076f0"],["static/js/1.6105a37c.chunk.js","ae3537cefdcf8ee5758c3af13aab4568"],["static/js/main.4857c4da.chunk.js","9d6cc8fb962129f3e8bc459c85d39297"],["static/js/runtime~main.229c360f.js","3b44b5daad3fcbefa8b355dfbc3d9630"]];
Please let me know if I can clarify anything else.
Replace index.html in staticFileGlobs with build/index.html
You are getting two service worker files because the name you are specifying: serviceWorker.js is different from the default name CRA goes with: service-worker.js
Change your swFilePath to service-worker.js and that should fix it.

Webpack Dev Server Issues

I am building a web application using Express + React.
I am dealing with a issue with WEbpack Dev Server.
My Webpack Dev Server builds the bundles just fine!
But, I have an issue with the way the files are served.
Usually , we name the root html file as index.html, but because of my Web application architecture , I cannot use index.html and have instead name it client.html.
This brings me to the problem that I am facing, the webpack dev server looks for the index.html when I go to localhost:8080, as I am using client.html the webpack dev serves asks me to select my file.
Webpack Static file select screen
So , is there a way to load client.html directly when I access localhost:8080(Webpack Dev Server).
Thanks in Advance!
In your webpack.config.js file you can add the configurations for the webpack dev server
devServer: {
historyApiFallback: {
rewrites : [
{from: /^\/$/, to: './client.html'}
]
}
}
This will redirect your default index.html to the client.html
For more details see the DevServer documentation

Hosting an angular 2 app on s3, unable to display local images

I'm hosting an angular 2 app on s3. I'm using redirect rules on the s3 bucket, as defined in the answer.
<RoutingRules>
<RoutingRule>
<Condition>
<HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
</Condition>
<Redirect>
<HostName>yourdomainname.com</HostName>
<ReplaceKeyPrefixWith>#!/</ReplaceKeyPrefixWith>
</Redirect>
</RoutingRule>
</RoutingRules>
My angular app is then using html5 routing to match the redirect rules:
In app.module.ts:
RouterModule.forRoot(appRoutes, { useHash: true })
This combination works well, with the exception of displaying an image in the assets folder of the website. This is in my navbar:
<img src="./assets/logo.png" id="group-ed-logo" />
I am using the angular-cli, which has the following in the angular-cli.json:
"assets": [
"assets",
"assets/logo.png",
"favicon.ico",
"logo.png"
],
Edit: I have added logo.png to the above and put the logo.png file at the root directory of the src file and then used:
<img src="logo.png" id="group-ed-logo" />
The logo then displays. It would be tidier to have the images in an assets folder. However, it may be that the angular-cli currently doesn't support assets in folders when using html 5 routing.
If the file is in the assets directory, then I am getting a 404 url not found: "http://www.myurl.com/#/assets/logo.png".
For folders, in the bucket 'Create a folder' then add your files to that bucket.
Also, if you drag and dropped the whole dist folder, you may be looking at the inside of the dist folder on the AWS UI, not realizing that you are in the dist folder. Copy only the contents of the dist folder, not the dist folder. -- This happened to me.

Resources