Next js Head doesn't access public folder? - reactjs

I'm using Head in a very straightforward way
import Head from "next/head";
const HeadTags = () => (
<>
<Head>
<link rel="stylesheet" type="text/css" href="/styles.css" />
<title>this works</title>
</Head>
</>
);
export default HeadTags;
The title does change, but the styles.css file is not having an effect therefore not imported from the public folder. Why doesn't it work?

Related

SSR Next.js <Head> tag is not rendering at the server side

import { getMeta } from '#/helpers/globalHelpers';
import Head from 'next/head';
import { useDispatch, useSelector } from 'react-redux';
import { increment, decrement, selectValue, bulkUpdate, reset } from '#/slicers/propertySlice';
import Link from 'next/link';
export default function Home({ meta }) {
const data = useSelector(selectValue);
const dispatch = useDispatch();
console.log(meta);
return (
<>
<Head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="og:title" content={meta.title} />
<meta name="og:description" content={meta.metadescription} />
<meta name="description" content={meta.metadescription} />
<meta name="keywords" content={meta.keywords} />
<title>{meta.title}</title>
</Head>
Hello world!
</>
)
}
export async function getServerSideProps({ resolvedUrl }) {
const pageData = await getMeta(resolvedUrl);
return {
props: { meta: pageData[0] }
}
}
I am working with next.js yarn and redux. I am trying to get my SEO data from my api and render is wit ssr. But it is rendering at the client side and SEO crawler tools (i am using screaming frog) can't see my title and description
Here is my code. I couldn't understand why my Head tag is rendering at the client side. Anyone can help?
Extra info, i checked _document.js, tag is correctly used and defined.
import { Html, Head, Main, NextScript } from 'next/document'
import Script from 'next/script'
export default function Document() {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
<Script src="assets/js/jquery.min.js"></Script>
<Script src="assets/bootstrap/js/bootstrap.min.js"></Script>
<Script src="assets/js/aos.min.js"></Script>
<Script src="assets/js/bs-init.js"></Script>
<Script src="assets/js/checkbox-show-hide.js"></Script>
<Script src="assets/js/dropdown-saver.js"></Script>
<Script src="assets/js/floatsearch.js"></Script>
<Script src="assets/js/heroclean.js"></Script>
<Script src="assets/js/location-list.js"></Script>
<Script src="assets/js/mobilemenu.js"></Script>
</body>
</Html>
)
}

MIxed Content bug requesting font stylesheet with Next js

I'm trying to add font to my website through Nextjs in a React component but getting the following error :
Mixed Content: The page at 'https://example.com/page/subpage' was loaded over HTTPS,
but requested an insecure stylesheet 'http://allfont.net/cache/css/bookman-old-style-bold.css'.
This request has been blocked; the content must be served over HTTPS.
I'm not sure why I'm getting this error since I'm making a https request via the Head like so:
import Head from "next/head";
export default function page() {
return (
<Head>
<link
href="https://allfont.net/allfont.css?fonts=bookman-old-style-bold"
rel="stylesheet"
type="text/css"
/>
</Head>
)
}
<link rel="preconnect" href="https://allfont.net" />
<link
href="https://allfont.net/allfont.css?fonts=bookman-old-style-bold"
rel="stylesheet"
type='text/css'
/>

Dynamically modify link rel="stylesheet" in head by react js

I have a multi language web project made by React.js & typescript and want to using bootstrap 5 CSS.
The problem is I want to dynamically change bootstrap CSS link on head section depend on language (ltr or rtl).
This link in public/index.html file:
<head>
...
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
...
</head>
convert to this dynamically:
<head>
...
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.0-beta1/dist/css/bootstrap.rtl.min.css" integrity="sha384-mUkCBeyHPdg0tqB6JDd+65Gpw5h/l8DKcCTV2D2UpaMMFd7Jo8A+mDAosaWgFBPl" crossorigin="anonymous">
...
</head>
After changing language I want to modify CSS link for rtl or ltr.
I'm using method on rout and successfully changing HTML dir but looking to modify with React.js & TypeScript.
Is there any solution for doing this?
You can do this by using ReactHelmet.You can create a StyleSheetUrlSelector Component. Then based on your criteria, you can render whichever stylesheet you want to render.
import React,{ FC } from "react";
import ReactHelmet from 'react-helmet';
interface ICssSelector {
ltr:boolean;
}
const CssSelector:FC<ICssSelector> =(props)=>{
const {ltr} =props;
return(
ltr === true?
<ReactHelmet link={
[{"rel": "stylesheet", type:"text/css", "href": "/style.ltr.css"}]
}/>
: <ReactHelmet link={
[{"rel": "stylesheet", type:"text/css", "href": "/style.rtl.css"}]
}/>
);
}
export default CssSelector

How do i Include css from static folder in a nextjs react project?

I'm fetching data from api call in _document.js, and based on data putting condition to include css using Link tag.
I was trying to include css file from public/static/ folder in _document.js or layout.js file,
but not working.
layout.js file
import React from 'react';
import Head from 'next/head'
...
<Head>
<link rel="stylesheet" href="public/static/ed_style.css" />
</Head>
...
I think your link is not correct. You can try an absolute one like this
<link rel="stylesheet" href="/static/ed_style.css" />
You should use import NextHead from 'next/head' instead of import Head from 'next/head'
Create your own Head component :
const Head = () => (
<NextHead>
<link rel="stylesheet" href="static/ed_style.css" />
</NextHead>
)
And then in your layout.js
import Head from '../components/head.js'
Thank you guys for you time.
I got solution.
I have put my css file ed_style.css directly to public folder and accessed as below.
<link rel="stylesheet" href="/ed_style.css" />
and Its working

