Performance of ES6 imports - javascript

In the React Bootstrap docs, it is suggested that modules be imported individually from single distribution files rather than from the larger distribution file.
import Button from 'react-bootstrap/Button';
// or less ideally
import { Button } from 'react-bootstrap';
Why is the second method less ideal?

As that link says:
You should import individual components like: react-bootstrap/Button rather than the entire library. Doing so pulls in only the specific components that you use, which can significantly reduce the amount of code you end up sending to the client.
If you import from react-bootstrap, the client will have to download everything in react-bootstrap. That could end up being quite a large chunk of code. In contrast, if you import from the react-bootstrap/Button, all that needs to be downloaded is the button - nothing extraneous is included.
Compare the file:
https://github.com/react-bootstrap/react-bootstrap/blob/master/src/Button.js
to
https://github.com/react-bootstrap/react-bootstrap/blob/master/src/index.js
As you can see, importing from the Button requires a few imports:
import classNames from 'classnames';
import React from 'react';
import PropTypes from 'prop-types';
import { useBootstrapPrefix } from './ThemeProvider';
import SafeAnchor from './SafeAnchor';
But importing from the index.js requires a very large number of imports, 77, to be precise.
export Accordion from './Accordion';
export AccordionToggle, { useAccordionToggle } from './AccordionToggle';
export AccordionCollapse from './AccordionCollapse';
export Alert from './Alert';
export Badge from './Badge';
// and 72 more
If you import from index instead of from Button, you're downloading a lot of code that you don't need, for no good reason.

Related

CSS modules importing doesn't work despite the righ compilation

I've got a problem with importing css modules to react component.
import React from 'react'
import styles from '../App.css'
const Button = () => (
... className={styles.button}...
)
export default Button;
There is no compilation error and stuff like that. Everything seems to by right, but when I run server button looks by default as with no css.
You need to use
Module css must have name App.module.css
Then import
import React from 'react';
import styles from './App.module.css';
And use className={styles.button}
The issue is probably in your webpack config - please share
In the css-loader options, ensure the modules option is set to true

Most efficient way of importing files from children folders?

I have a parent directory that contains children directories, where each contains an SVG component and I only need to import some of them. I'm currently importing all the components I need by doing this:
import FacebookIcon from 'project/icons/Facebook';
import TwitterIcon from 'project/icons/Twitter';
import DiscordIcon from 'project/icons/Discord';
import MediumIcon from 'project/icons/Medium';
import YoutubeIcon from 'project/icons/Youtube';
However this seems very verbose. Is there a less verbose way of doing this?
I thought about destructuring, but I wasn't sure how to do this since each file is in a different folder.
Typically, you want to import similar components from a single source (you will get auto-complete too):
import {
FacebookIcon,
TwitterIcon,
DiscordIcon,
DiscordIcon,
MediumIcon,
YoutubeIcon,
} from "project/icons";
// Usage
<FacebookIcon/>
// Same
import Icons from './project/icons';
// Usage
const Icon = Icons.FacebookIcon;
<Icon/>
To achieve this, create index.js file in project/icons and make named export for each of the components.
export { default as FacebookIcon } from "./FacebookIcon";
...

Standard Way for React Import Statements

I was wondering if there's a standard way to write import statements in react? For example, I have this:
import React, { useState, FormEvent } from 'react';
import Avatar from '#material-ui/core/Avatar';
import {Grid, Checkbox, TextField, FormControlLabel, CssBaseline} from '#material-ui/core';
import LockOutlinedIcon from '#material-ui/icons/LockOutlined';
import { LOGIN } from '../../graphql/mutations/login';
import { schema } from '../../helpers/validations/login';
import { Redirect } from 'react-router-dom';
import { useMutation } from '#apollo/react-hooks';
import StatusMessage from '../../helpers/statusMessages/loginMessage';
import Copyright from '../../components/copyright/copyright';
import CustomButton from '../../components/button/button';
import { ExecutionResult } from 'graphql';
import { Wrapper, StyledLink, Form, StyledTypography, StyledBox, StyledContainer} from './styles';
import { store } from '../../store';
import { useDispatch } from 'react-redux';
import SignInResponse from '../../graphql/responses/login';
import { useFormik } from 'formik';
Are there any rules about whether I should import everything from '#material-ui/core';separately or together? Does it make a difference apart from reducing the number of lines?
Is there any rule about if I should import other local files/functions after react's own libraries/content? Any other rules/suggestions?
There are known standard, most of them are opinions rather than must-dos. I would recommend that you take a look at eslint-plugin-import as it has a extensive list of standards/opinions regarding imports:
Ensure all imports appear before other statements ([first])
Ensure all exports appear after other statements ([exports-last])
Report repeated import of the same module in multiple places ([no-duplicates])
Forbid namespace (a.k.a. "wildcard" *) imports ([no-namespace])
Ensure consistent use of file extension within the import path ([extensions])
Enforce a convention in module import order ([order])
Enforce a newline after import statements ([newline-after-import])
Prefer a default export if module exports a single name ([prefer-default-export])
Limit the maximum number of dependencies a module can have ([max-dependencies])
Forbid unassigned imports ([no-unassigned-import])
Forbid named default exports ([no-named-default])
Forbid default exports ([no-default-export])
Forbid named exports ([no-named-export])
Forbid anonymous values as default exports ([no-anonymous-default-export])
Prefer named exports to be grouped together in a single export declaration ([group-exports])
Enforce a leading comment with the webpackChunkName for dynamic imports ([dynamic-import-chunkname])
Regarding the order, what's recommended is:
node "builtin" modules
"external" modules
"internal" modules
modules from a "parent" directory
"sibling" modules from the same or a sibling's directory
"index" of the current directory
There is no standard way, just personal preferences.
Personally, I prefer to group imports from a common source, like you did in '#material-ui/core';. You could also do that with components, helpers, and similar local modules. Also, I prefer to import first third-party modules and then local modules.
It's all about finding something "logical" and easy to scan to you.
Don't worry about how many lines were used to import modules. I think it's a best practice to first import modules from other vendors, then import local modules. There are some lint rules to enforce that I think.
Other than that, I'd say only import what is needed:
import Avatar from '#material-ui/core/Avatar';
is better than
import * as MaterialUI from '#material-ui/core';
No, there is no standard on how you import something. But instead of import everything just import what you need, it'll also help webpack in tree-shaking unused code. So I would suggest this:
import { Avatar } from '#material-ui/core';
One other I like to do is separate my local imports from the packages imports, it makes the code more readable:
import React, { useState, FormEvent } from 'react';
import LockOutlinedIcon from '#material-ui/icons/LockOutlined';
import { ExecutionResult } from 'graphql';
import { Avatar, Grid, Checkbox, TextField, FormControlLabel, CssBaseline } from '#material-ui/core';
import { Redirect } from 'react-router-dom';
import { useMutation } from '#apollo/react-hooks';
import { useDispatch } from 'react-redux';
import { useFormik } from 'formik';
import { LOGIN } from '../../graphql/mutations/login';
import { schema } from '../../helpers/validations/login';
import { store } from '../../store';
import { Wrapper, StyledLink, Form, StyledTypography, StyledBox, StyledContainer } from './styles';
import StatusMessage from '../../helpers/statusMessages/loginMessage';
import Copyright from '../../components/copyright/copyright';
import CustomButton from '../../components/button/button';
import SignInResponse from '../../graphql/responses/login';

