How can i save js, css in cache from Gatsby? - reactjs

i have some files from node_modules they need to be saved in cache because i am getting this information
enter image description here
to get this information i audited with lighthouse this is the web https://www.webpagetest.org/
this is the final result, "cache static content" is the wrong
enter image description here
i am working with Gatsby, i found this information about my problem https://www.gatsbyjs.com/docs/caching/#javascript-and-css but i am not sure how can i use it or should i use another library? i dont have idea how can i cache
i think i should use these properties:
The cache-control header should be cache-control: public, max-age=31536000, immutable
this is my file gatsby-config
plugins: [
'gatsby-plugin-top-layout',
{
resolve: 'gatsby-source-filesystem',
options: {
name: 'assets',
path: `${__dirname}/src/assets`,
},
},
`gatsby-plugin-image`,
'gatsby-transformer-sharp',
'gatsby-plugin-sharp',
{
resolve: 'gatsby-plugin-manifest',
options: {
},
},
{
resolve: `gatsby-plugin-offline`,
options: {
precachePages: ['/projects/'],
},
},
{
resolve: 'gatsby-plugin-material-ui',
my propuse to do this is solve this problem, there are a blank space when i reload the web application
blank space

Gatsby generates static content. It doesn't handle sending HTTP responses. That's going to be a web server (or in your case firebase).
Checkout the docs for sending headers on firebase
https://firebase.google.com/docs/hosting/full-config#headers
You'll need something like:
"hosting": {
"headers": [ {
"source": "**/*.#(eot|otf|ttf|ttc|woff|font.css)",
"headers": [ {
"key": "cache-control",
"value": "public, max-age=31536000, immutable"
} ]
} ]
}
This caches font files which is generally safe because fonts change very rarely.
You can add js and css to that list if you want as well. Keep in mind that you'll need to change the names of an js and css files or the browser will wait 1 year before reloading them.

Related

Next.js CORS blocking using Vercel

This is not only a question, also an answer to my problem which took me a lot to resolve, I believe some devs will find it useful.
Let's start with some basic info:
The client app is using NextJs.
The server app is using NestJs deployed using the Vercel service.
Everything works fine in localhost, but when deployed the requests are always blocked by the CORS.
The server app deployment config (vercel.json) is the following:
{
"version": 2,
"builds": [
{
"src": "src/main.ts",
"use": "#vercel/node"
}
],
"routes": [
{
"src": "/(.*)",
"dest": "src/main.ts",
"methods": [
"GET",
"POST",
"PUT",
"PATCH",
"DELETE"
]
}
]
}
In the server app, I enabled the CORS in the main.ts file:
app.enableCors({
allowedHeaders: '*',
origin: '*',
credentials: true,
});
Using any client I used (NextJs, Angular and even Insomnia and Postman) it shows that the CORS are set to accept any origin, still it's still blocking the requests.
The answer is not related to NextJs or NestJs but only to the vercel deployment config which needs to accept the OPTIONS type of HTTP request, the correct vercel.json file should look like this:
{
"version": 2,
"builds": [
{
"src": "src/main.ts",
"use": "#vercel/node"
}
],
"routes": [
{
"src": "/(.*)",
"dest": "src/main.ts",
"methods": [
"GET",
"POST",
"PUT",
"PATCH",
"OPTIONS",
"DELETE"
]
}
]
}
Unfortunately, I didn't find this info in any docs I looked in, it only came up since HTTP requests of type OPTIONS are being used in the CORS mechanism.
Besides applying the CORS config for vercel, described here, you will also need your vercel lambda function to return a 200 status code for request using the OPTIONS method.
Please also that your vercel config needs to allow any custom header that you may be using when querying the endpoint. Lets say your GET request includes a header X-UserSession, such header should be allowed by CORS config as:
{ "key": "Access-Control-Allow-Headers", "value": "X-UserSession" }

What best solution for prevent browser cache file in react

My problem is
when I deploy new version react web to production
some user browser display old version from previous deploy
My user have to press ctrl+f5 for clear cache browser then I think which bad solution
please suggest best solution for me thx bro.
This could be because your web server is setting a cache control response header, which is set to a large value. Could you check the value in devtools?
A simple explanation of what cache control does is it tells the browser that the browser can use the cached resource upto n minutes. So only after n minutes will the browser send a new request for the resource.
Since you have a react app (a web app), the browser requests for index.html, and it will subsequently fetch the js bundle for your react app.
When you push an updated version, the browser doesn't know that there is an update. Since the index.html was cached, it continues to use it. Until the cache time expires, and then it will fetch again and this time it will get the latest js bundle.
Based on your server, you will need to figure out how to set the cache-control header for index.html to be of value no-cache. Here is an example of how I set it up in firebase hosting,
{
"firestore": {
"rules": "firestore.rules",
"indexes": "firestore.indexes.json"
},
"functions": {
"predeploy": [
"npm --prefix \"$RESOURCE_DIR\" run lint",
"npm --prefix \"$RESOURCE_DIR\" run build"
]
},
"hosting": {
"public": "build",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
"headers": [
{
"source": "/service-worker.js",
"headers": [{ "key": "Cache-Control", "value": "no-cache" }]
},
{
"source": "/index.html",
"headers": [{ "key": "Cache-Control", "value": "no-cache" }]
},
{
"source": "/static/**/*",
"headers": [
{
"key": "Cache-Control",
"value": "max-age=31536000"
}
]
}
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
}
Since create react app automatically configures the webpack build to generate static files with different hashes in the filename, it is fine to set a large cache value for it.
That occurs because, by default, the service workers do cache, so you should check your react project index.js file and check to see if services workers are registered. serviceWorker.register().
If it is registered then Unregister the service worker serviceWorker.unregister().
The above being quite drastic as a method, since it could affect your user experience what is recommended is that you configure your PWA to suit your particular caching needs. Follow this resource "https://developers.google.com/web/ilt/pwa/caching-files-with-service-worker" for more about playing with service workers.
In case you need caching for your application, your backend sends appropriate response headers.

Images breaking between localhost and Netlify using NetlifyCMS

OK, I'm pretty new to JAMstack, React, GatsbyJS, NetlifyCMS and Netlify, so do forgive me if this is simple.
I have a site running using React and GatsbyJS, and have NetlifyCMS running too to control the content. For the most part the site is running fine, however I keep running into an issue when it comes to images between the different environments.
When I add an image into the body section of any page through NetlifyCMS, I then pull the repo the image simply doesn't appear and is replaced with the broken image icon. However, it seems to work fine when on Netlify.
Occasionally, it appears, but after a push or a pull or restarting the Gatsby develop server, it just breaks again.
It only seems to happen when adding an image via NetlifyCMS into the body content so it appears in the main content of the markdown file; it is seemingly working fine when in frontmatter.
I've spent many hours on this it seems. I've got the full range of plugins installed, and I can't seem to find anyone else that is facing this issue.
All the other HTML seems to work fine but these images really don't want to.
gatsby-config.js
siteMetadata: {
title: 'Sheringham Shantymen',
description: 'The Shantymen travel widely throughout the UK and Ireland supporting Lifeboat Stations in their fundraising efforts and are always considering how they can help in others to raise funds by performing concerts.',
},
plugins: [
'gatsby-transformer-sharp',
'gatsby-plugin-sharp',
{
resolve: 'gatsby-transformer-remark',
options: {
plugins: [
"gatsby-remark-copy-linked-files",
"gatsby-plugin-netlify-cms-paths",
{
resolve: 'gatsby-remark-relative-images',
options: {
name: 'uploads',
},
},
{
resolve: 'gatsby-remark-images',
options: {
// It's important to specify the maxWidth (in pixels) of
// the content container as this plugin uses this as the
// base for generating different widths of each image.
maxWidth: 1600,
},
}
],
},
},
'gatsby-plugin-react-helmet',
'gatsby-plugin-sass',
{
// keep as first gatsby-source-filesystem plugin for gatsby image support
resolve: 'gatsby-source-filesystem',
options: {
path: `${__dirname}/static/img`,
name: 'uploads',
},
},
{
resolve: 'gatsby-source-filesystem',
options: {
path: `${__dirname}/src/img`,
name: 'images',
},
},
{
resolve: 'gatsby-source-filesystem',
options: {
path: `${__dirname}/src/pages`,
name: 'pages',
},
},
{
resolve: 'gatsby-source-filesystem',
options: {
path: `${__dirname}/src/gigs`,
name: 'gigs',
},
},
{
resolve: 'gatsby-source-filesystem',
options: {
path: `${__dirname}/src/discography`,
name: 'discography',
},
},
{
resolve: 'gatsby-plugin-web-font-loader',
options: {
google: {
families: ['Source Sans Pro', 'Source Serif Pro']
}
}
},
{
resolve: `gatsby-plugin-manifest`,
options: {
name: "Sheringham Shantymen",
short_name: "Shantymen",
start_url: "/",
background_color: "#172957",
theme_color: "#FAC43E",
// Enables "Add to Homescreen" prompt and disables browser UI (including back button)
// see https://developers.google.com/web/fundamentals/web-app-manifest/#display
display: "standalone",
icon: "src/img/logo-badge.png", // This path is relative to the root of the site.
},
},
{
resolve: 'gatsby-plugin-netlify-cms',
options: {
modulePath: `${__dirname}/src/cms/cms.js`,
},
},
{
resolve:'gatsby-plugin-purgecss', // purges all unused/unreferenced css rules
options: {
develop: true, // Activates purging in npm run develop
purgeOnly: ['/all.sass'], // applies purging only on the bulma css file
},
}, // must be after other CSS plugins
'gatsby-plugin-netlify', // make sure to keep it last in the array
],
}
Content.js component
import PropTypes from 'prop-types'
export const HTMLContent = ({ content, className }) => (
<div className={className} dangerouslySetInnerHTML={{ __html: content }} />
)
const Content = ({ content, className }) => (
<div className={className}>{content}</div>
)
Content.propTypes = {
content: PropTypes.node,
className: PropTypes.string,
}
HTMLContent.propTypes = Content.propTypes
export default Content
Called on the page template:
<PageContent className="content" content={content} />
I expect to add an image into the body of markdown, for Gatsby to process the image and output it as a processed/blur up loading image, and for this to work consistently across all servers (localhost and Netlify).
Instead, when it outputs initially (sometimes) it's a huge image, breaking out of containers, then following a server restart or similar the image simply breaks.
Turns out this was a small bug in the version of Netlify CMS I was running - I updated from 2.6.1 to 2.8.0 and this has fixed the issue (as of 2.7.0).

how to handle client side react routing in loopback.js

I am using react with loopback. I wanted to integrate react code in loopback.
if i do these 3 steps
1)middleware.json - put this
"files": {
"loopback#static": {
"params":"$!../client"
}
},`
2)root.js
router.get('/');
3)front end code
"build": "react-scripts build && cp -r build/* ../client/",
That didopen my react site on localhost:3000 .Now issue is when i do this
i cant access my loopback on :3000/explorer
So my first question is in this scenario, how to access explorer.
But then i rolled it back , because i wanted to use loopback explorer again.
So, i deleted all these added code and explorer came back
but when i added it again
Now, i dont see my react code
I can still see explorer at http://localhost:3000/explorer/
if i go to http://localhost:3000/apphome
i see 404 error
Right now, my middleware.json file for loopback is
{
"initial:before": {
"loopback#favicon": {}
},
"initial": {
"compression": {},
"cors": {
"params": {
"origin": true,
"credentials": true,
"maxAge": 86400
}
},
"helmet#xssFilter": {},
"helmet#frameguard": {
"params": [
"deny"
]
},
"helmet#hsts": {
"params": {
"maxAge": 0,
"includeSubdomains": true
}
},
"helmet#hidePoweredBy": {},
"helmet#ieNoOpen": {},
"helmet#noSniff": {},
"helmet#noCache": {
"enabled": false
}
},
"session": {},
"auth": {},
"parse": {
"body-parser#json": {},
"body-parser#urlencoded": {
"params": {
"extended": true
}
}
},
"routes": {
"loopback#rest": {
"paths": [
"${restApiRoot}"
]
}
},
"files": {
"loopback#static": {
"params":"$!../client"
}
},
"final": {
"loopback#urlNotFound": {},
"./LoopbackUrlNotFoundCatch.js": {}
},
"final:after": {
"strong-error-handler": {}
}
}
root.js file
'use strict';
//router.get('/', server.loopback.status());
module.exports = function(server) {
// Install a `/` route that returns server status
var router = server.loopback.Router();
router.get('/');
server.use(router);
};
-edit
I made some changes. Now, i have react components showing, I can also see data when i use api routes. But, explorer is still missing.
middleware.json
"files": {
"loopback#static": [
{
"name": "publicPath",
"paths": ["/"],
"params": "$!../client"
},
{
"name": "reactRouter",
"paths": ["*"],
"params": "$!../client/index.html",
"optional":true
}
]
},
I have also changed named of root.js to root_something.js . In documentation, its written, no need of root.js
First of all you Should be create react app in an other director like
Root ->
|-- client // emply
|-- clint_src // react app
and getting build react app and copy build files to client
now you should be remove server.loopback.status() in "server/boot/root.js" file
Example:
router.get('/', server.loopback.status());
To :
module.exports = function(server) {
// Install a `/` route that returns server status
var router = server.loopback.Router();
router.get('/');
server.use(router);
};
after that you need say to loopback middleware which file should be load in your path
go to middlware /server/middleware.json and replace blow code to "files": {}
"files": {
"loopback#static": [
{
"paths": ["/"],
"params": "$!../client"
},
{
"paths": ["*"],
"params": "$!../client"
}
]
},
on "paths": ["*"], all route will be open react file exeption the "/api" and "explorer" so you should be handle page notfound inside react app
Hope This was help full
Good Luck
I suspect React's default service worker intercepts and tries to cache /explorer. It skips urls prefixed with __ so this might fix the need to clear browser:
In component-config.json:
{ "loopback-component-explorer": {
"mountPath": "/__explorer" }}
Then access explorer at /__explorer.
As the instructions for adding a GUI to a loopback application state, you need to remove the root.js '/' route completely, by either renaming the root.js file to something without a .js extension, or deleting the file altogether.
$ rm root.js
### or, you can do this
$ mv root.js root.js.old
In the loopback 3 server configuration, the client folder has to be setup as a middleware route in middleware.json, like so:
"files": {
"loopback#static": {
"params": "$!../client"
}
},
Now, your client application is served from the /client folder, and by default the static files are served with Express -- so, it will look for index.html when you hit localhost:3000/

How To Use Grunt-Asset-Fingerprint To Refresh Cache

I am trying to get around an issue in my Angular website where when I add a page or make a change it does not show up to a user because of caching. Having done some reading I understand that what I want to do is to create a fingerprint.
I had a look around and it seemed like grunt-asset-fingerprint would do the trick. I have downloaded the package and tried to run it. However, I have two issues:
It only seems to copy one file into the assets mapping file (infact it was my bing authorisation file), I would have thought it would copy all of them?
I have no idea what to do next, do I need to add the fingerprint to the file names in order to avoid the caching problem? I could not find much documentation online.
Any help would be much appreciated! The relevant parts of my grunt config and the outputs of the assets.json file are below. Thanks!!
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
assetFingerprint: {
options: {
algorithm: 'md5',
},
dist: {
src: ["dist/**/*"],
dest: "dist/"
},
}
});
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-processhtml');
grunt.loadNpmTasks('grunt-contrib-imagemin');
grunt.loadNpmTasks('grunt-contrib-htmlmin');
grunt.loadNpmTasks('grunt-newer');
grunt.loadNpmTasks('grunt-asset-fingerprint');
};
assets.json
{
"dist/": "./dist-dec2ce4621028dc1bd5g081ea11d1aff"
}
I was able to successfully append the hash to my app.js file using this structure:
assetFingerprint: {
"options": {
"manifestPath": "dist/assets.json",
"findAndReplaceFiles": [
"index.html"
],
"keepOriginalFiles": false
},
"dist": {
"files": [
{
"expand": true,
"cwd": "dist",
"src": "app.js",
"dest": "dist"
}
]
}
}
This will also update the reference to app.js in my index.html file. You have to make sure the paths used in the files block align with your directory structure.
Refer grunt-rekai, this could solve file rename and have more options.
https://www.npmjs.com/package/grunt-rekai

Resources