react-helmet outputting empty strings on server-side

I am using react-helmet and on the client all is good in the inspect window and the tags are being outputted correctly. However, when I boot up in production and the SSR kicks in the tags aren't shown in the source and I'm getting no errors at all.
I tried logging the 'stringified' title tag too and got:
<title data-react-helmet="true"></title>
Here is some code:
This is one of the page components where I'm setting the tags from, the 3 page components are all set up identically to this. (I've simplified the components render function and data object as they are quite large and I'm sure these aren't at fault.)
import React, { Component } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import { Helmet } from 'react-helmet';
// Components
import WorkGrid from 'universal/components/Grid';
import Wrapper from 'universal/components/Wrapper';
import Container from 'universal/components/Container';
import Hero from 'universal/components/Hero';
import PageWrapper from 'universal/components/PageWrapper';
import GridHeader from 'universal/components/GridHeader';
const data = {};
class Work extends PageComponent {
render () {
return (
<PageWrapper ref="root">
<Helmet>
<title>Work</title>
<meta name="description" content="Work Description" />
</Helmet>
<h1>Work Page</h1>
</PageWrapper>
);
}
}
export default connect(state => ({
theme: state.ui.theme
}), { changeTheme }, null, { withRef: true })(Work);
This is some of the server code, specifically where the SSR goes down and I'm calling Helmet.renderStatic();
// Node Modules
import fs from 'fs';
import {basename, join} from 'path';
// Libraries
import React from 'react';
import {StaticRouter} from 'react-router';
import {renderToString} from 'react-dom/server';
// styled-components
import { ServerStyleSheet, ThemeProvider } from 'styled-components';
import { theme } from '../universal/constants';
// Redux
// import {push} from 'react-router-redux';
import createStore from 'data/redux/createStore.js';
import createHistory from 'history/createMemoryHistory';
import { Provider } from 'react-redux';
// Third Party Scripts
import * as thirdPartyScripts from './thirdPartyScripts.js';
// Helmet
import {Helmet} from 'react-helmet';
function renderApp(url, res, store, assets) {
const PROD = process.env.NODE_ENV === 'production';
const context = {};
const {
manifest,
app,
vendor
} = assets || {};
let state = store.getState();
const stylesheet = new ServerStyleSheet();
const initialState = `window.__INITIAL_STATE__ = ${JSON.stringify(state)}`;
const Layout = PROD ? require( '../../build/prerender.js') : () => {};
const root = PROD && renderToString(
stylesheet.collectStyles(
<Provider store={store}>
<ThemeProvider theme={theme}>
<StaticRouter location={url} context={context}>
<Layout />
</StaticRouter>
</ThemeProvider>
</Provider>
)
);
const styleTags = stylesheet.getStyleTags();
const seo = Helmet.renderStatic();
console.log(seo.title.toString());
const html = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
${seo.title.toString()}
${seo.meta.toString()}
${seo.link.toString()}
<link rel="shortcut icon" href="/favicon.ico">
<link rel="icon" sizes="16x16 32x32 64x64" href="/favicon.ico">
<link rel="apple-touch-icon" href="/favicon-57.png">
<link rel="apple-touch-icon" sizes="114x114" href="/favicon-114.png">
<link rel="apple-touch-icon" sizes="72x72" href="/favicon-72.png">
<link rel="apple-touch-icon" sizes="144x144" href="/favicon-144.png">
<link rel="apple-touch-icon" sizes="60x60" href="/favicon-60.png">
<link rel="apple-touch-icon" sizes="120x120" href="/favicon-120.png">
<link rel="apple-touch-icon" sizes="76x76" href="/favicon-76.png">
<link rel="apple-touch-icon" sizes="152x152" href="/favicon-152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/favicon-180.png">
<meta name="msapplication-TileColor" content="#FFFFFF">
<meta name="msapplication-TileImage" content="/favicon-144.png">
<meta name="msapplication-config" content="/browserconfig.xml">
${ styleTags }
${PROD ? '<link rel="stylesheet" href="/static/prerender.css" type="text/css" />' : ''}
<link href="${thirdPartyScripts.googleFont}" rel="stylesheet" type="text/css">
<script>${thirdPartyScripts.googleAnalytics}</script>
</head>
<body>
<script>${initialState}</script>
${PROD ? `<div id="root">${root}</div>` : '<div id="root"></div>'}
${PROD ? `<script>${manifest.text}</script>` : ''}
<script>${thirdPartyScripts.facebookPixel}</script>
<script async src="${thirdPartyScripts.googleAnalyticsSrc}"></script>
${PROD ? `<script src="${vendor.js}"></script>` : ''}
<script src="${PROD ? app.js : './static/app.js'}"></script>
</body>
</html>`;
res.send(html);
}
Also, I am using React Router v4 if that's of any help.
I found the solution to this the other week and thought I may as well update this so it can help anyone else having this problem...
Good news is it was surprisingly simple!
For me anyway it was down to the fact that I separate webpack bundles for the client and the server. So in layman's terms it was including react-helmet twice, once for the client and once for the server, meaning all the state holding the meta tags in the client side code didn't exist in the .rewind() call on the server.
Just add this to your server webpack config file
externals: ['react-helmet']

Resources