How can I implement a real partial update with ReactJS? - javascript

I had a job interview and the recruiter asked me about "handle the partial updates and manage application size"
For example he explained and displayed a SPA that size was 8MB and he said it's not ideal and perfect !?!?
And he said we should manage the application size with different methods !?
For a test, after the interview session I checked the linkedin website with google chrome DevTools. after any requests I saw response who that was html web page (Html, Css, JS) and apparently linkedin after each requests appends html response to page who it's an idea to control SPA size !
So I have a question, by default in create-react-app package we have webpack to create web modules and that load all components to one bundle.js and this js file will be heavy for 40 or more component. maybe 10MB or more than ...
How can I implement a real and optimized SPA structure with a perfect and accurate partial update method ?
Unfortunately I just know a little of English, please forgive me if I had mistake to write English :-) ;-)
Thank you

I think what you are looking for is Dynamic imports or asynchronously loading components(or more code) whenever needed. There are various ways you can do this like
Load when the user scrolls down towards the components
Only Load the component when a user clicks a button (ex. a Modal)
Load the component after the initial critical data is already rendered(ex. only ldownload the code for the component after its parent component is already loaded and rendered to the dom).
The last example can be done like this :
class Dynamic extends Component {
constructor(props) {
super(props);
this.state = { module: null };
}
componentDidMount() {
const { path } = this.props;
import(`${path}`)
.then(module => this.setState({ module: module.default }))
}
render() {
const { module: Component } = this.state; // Assigning to new variable names #see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
return(
<div>
{Component && <Component />}
</div>
)
}
}
What the above code is doing is loading the Component code after its parent component is already loaded by importing it in component did mount.
This code-splitting method is currently
supported by create-react-app.
read more here
Also check this react-loadable

I suggest you look at lazy loading concepts in ReactJs documentation. It is basically importing only when need arrives and reduces bundle size.
ReactJS Code splitting Documentation

Related

How do I take advantage of Next.js server-side rendering while using React hooks extensively?

