Inline the Web App Manifest? - html

I have a marketplace/web application with thousands of static single page apps.
Wish to add a Web App Manifest for each single page app in the <head> </head> tag of their corresponding stem_url (The {root}/index.html for all the urls of a given SPA).
The standard method:
<link rel="manifest" href="/manifest.json">
…does not seem like a good way to go forward because this would mean thousands of manifest.js files being dumped into the /public folder (it's a rails app!) and it would eventually make the app/assets compilation job very heavy as this number goes up.
Is there a way we could inline manifest json just like we do the style tags:
<style>
body { // style here }
…
</style>
An equivalent of manifest declaration:
<manifest>
{
"name": "HackerWeb",
"short_name": "HackerWeb",
…
}
</manifest>

You can inline the json by using a data:url. So instead of the standard
<link rel="manifest" href="/manifest.json">
it would be
<link rel="manifest" href='data:application/manifest+json,{ "name": "theName", "short_name": "shortName", "description": "theDescription"}' />
I wanted to inline it too and tried it just now. It works

Improved answer
As mentioned by RADXack, this works great
<link rel="manifest" href='data:application/manifest+json,{ "name": "theName", "short_name": "shortName", "description": "theDescription"}' />
But what if you want to add more attributes like the colors or start_url?
Then on your server you could add:
const manifest = JSON.stringify({
name: "React Doc",
short_name: "React"
start_url: "/",
background_color: "#fffff",
theme_color: "#ff00ff",
display: "standalone",
});
const HTML = `<!DOCTYPE html>
<html lang="en">
<head>
<link rel="manifest" href='data:application/manifest+json,${encodeURIComponent(manifest)}' />
...rest of your code`
encodeURIComponent will convert all special characters for you.
This way, you are sure that whatever the data being passed is, it'll be URL friendly

The main thing to remember is that the manifest request is still just a network request.
So you can Add Query Params
/manifest.json?title=Hello&icon=.....
Or you could do:
/manifest.json?appId=1234
OR you can just use a pretty URL:
/manifest/1234
Then on your server you can return the JSON that you want.

Related

ASP.NET Core - serve different HTML file for SPA?

Question
How can I serve different HTML (entry) files for an SPA application (Vue) in ASP.NET Core?
Explanation
Depending on a condition, I would like to serve a different HTML page (much like a controller would do for a non-SPA). The page would still include the entry point for Vue apps <div id="app">, but some other changes should be done before serving the HTML.
I know I somehow have to change the startup.cs file because that renders the HTML with app.UseStaticFiles() and app.UseSPAStaticFiles()
Example
Condition 1 is fulfilled, base.html is served from client -> public -> base.html
Condition 2 is fulfilled instead, special.html is served from client -> public -> special.html
Code
The basic HTML looks something like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>Title</title>
</head>
<body>
<noscript>
<strong>We're sorry but this webpage doesn't work properly without JavaScript enabled. Please enable it to
continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
The important parts of startup.cs looks like this:
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
// ....
app.UseStaticFiles();
app.UseSpaStaticFiles();
// ....
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
if (env.IsDevelopment())
{
endpoints.MapToVueCliProxy(
"{*path}",
new SpaOptions { SourcePath = "ClientApp" },
npmScript: "serve",
regex: "Compiled successfully");
}
// Add MapRazorPages if the app uses Razor Pages. Since Endpoint Routing includes support for many frameworks, adding Razor Pages is now opt -in.
endpoints.MapRazorPages();
});
// ....
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
});

How to create a preview (Image and description) to the Url when shared link on Social media,Gmail and Skype using React JS?