Javascript how to export modules inside groups

I´ve several React components as a library in folder ux (some itens below):
import MessageBar from "./atoms/MessageBar/MessageBar";
import Spinner from "./atoms/Spinner/Spinner";
import Button from "./atoms/Button/Button";
import AccordionHeader from "./molecules/AccordionHeader/AccordionHeader";
import AutocompleteList from "./molecules/AutocompleteList/AutocompleteList";
import ButtonGroup from "./molecules/ButtonGroup/ButtonGroup";
import LoginPanel from "./organisms/LoginPanel/LoginPanel";
import WelcomePanel from "./organisms/WelcomePanel/WelcomePanel";
I wish to export these objects so that it can be imported from its group:
import LoginPanel from "ux.organisms";
Or
import Button from "ux/atoms";
Or whatever.
The idea is that you are getting the element from an specific group inside ux library.
What is the suggested way to export all of those components, organized into groups (atoms, molecules, organisms, etc.) ?
PS:
a. I don´t wnat to change the component name (ButtomAtom, etc...)
b. The result will be a npm library to be imported by other projects. So, this code will reside on my ux/index.js file.
Then make a index.js file at ux/atoms/ and fill it with:
import MessageBar from "./MessageBar/MessageBar";
import Spinner from "./Spinner/Spinner";
import Button from "./Button/Button";
//...
export { MessageBar, Spinner, Button };
So now one can do:
import { MessageBar } from "ux/atoms";
Or if you need every submodule:
import * as Atoms from "ux/atoms";

Webpack resolve a directory for import paths (goCardless as a boiletplate)

Currently a typical component will look like the below code. Note that using the paths to the file has become problematic and ugly. Moving a file causes massive issues with updating paths across multiple components.
This truly takes away from the component based experience when a path change can break everything and cause mass find and replace of paths.
In an ideal world the displayName would be the import reference and searched for within the directory.
'use strict';
//libs
import React from 'react';
//components
import TopFeatures from '../../headphones/subcomponents/top-features';
import Prices from './prices';
import Image from '../../layout/image';
import InlineRatingElement from '../../reviews/rating';
//helpers
import { getImageUrl } from '../../helpers/app/image';
import { initiateInlineRatings } from '../../helpers/app/inline-ratings';
export default class HDOverview extends React.Component {
displayName = 'HDOverview'
static propTypes = {
vendor: React.PropTypes.string.isRequired
}
constructor(props) {
super(props);
}
render() {
return (
<div>
JSX
</div>
);
}
}
I am looking to do something like this:
import TopFeatures from 'TopFeatures';//TopFeatures is the displayName
import Prices from 'Prices'; //Prices is the displayName etc.
import Image from 'Image';
import InlineRatingElement from 'InlineRatingElement';
//helpers
import { getImageUrl } from 'ImageHelper';
import { initiateInlineRatings } from 'InlineRatingHelper';
Webpack has a great tutorial on resolve aliases here: http://xabikos.com/javascript%20module%20bundler/javascript%20dependencies%20management/2015/10/03/webpack-aliases-and-relative-paths.html
However this insinuates that the path to the component would need to be logged in one place - in an ideal world there would be a way to dynamically check paths / directories to find the displayName that matches. Note that we have 200 components, so manually creating that list is do-able but sizable.
Having looked around I have seen people using
require("components!/layout/image")
however we would like to stick to the import technique and not go back to require.
Any suggestions or advice are greatly appreciated.
I think that this is, unfortunately, a limitation of node, npm.
There are workarounds to get absolute/mapped paths to work in npm but all of these have drawbacks: https://gist.github.com/branneman/8048520
Another option is individual npm packages for each component, but this adds a lot of overhead.

Categories