I've recently started working on a frontend project that uses Next.js, and I'm trying to figure out how to best take advantage of the SSR it provides. I want to use some client-side fetching as well, and while the documentation explains that using React hooks in a component will make it render client-side, it seems quite sparse about how this affects the other components up/down the DOM tree.
I tried to test the SSR/CSR behaviour by creating a site with some components with/without React hooks in them, and opening it in Chrome first with JavaScript enabled, then disabled. So far I've found out a couple of things and I was wondering if my assumptions are right:
it seems that components that use hooks work like typical React components - their children re-render when effect/state hooks in the parent render, so they don't seem to benefit from SSR and should instead be optimised using React features like React.memo.
when I open the site with JS disabled, it seems that all components come pre-rendered - components that use state and display it, even show the initial state set in the hook. For example, the below component:
export const TestComponent = () => {
const [num, setNum] = useState(13)
return (
<div>
<button onClick={() => setNum(num+1)}>CLICK</button>
<h2>Number: {num}</h2>
</div>
)
}
actually contains the text "Number: 13" (the button obviously doesn't work without JS though)
What I'm also wondering is how much using global context providers is going to diminish performance improvement from SSR. Let's say my _app.jsx wraps each page in a provider that periodically queries an API. Does it completely void the advantage presented by SSR, seeing as it will probably cause the entire page to re-render?
Think of SSR as first paint data, and what is the trigger for it. Anything that causes the trigger for SSR to run, you will be getting data from getServerSideProps
SSR is usually done for SEO purposes so the bot can crawl the pre-rendered data. Any data that is depended on client-side fetch will be less prone for crawling.
Let's say for a shopping page, the initial products load can be SSR while subsequent products on clicking of a 'Load More' button happens on client side with the useSWR hook. This is a valid approach, and it mixes both SSR and CSR.
If a provider queries the API, that is a client side fetch. It won't coincide with what SSR is doing. It's important to know the trigger for SSR, which usually happens on a first visit, reload and anything that triggers a route change / push. Both SSR and client-side fetch do things their own way.
Further Reads:
https://swr.vercel.app/docs/with-nextjs#pre-rendering-with-default-data
https://nextjs.org/docs/routing/shallow-routing
There is no one-size-fits-all answer to this question, as the best way to take advantage of Next.js server-side rendering while using React hooks extensively will vary depending on your specific needs and preferences. However, some tips on how to achieve this include:
1. Try using the Next.js client and server libraries together. The Next.js client library allows you to use Next.js features in your React applications, while the Next.js server library allows you to use Next.js to rendering your applications on the server. This can be a great way to take advantage of both Next.js' server-side rendering capabilities and React's hooks feature.
2. Use react-router-dom for routing. react-router-dom is a popular routing library for React that also supports server-side rendering. This can be a good choice for applications that need to use Next.js' server-side rendering capabilities as well as router functionality.
Here is the small example. I hope it would help you.
import React from 'react';
import { useRouter } from 'next/router';
const Page = () => {
const router = useRouter();
const { id } = router.query;
return <p>Post: {id}</p>;
};
export default Page;

Next.js - How to use getStaticProps to fetch Menu data and then pass it to the layout?

I am using Sanity.io as a backend, within Sanity I am handling the data for my main menu (parent/children object arrays).
Whilst I can fetch this data just fine, I want to do so via getStaticProps, as I'd like my site to remain entirely statically generated.
getStaticProps doesn't work in my layout.js file as it's not located in the "pages" directory. Nor does it work inside the _app.js file.
So currently Im having to fetch the menu within each page, and pass it as a prop into the Layout components (which has to be on every page now!), so that I can pass it from inside the Layout into the header component.
As such, my page looks like this:
function Page({ menu }) {
return (
<Layout menu={menu}>
<article>
...
</article>
</Layout>
)
}
export const getStaticProps = async (context) => {
const menu = await client.fetch(**menu query**);
return {
props: {
menu,
},
};
}
I am well aware that the Layout component should be situated inside the _app.js file instead, and that is where I'd rather it were, but I can't
This is obviously a very convoluted way of doing it, but I see no other method currently outside of using getInitialProps within Layout, but as I understand it, this will involved SSR rather than SSG.
I spent quite some time researching but the best answer I've found so far is that allowing getStaticProps in the layout "will be allowed in the near future", alas this was some time ago...
Can anybody point me in the right direction?
It seems crazy to have to include the layout on each page rather than have it on every page in the app, just so that I can get data into the header component at build time.
Although I still haven't found a native solution to this which doesn't involve fetching the menu data in getStaticProps on every page and passing it up the tree to the Layout -> Header.
I did come across a guide to a Node based solution from Brewhouse digital, NextJS getStaticProps With Components which is pretty cool.
Basically you can just create a "pre-build" process which is executed before the build, it fetches the data from your endpoint and stores it locally in a JSON file. You can then read that JSON file directly into your Layout or Header component for example.

How to lazy load Angular Components of the home page?

I have my code as given below in app.component.html i.e. as soon as the user lands on the home screen; I want to lazy load the app-image-gallery & app-users-list and want to load them with some Shimmer effect or Loader as soon as the user reaches the viewport of that particular component. Almost every grown up site use this but this thing is kind of difficult to find for Angular.
I have read many articles on lazy loading of component on button click but haven't found this thing implemented anywhere.
app.component.html
<app-navbar></<app-navbar>
<app-image-gallery></app-image-gallery> //list of images from backend
<app-users-list></app-users-list> //users list from backend
<app-faq></app-faq>
UPDATE(2022) -
After a lot of reasearch, I found these awesome packages for Angular lazy loading of components because packages like #herodevs/hero-loader & ngx loadable are deprecated for newer versions of angular. I will also attach the link to their articles-
#angular-extensions/elements
#juristr/ngx-lazy-el
ngx-element
Articles-
#juristr/ngx-lazy-el
#angular-extensions/elements
These packages are suitable for Angular 9+ versions. I hope it helps someone. And suppose if you want to load components on scroll, On Scroll Load, this is the thing you are looking for and each solution fully tested.
This solution is been tested with angular 9 and above with ivy.
If you are using older version of angular checkout this article:
https://pretagteam.com/question/load-new-modules-dynamically-in-runtime-with-angular-cli-angular-5
Angular 9+ solution:
Before you start you should make sure that your lazy loading components are in a separated module which is not imported in your app module.
First you need to pick a container element and mark it with a template variable to render your lazy component inside it.
Something like:
<div #container></div>
And then in your component class you need to query this container using #ViewChild as ViewContainerRef:
#ViewChild('container', {read: ViewContainerRef}) container: ViewContainerRef;
Now you are ready to lazy load your component using the webpack dynamic import. which as by default available in an angular app.
Then you will need to resolve the component factory using the angular ComponentFactoryResolver after you inject it in your component constructor.
And at the end you will just render the component factory in the view reference you have prepared this.container:
lazyLoadAppImageGallery() {
import('path/to/your/app-image-gallery-component')
.then(({AppImageGallery}) => {
const componentFactory =
this.componentFactoryResolver.resolveComponentFactory(AppImageGallery);
const { instance } = this.container.createComponent(componentFactory);
});
}
After you have rendered your component you might want to pass some data to it.
You could use the instance for this:
instance.propertyName = someValue
Checkout this nice article for more infos:
https://medium.com/#ckyidr9/lazy-load-feature-modules-without-routing-in-angular-9-ivy-220851cc7751
Update
Here is a working solution with dynamic render on scroll
https://stackblitz.com/edit/angular-ivy-megwrz
If you might use lazy loading with routes, just checkout angular simple documentation
https://angular.io/guide/lazy-loading-ngmodules
You could also combine both solutions. In case you want to dynamically load a component in a lazy loaded module loaded by route.
Update since Angular v13
Since v13 ComponentFactoryResolver is deprecated. Create component does require resolving component factory. You can use the component class directly thanks to the Ivy engine. Which means instead of writing:
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(AppImageGallery);
const { instance } = this.container.createComponent(componentFactory);
you could just write:
this.viewContainerRef.createComponent(AppImageGallery);

jQuery in react component

I have a web-app built with react. In this app I also have some pages with jQuery code from an old version. Right now this is rendered server side and i have to load the entire ejs file with jQuery and jQuery-UI code in script-tags with its own navigation menu. (Almost 1000 lines of jQuery code)
This means that I have to build another nav-menu for these jQuery pages.
I would like to render this jQuery depended code in my "content div" so I can still use the react menu which uses react router. I would like to render it like a component. But I don't know if this is the best solution.
I have read many examples of how this could be done, but I don't know which of them to go for and I have been strugling to make them work
Like shown in this example: Adding script tag to React/JSX This example adds script tags in componentWillMount
Or with import and require like this example: How to add script tag in React/JSX file?
I couldn't make these solutions work without installing jQuery through npm.
I have not yet installed jQuery through npm because I know this will affect my bundle size for the rest of the application and I am only using jQuery for a couple of my pages. The user don't really need to load jQuery for the rest of the app
What do you recommend in a situation like this? What is the best solution for performance and user experience?
Take a look at react-async-component. Your component might look something like:
// SomethingWithJquery.js
import React, {Component} from 'react'
import $ from 'jquery'
class SomethingWithJquery extends Component {
constructor(props) {
super(props)
}
render() {
// ... as much jquery mess as you need
}
}
export default SomethingWithJquery
And wrapper in separate file:
// SomethingWithJquery.async.js
import { asyncComponent } from 'react-async-component';
export default asyncComponent({
resolve: () => System.import('./SomethingWithJquery')
});
Than you can use it as regular react component, react-async-component will load entire component in separate .js file on purpose under the hood.

What in React should actually be rendered

I am currently working on learning React and Redux. Now I am getting a better grasp on what the two do:
React - Render components on the page
Redux - Keep the state of the page
My question though is: what should I actually be rendering with React? Is React suppose to render the entire page, even the header that won't change? For instance, am I suppose to create a new component for the header (logo and tabs, not changing), or just add that to the HTML file I will be rendering to?
I would suggest adding absolutely everything as a React component. Have a single <div> in your html file that you mount your React app to. I found that when I started using React I would try and avoid writing extra code (sure, writing a component for a header rather than the raw HTML is extra lines).
But this introduces complexity, in a way. Different parts of your app are rendered differently. In the long run, in my experience, consistency and readability is more important than fewer lines of code.
BTW if you're using stateless functional components (which your header would be), it's barely any extra code.
import React from 'react';
export default Header = () => <header>My wonderful app</header>;
like most other frameworks, you will have your base 'index.html' file that will include all of your dependencies and then a body which contains a div that you will render your react components into. it will look something like this:
<html>
<head>
<-- script, css, framework files added here -->
</head>
<body>
<div id="reactApp"</div>
</body>
</html>
then your main app file in react will have something along the lines of this at the bottom:
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('reactApp')
);
everything else can be rendered within React and passed along to that div view.
It's entirely possible to have a hybrid page. For example: keep the navbar as native HTML where as the content is React.
Remember, React is component oriented so you could think of it as small widgets.
However, you will often have different widgets share the same state. In this case, it's good to make them part of the same tree of components.
Your question doesn't have a definite answer. It depends on what your application state needs are, but use React for the dynamic pieces of your page. Those parts that you're thinking are going to change without a reload will probably keep a state, so that's where React's stage management could come in handy.

Categories