We are developing a web app using React JS.
We want to display an image and a description when shared on social media sites and Skype.
Right now when the URL link is shared, only the URL is getting displayed like this:
But we want to make it look like this in the Nat geo site:
.
What we have tried is :
index.html in /projectname/public/ folder
<head>
<meta charset="utf-8">
<meta name="keywords" content="Description goes here">
<meta name="author" content="title goes here">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="light">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
</head>
and in manifest.json we have:
{
"short_name": "ABC",
"name": "Title",
"icons": [
{
"src": "favicon.ico",
"sizes": "192x192",
"type": "image/png"
}
],
"start_url": "./index.html",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
How can we achieve this? Is it because of the port number appended to the URL?
It also doesn't seem to work with localhost URL.
Thank you
You need to set the Open Graph Meta tags:
https://ogp.me
React renders on the client per default. In some cases (for example when sharing links on facebook), they don't render your site to detect these meta tags.
In this case you need Server-Side-Rendering (e.g. use NextJS or https://prerender.io)
With React client side rendering, you should manage documents head with react-helmet.
import React from 'react';
import { Helmet } from 'react-helmet';
class Application extends React.Component {
render() {
return (
<div className="application">
<Helmet>
<meta charSet="utf-8" />
<title>My Title</title>
<link rel="canonical" href="mysite.com/example" />
</Helmet>
...
</div>
);
}
}
Other possible solution with SSG or SSR rendering check frameworks like Next.js and Gatsby.js

Proxy to multiple paths angular

I'm trying to proxy to a certain API endpoint that returns an html page but I get the error
Access to font at 'https://data.domain.com/v3/assets/fonts/glyphicons-halflings-regular.woff2' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
GET https://data.domain.com/v3/assets/fonts/glyphicons-halflings-regular.woff2 net::ERR_FAILED
Inside my angular app, I have three different targets that I am proxying to. The first two proxies work fine but the other is a bit weird.
My proxy.conf.json file looks sth like this...
{
"/API": {}, // First proxy works fine
"/info": {}, // Second proxy fine too
"/data": {
"target": "https://data.domain.com/v3/uk",
"secure": false,
"pathRewrite": {
"^/data": ""
},
"changeOrigin": true,
"logLevel": "debug"
}
}
So inside my data service, I define a variable data that contains the path '/data' and I pass that as the path in my POST request like so...
private data = '/data';
public fetchData(data: Data) {
return this.http.post(this.data, data, {responseType: 'text');
}
Upon making that post request, I'm expecting the returned value to be some html code that I'd like to bind to my template. Herein lies the problem. You see, the returned HTML looks something like this...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>My Page</title>
<!-- Bootstrap -->
<link href='https://fonts.googleapis.com/css?family=Ubuntu:300' rel='stylesheet' type='text/css'>
<link href="https://data.domain.com/v3/assets/css/bootstrap.min.css" rel="stylesheet">
<link href="https://data.domain.com/v3/assets/css/loading-bar.min.css" rel="stylesheet">
<link href="https://data.domain/v3/assets/css/custom.css" rel="stylesheet">
</head>
<body
<p class="title">Page Title</p>
</body>
</html>
See that bootstrap import? I think that's what's causing the problem because inside the bootstrap.min.css code, references to the glyphicons-halflings-regular font are made like so...
url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype')
Hence for each of those font formats, I get the exact same error repeated.
How can I solve this?

Next.js PWA (Service Worker + Manifest.json)

I am using Next.js to develop a Server Side Rendering website and I want to make it a Progressive Web App but the problem I couldn't find the way to make it happen correctly.
When I build the application it serves correctly the service worker but there is no manifest.json and in some projects examples it serves the manifest.json but I tried it in Lighthouse audit and it says
Service worker does not successfully serve the manifest's start_url
One of the examples I used
Create Next App With Service Worker Precache
I think that the problem is that the start_url is . or / and not a valid file because in Next.js there is no index.html to serve from the start.
In summary
I am looking for an example using Next.js to build it to a dist folder and when I serve it it has a valid Service Worker and a valid Web Manifest.
A. Some file are expected to be found at "/"
You have this error because browsers expect some files to be served from the root of the server, including:
/manifest.json
/sitemap.xml
/favicon.ico
/robots.txt
/browserconfig.xml
/site.webmanifest
While the majority of these paths can be set with meta tags, older browsers just ignore them and error if these exact file names are not served.
B. Configure alternative paths and use NextJS static file
At the time of writing, there is ongoing work for supporting offline in NextJS. But it's not ready yet.
If you don't need to support older browsers and you don't want advanced SEO, you can use NextJS's Head component (see documentation) to define the manifest.json path like you would for any NextJS static file:
import Head from "next/head"
export default () => (
<Head>
<link rel="manifest" href="/static/manifest.json" />
<link rel="manifest" href="/static/site.webmanifest" />
<link rel="shortcut icon" href="/static/favicon.ico"
</Head>
)
Please note that robots.txt cannot be serve from a subdirectory (source), so this solution is not a good fit if you need to define this file.
C. Serve these files like expected
The proper solution would be to serve these files from your express server like so
const { createServer } = require('http')
const { parse } = require('url')
const next = require('next')
const { join } = require('path')
const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare()
.then(() => {
createServer((req, res) => {
const parsedUrl = parse(req.url, true)
const rootStaticFiles = [
'/manifest.json',
'/sitemap.xml',
'/favicon.ico',
'/robots.txt',
'/browserconfig.xml',
'/site.webmanifest',
]
if (rootStaticFiles.indexOf(parsedUrl.pathname) > -1) {
const path = join(__dirname, 'static', parsedUrl.pathname)
app.serveStatic(req, res, path)
} else {
handle(req, res, parsedUrl)
}
})
.listen(port, (err) => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
})
Note: This code directly comes from the NextJS examples repository
here are the steps to make your next.js progressive. check the example
npm i next-pwa
next.config.json
const withPWA = require("next-pwa");
module.exports = withPWA({
pwa: {
dest: "public",
},
...
});
add manifest.json and icons to public folder from the example. However, icons directory is missing "maskable_icon.png". So create a maskable icon from here then add this to "manifest.json".
{
"src": "path/to/maskable_icon.png",
"sizes": "196x196",
"type": "image/png",
"purpose": "any maskable"
}
add those tags to import Head from "next/head". Head is used for better SEO setting. check the documentation*
<meta charSet="utf-8" />
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"
/>
<meta name="description" content="Description" />
<meta name="keywords" content="Keywords" />
<title>Next.js PWA Example</title>
<link rel="manifest" href="/manifest.json" />
<link
href="/icons/favicon-16x16.png"
rel="icon"
type="image/png"
sizes="16x16"
/>
<link
href="/icons/favicon-32x32.png"
rel="icon"
type="image/png"
sizes="32x32"
/>
<link rel="apple-touch-icon" href="/apple-icon.png"></link>
<meta name="theme-color" content="#317EFB" />
</Head>
lastly check if it is working. add Lighhouse extension to chrome dev tools from chrome app store and run start the performance.

React firebase error after build and deploy SyntaxError: expected expression, got '<'

i'm trying to deploy my react app through firebase but after deploying i get a blank page and the SyntaxError: expected expression, got '<'. i think this is because it's reading the < from html but i'm not sure how to solve this. below is the index.html form my build folder which is initialized as the source for firebase
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<link href="../src/App.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Merriweather:900" rel="stylesheet">
<link rel="manifest" href="/CV/manifest.json">
<link rel="shortcut icon" href="/CV/favicon.ico">
<title>Lorenzo Wijtman</title>
<link href="/CV/static/css/main.1b15713e.css" rel="stylesheet">
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script type="text/javascript" src="/CV/static/js/main.1b785adb.js"></script>
</body>
</html>
my firebase.json content below
{
"hosting": {
"public": "build",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
}
Your HTML contains this script include:
<script type="text/javascript" src="/CV/static/js/main.30b4dcd1.js"></script>
If you try to load this URL, you will see that you're getting back your original HTML, instead of a JavaScript file. Since you told the browser to expect JavaScript, it is complaining about the angular brackets.
It looks like you're not deploying a /CV/static/js/main.30b4dcd1.js. Since you're telling Firebase Hosting to rewrite everything to /index.html, that's what it does when there is no matching file for a URL.