I am having a small issue, I know I can use _document.js for /page however I need a different document layout for a directory. I am wondering how can I change the document theme/layout based on a sub directory.
I tried to make a new _document.js under the sub directory /staff however that did not work.
That is a good question, indeed you can only create one custom _document.js (or _document.ts if you are using typescript). To change the structure of your DOM -- adding scripts, changing <Head> balises for SEO etc...
Since _document.js is the "root" of the DOM tree, it would not make sense to be able to overwrite this file in other subfolders.
However, if you need a different Layout, I would suggest to create a custom Layout component that you can use whenever you need! In your case, you can name it StaffLayout.
Note that your problem is a common use case and Next.JS even provided a demo repository to help you achieve it.
eg.
// components/staffLayout.js
import Navbar from './navbar'
import Footer from './footer'
export default function StaffLayout({ children }) {
return (
<>
<Navbar />
<main>{children}</main>
<Footer />
</>
)
}
and then in your /staff directory
// pages/staff/backOffice.js
import StaffLayout from '../../components/staffLayout'
export default function BackOffice() {
return (
<StaffLayout>
<>enter you code here</>
</StaffLayout>
)
}
If you need multiple Layouts, Next.js created a mechanism out-of-the-box that can even remove the need for using StaffLayout every-time. It is a little bit more advance so I will only link the documentation.
Related
I'm using Next.js version 12.0.4 on a new project, having used Next.js version 10 on a prior one.
Has something changed with Static Site Rendering at build time? It's rendering all my output pages when I do an npm run build (which in turn executes "next build and next export") with html files that include a ton of .js files and no native text "content" which I'd expect.
That is, the output doesn't have any of the standard HTML <h1>, <h2> etc. in it, just a bunch of javascript for the client to hydrate.
Prior versions of Next.js (or perhaps it was my configuration?) seemed to render pure, finalized HTML just fine.
I'm trying to render a simple About page (no dynamic routes, no dynamic props for this route) and, while it properly renders a page in the "/about/index.html" output location, that page has a bunch of .js files and a JSON payload. That page does indeed display properly, but I'd really like the output in the "out" directory to be actual .html files with HTML pre-rendered, for SEO and other reasons.
In my next.config.js, I've specified:
module.exports = {
exportPathMap: function () {
return {
"/": { page: "/" },
"/about": { page: "/about" },
};
},
};
I've also specified getStaticProps on the about page conponent (about.tsx). (I'm using typescript if that matters.)
The rendered /about/index.html file has a ton of .js includes and no real HTML "content".
Have I missed a configuration setting? What can I do to make it render pure HTML where I'd like?
AHA! Ok, so this error was of course a coding error on my side.
In _app.tsx, I had a wrapper for Authentication that I had written. By (bad) design, it was deliberately NOT rendering children for it if the user wasn't authenticated. Therefore, the pre-renderer wouldn't render the "regular" html elements, because the pre-renderer of course does not sign in.
If this same problem happens to you, make sure you're not wrapping all views up in some provider element which conditionally renders children.
Because of NEXT_DATA element dom size is getting very high and it is affecting to the performance. Can anyone plz help me to remove NEXT_DATA from dom?
I am using full server-side rendering with dynamic routes in next Js.
TLDR: If you would(/could) remove the __NEXT_DATA__ script tag, React wouldn't be able to hydrate. You either hardcode the data in the page or try to reduce your pageProps payload, returned from getServerSideProps.
I came upon this issue also recently, where I asked myself, why would there be a need for the content to be included in the HTML 2 times.
As the content itself - when your NextJS renders the appropriate HTML and sends it to the client
As JSON in <script> tag - This is because of the need for rehydration on the client side.
"Solutions"
Returning only necessary data from data-fetching method - I can recommend reading up on this article Reducing HTML payload with NextJS, in which they talk about formatting / aggravating the necessary data and returning only the needed fields.
Not using the data-fetching method and hardcoding static content - The idea behind using static data fetching, if not using revalidate option, is that the content shouldn't be changing (maybe ever). So in that case, why couldn't we hardcode the data in the page itself. Althought downside of this of course is, having to write it all out manually / download the required content to some JSON / object and then use it in the page like so.
Reading
Here's a github link with related discussion in next in which you might be interested.
Blog post about reducing the size of __NEXT_DATA__ - by Liran Cohen.
To remove the rehydration data regex: <script id="__NEXT_DATA__((.|n)*)script> from all pages of the static website run the following command after the build has finished:
find out -name '*.html' | xargs perl -0777 -pi -e 's/<script id="__NEXT_DATA__.*?script>//sg;'
If you come across this issue, make sure you don't have any conditional rendering. This is how I solved this issue myself !
You can do this to not show __NEXT_DATA__:
export const config = {
unstable_runtimeJS: false,
};
But all JavaScript functionality will not work in frontend.
Sometimes you might not require some of the __NEXT_DATA__ props during client side rendering.
To drop those props, you can mutate the NextScript.getInlineScriptSource function in the _document.tsx file. Here is an example:
// _document.tsx
const nextInlineScriptSource = NextScript.getInlineScriptSource;
NextScript.getInlineScriptSource = (props) => {
if (props?.__NEXT_DATA__?.foo) {
props.__NEXT_DATA__.foo = 'bar';
}
return nextInlineScriptSource(props);
};
I'm using Gatsby for the first time on a simple website project. I'm accustomed with traditional React apps where there is a root file component, typically "App.js" that one attaches Providers and other global level functionality.
Gatsby doesn't offer a root App.js, but it does offer wrapRootElement and wrapPageElement, which, after a bit of wrangling, worked just fine on my localhost.
export const wrapRootElement = ({ element }) => {
return (
<ThemeProvider theme={theme}>
{element}
</ThemeProvider>
)
}
and
export const wrapPageElement = ({ element, props }) => {
return <Layout {...props}>{element}</Layout>
}
inside of gatsby-browser.js (and with appropriate local imports and such)
(using Root for my Theme Provider and Page for my Layout wrapper, which includes header and footer elements)
I used 'gatsby clean' then 'gatsby build' to generate the deployable public folder, but upon upload to my shared host, only the inner portion showed up, not the header or footer, nor did my theme colors show up.
On a whim, I downloaded Gatsby and pulled out their "using-redux" example, built, and deployed it to the same shared host with similar results — that is, it doesn't behave as expected.
What am I missing? Since it fails on the Gatsby example, I'm presuming it as something to do with my server side setup (recall, it works fine on localhost). I have Node installed, but I'm not using it as part of this app; it's intended to be completely static and I'm just trying to use the wrappers to clean up my code.
After toying around with it some more, I replicated the code in gatsby-browser.js into gatsby-ssr.js. Voila, it worked.
This article is what inspired me, sort of: https://www.gatsbyjs.org/docs/api-files-gatsby-browser/. It states:
If you use one of them, consider if you should implement it in both
gatsby-ssr.js and gatsby-browser.js.
I had read the article earlier, but didn't take the gatsby-ssr.js file as being a requirement. Apparently, I should have interpreted the word "should" a bit more forcefully.
I have problem with parent fetch() hook, which is called during going to child page through the nuxt-link. How to resolve this problem? Maybe is it nuxt.js bug? To achieve parent -> child structure, I set up my project according to the pattern given in the nuxt.js documentation:
-parent.vue
-parent
--child1.vue
--child2.vue
For example going to Child1 through the nuxt-link: <nuxt-link to="/parent/child1">Child1</nuxt-link> causes calling fetch() hook in parent.
I think a lot of people have this problem. Thank you in advance for your help in resolving this problem.
Take a look at Vue custom options merge strategies https://v2.vuejs.org/v2/guide/mixins.html#Custom-Option-Merge-Strategies
~/plugins/custom-merge-fetch.js
import Vue from 'vue'
Vue.config.optionMergeStrategies.fetch = function (childFetch, parentFetch) {
// your logic
}
And in nuxt.config.js
plugins: [
'~/plugins/custom-merge-fetch',
],
I have already find the solution, which is very simple. In my case I forgot add default page for nuxt-child(creating index.vue file in parent folder) like below:
-parent.vue
-parent
--index.vue
--child1.vue
--child2.vue
After doing this, the problem is resolved and parent fetch() hook is not calling anymore. Previously, the DOM structure was not generated by default for child pages(index.vue file was not created), which resulted in the parent refreshing, when going to the child page through the nuxt-link.
I am on wodpress 5.2 with twenty-ten theme. This means there is a lot of places where gutenberg generated content is broken. I could fix many things in child theme css, yet I want embedded images looking like old ones. I am looking for short and clean way to inherit what built-in image block offers and make custom image with same editor options yet slightly modified HTML fragment generated by that block, applying custom classes to figure and figcaption for a start.
You have two options (at least).
Make your own block
You can grab the code of the image block at github and start creating your own block from it, e.g. using create-guten-block. You will need some time (~ 1-2h) to get it working because some import statements and other things must be adapted, it's not only copy and past.
=> Use it if you need lots of customizations to what the image block can offer and you want to get to the heart of block creation, altering functions, behavior, appearance, anything.
Edit the existing block in a filter
Gutenberg offers many new filters, e.g. the blocks.getSaveContent.extraProps filter. It lets you manipulate the blocks properties, such as the classes.
function addBlockClassName( props, blockType ) {
if(blockType.name === 'core/image') {
return Object.assign( props, { class: 'wp-caption' } );
}
return props;
}
wp.hooks.addFilter(
'blocks.getSaveContent.extraProps',
'some-custom-name/add-block-class-name',
addBlockClassName
);