ReactJS: Load .less only when component is used - reactjs

I am probably missing a verry basic understanding of loading less files in ReactJS, but I am unable to solve the following issue.
I have created components and created less files for each of them, for example:
import * as React from 'react';
import Row from 'antd/lib/row';
import Col from 'antd/lib/col';
import { NavLink } from 'react-router-dom';
import '../styles/how-it-works-styles.less';
import Icon from 'antd/lib/icon';
class HowItWorksComponent extends React.PureComponent<Props> {
public constructor(props: Props) {
super(props);
}
public render() {
return (
<Row className={'steps-row'}>
Now when I load a page where this component is not at all used, the less file is stilling being loaded into the dom. Could someone explain why this is happening and how i can prevent this from happening?

Your problem is not really about less, but a general problem of how to bundle a web app optimally. Since you're not providing your main app component or your webpack config (assuming you're using webpack for bundling), I obviously don't know the details of your setup. In general however, the standard configuration is to bundle all the components and other imports reachable from the entry point file into one big file. The fact that you use react router or similar to split your app into "pages" doesn't change this, as react router only affects which components are rendered when, not the bundling.
If you need to split your app into multiple bundles (which IMO requires a relatively large app to consider) you can use dynamic imports to make some of your components "Loadable". This means they will be placed in a separate bundle which is only loaded as needed. There is a tutorial in the react router documentation on how to set this up: https://reacttraining.com/react-router/web/guides/code-splitting

Related

Tree shaking from remote import

This question might seem unusual and a little anti-pattern but at this stage I am just trying to figure out what is possible.
The situation is that I have a few components which are available from a remote import (via Webpack 5's Module Federation). The caveat is that I don't want to lazily load them.
Once imported, the components are passed into a HOC to enrich some functionality and then exported:
import ComponentFooRemote from 'testRemote/Foo'
import ComponentBarRemote from 'testRemote/Bar'
const ComponentFoo = withEnrichedFunctionality(ComponentFooRemote)
const ComponentBar = withEnrichedFunctionality(ComponentBarRemote)
export {
ComponentFoo,
ComponentBar,
}
Functionally this works as expected. The components can be imported, rendered, and no components are loaded twice.
The issue is that the code imported from the remotes are always loaded. If I don't use ComponentBar - or even if I delete ComponentBar - the code from the remote will be downloaded as long as the original import is present. This is happening when using both development and production mode in the Webpack config.
Does anyone know if I can tree-shake these imports or restructure the code to better optimise the performance? Ideally I would like to import the components from the same path.

Can I use react in some view of my laravel website

I have a laravel website that is currently live and is using blade template for the views and I am thinking of using react JS in some views.
I want to know if it's possible to use react in some views while still having the blade template rendering some views.
OR do I have to rewrite the whole website in react for this to work.
Ok here's some example code that might help you get started with React:
Write a test react app e.g. test.jsx in your resources/js (or .tsx if you're using typescript). It might look something like:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './App';
const root = document.getElementById('react-root');
if (root) {
ReactDOM.render(
<App />,
root
);
}
Here App is the React component root for the feature you are replacing.
You can add this in your webpack.mix.js file as well to transpile it independently or import it in your app.js (which is easier). However in the later case you are loading this code in all views and if there is another page with an element with id react-root there will be problems.
Your blade will now become:
#extends('layouts.index')
#section('content')
<div id="react-root"></div>
#endsection
Of course here it is oversimplified. You can just replace only the part that has the feature you are transitioning with <div id="react-root"></div> and have react handle that part from then on.
You can also do this multiple times in a single .blade.php file by making multiple calls to ReactDOM.render on different root elements. React will be fully responsible for everything under the root elements it renders to and the rest of your code will continue to run as before. However be aware that code that relied on element selectors via e.g. jQuery should not be used to manipulate nodes that React manages as that may cause problems.

REACT import css and js files

My application needs to have two pages, one landing page and one admin page. Both pages use different themes. I could not integrate css and js files of these two pages in a single page application.
const jquery = require('mdbootstrap/js/jquery-1.11.3.min.js');
window.jQuery = jquery;
window.$ = jquery;
require('mdbootstrap/css/bootstrap.min.css');
require('template/homePage/js/plugins/owl-carousel/owl.carousel.css');
require('template/homePage/js/plugins/owl-carousel/owl.theme.css');
require('template/homePage/js/plugins/owl-carousel/owl.transitions.css');
require('template/homePage/css/animate.css');
require('template/homePage/js/plugins/YouTube_PopUp-master/YouTubePopUp.css');
require('template/homePage/css/preloader.css');
require('template/homePage/css/style.css');
require('mdbootstrap/js/popper.min.js');
require('mdbootstrap/js/bootstrap.min');
require('template/homePage/js/plugins/vivid-icons');
require('template/homePage/js/plugins/owl-carousel/owl.carousel.js');
require('template/homePage/js/plugins/YouTube_PopUp-master/YouTubePopUp.jquery.js');
require('template/homePage/js/plugins/wow/wow.js');
require('template/homePage/js/plugins/jquery.easing.min.js');
require('template/homePage/js/main');
this sample import not good work. And I need outside link css and js.
I have two problem one of them is $(...).scrollspy is not a function
other WOW is not a function.
None of them work in sequence.
When you want to import resources into your React app, you use imports like this:
// Import with variable assignation
import logo from './logo.png';
// Import without variable assignation
import './css/index.css'
You can read more about this in the create-react-app documentation:
https://create-react-app.dev/docs/adding-images-fonts-and-files/
You can read more about ES7 imports here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
I see what you're trying to do is to add libraries and resources to your app component, like if were a common html file, you can't do that in React , you need to find an implementation.
It is not recommended to use jQuery with React, because you use jQuery to write code in a simple and fast way to create complex implementations, now those complex implementations can be made with just React and JS, that is what React is designed for.
Now I understand that you might want to use jQuery even do is not that recommendend, so here is a link where you can get jQuery to install it as a plugin for your React app
https://www.npmjs.com/package/jquery
You would be able to import it to your component like this:
import $ from "jquery";
To use Bootstrap in your React app you check out the documentation of an implementation of Bootstrap for React, react-bootstrap:
https://react-bootstrap.github.io/getting-started/introduction

How to import SCSS files in React component only when it renders?

I have a large React.js project, for which I have created separate SCSS files for separate React Components. The problem is styles in one component, let's say Component_1, are available in other components.
I have tried using import() the SCSS files within the Componets' componentWillMount() methods.
// instead of this
import "../Styles/_header.scss";
class Header extends React.Component {
// I am trying this
componentWillMount() {
import ("../Styles/_header.scss");
}
}
But I have many functional components, and for that I am seaching an Webpack way or any other way, so that my SCSS files will be only available in the Components from which I am importing... Thanks
I know it will have impact and you will need to refactor, but styled-components is your friend here.
Basically, you add styling on component level. In combination with lazy loading components you only load your component with its styling when the components need to be rendered by React.
You can use this babel plugin to conditionally import things. Also in your functional components you can use the effect hook to replace componentWillMount/componentDidMount.

React lazy loading javascript file

I am trying to make my application more performant with React.lazy. As the Ethereum lightwallet is a huge file, I would like to put it into a separate bundle. The currently working import is the following:
import lightwallet from 'eth-lightwallet/dist/lightwallet.min.js';
When I try to import using the lazy syntax
const lightwallet = React.lazy(() => import('eth-lightwallet/dist/lightwallet.min.js'));
Only a React.lazy object ($$typeof: Symbol(react.lazy)) is returned instead of the lightwallet object. I think this is due to the fact that lightwallet doesn't have a default export. How could I get around this problem? Thanks!
I suggest following the example here:
https://reacttraining.com/react-router/web/guides/code-splitting
react-loadable is an npm package that makes code-splitting (a.k.a lazy loading) quite easy and also provides you the ability to render a loading component until the lazy load has finished.
The only gotcha is that if you're using Babel to transpile your code bundles, you'll have to add support for the Dynamic Import syntax, webpack already has this by default, but Babel doesn't.
The Babel Plugin:
#babel/plugin-syntax-dynamic-import
will make this possible by adding support for the syntax.
I recommend react-loadable over React.lazy as it makes displaying a loading component while the lazy-load happens VERY easy, and provides you hooks to display an error component and retry the import in the case that it fails.
Read more about react-loadable here:
https://github.com/jamiebuilds/react-loadable
Your code would look something like this:
import Loadable from 'react-loadable';
import Loading from './YOUR-LOADING-COMPONENT';
const LoadableWallet = Loadable({
loader: () => import('eth-lightwallet/dist/lightwallet.min.js'),
loading: Loading,
});
export default class Wallet extends React.Component {
render() {
return <LoadableWallet/>;
}
}
Make sure that your react version is up to date in React v16.6.0. And also the core idea behind the React. lazy is React.lazy takes a function that must call a dynamic import(). This must return a Promise which resolves to a module with a default export containing a React component. But is this scenario min.js won't give any promise. Most probably That didn't work.

Resources