-1

What is the difference between importing stuff from material-ui like this

import { Paper } from '@material-ui/core'

vs. like this, which works exactly the same way in my Webpack setup:

import Paper from '@material-ui/core/Paper'

Is any of these methods of importing, costly in terms of the resulting bundle size?

Note:

I am using this in a project that was bootstrapped with Create-React-App and the Create-Reac-App that I am using uses Webpack v3.5.1

Siya Mzam
  • 4,655
  • 1
  • 26
  • 44

3 Answers3

2

import { something } from 'test-m' implies that, test-m has a named export on it, i.e:

module.exports = { something: 'other string' }

or even, on the es6 syntax:

export const something = 'other string'

--

import something from 'test-m' => implies that test-m has a default exports, i.e:

module.exports = 'other string'

or with es6 syntax export default 'other string'

How this affects bundling? Well, named exports is the way to go. Why?

Named exports imports only what is necessary from each module, so by using named exports, bundlers can tree-shake the module and take out from that module only what is necessary. This process decreases by a lot the size of the final module. In comparison to default exports, bundlers would pull to the chunk the whole module, despite you using one or all features that module provides.

TL;TR: named exports === lower bundle size.

PlayMa256
  • 6,603
  • 2
  • 34
  • 54
  • Okay, cool. So are you saying that the first method that I have specified above would result in a smaller bundle? Also, between those two methods, would tree shaking (webpack v3) work ? – Siya Mzam Aug 07 '18 at 14:12
  • I wrote this on the answer. `so by using named exports, bundlers can tree-shake the module` – PlayMa256 Aug 07 '18 at 14:13
  • "So are you saying that the first method that I have specified above would result in a smaller bundle? " - yes – PlayMa256 Aug 07 '18 at 14:13
  • I am asking because I heard from my tech lead that tree shaking is not supported in v3 – Siya Mzam Aug 07 '18 at 14:14
  • 1
    Oh, it is... don't worry. – PlayMa256 Aug 07 '18 at 14:14
  • 1
    webpack >= 3 supports it. – PlayMa256 Aug 07 '18 at 14:14
  • 1
    One thing to note is that in the example of `Paper` you are not importing from the same module as in the example in this answer. In one case you are doing an import from '@material-ui/core' and in the other you are doing an import from '@material-ui/core/Paper'. Also, I would not say that the first way you specified will result in smaller bundle. The second one is also only importing the `Paper` export, since that's the default and only thing exported from '@material-ui/core/Paper'. This does not need tree-shaking at all, actually. – Andres Rojas Aug 08 '18 at 07:55
1

In the case of import { Paper } from '@material-ui/core' you are importing the Paper named export from @material-ui/core module which contains other named exports.

In the case of import Paper from '@material-ui/core/Paper' you are importing the default export from @material-ui/core/Paper module which contains only Paper and exports it as default.

Some libraries have this approach of exposing both the main script with named exports and the individual modules for each function. For instance, Lodash. You can do both import { find } from 'lodash' and import find from 'lodash/find'. In both cases you will get the same find function.

Regarding pros, depending on the bundler configuration and the modules system used by the library, this: import { Paper } from '@material-ui/core' may not be tree-shaked and you will end up with the whole '@material-ui/core' in your bundle.

This: import Paper from '@material-ui/core/Paper' for sure will always only add Paper to your bundled code.

Andres Rojas
  • 123
  • 7
0

The first import will import the default class export. Whereas the second import imports only the exported function/object. This is quite a common difference when importing for Jest tests in react.

Take an example of a redux connected component:

export class ReduxConnect {

  render(){
    return (<h1> Some component </h1>);
  }

}

export const mapStateToProps = state => ({
  something: state.something
});

export default connect(mapStateToProps)(ReduxConnect);

Doing import ReduxConnect will import the default import, defined at the bottom which exports the redux connected component. Whereas import {ReduxConnect, mapStateToProps} would give you the option to export objects/functions individually from the class. In this case the difference would be between importing the redux connected component vs the pure component itself.

Adam
  • 1,724
  • 13
  • 16
  • This doesn't answer the bundling question at all. – T.J. Crowder Aug 07 '18 at 13:51
  • He changed the question, when I answered it he didn't ask about that stuff and his question was very different actually. – Adam Aug 07 '18 at 13:57
  • No, [the very first version](https://stackoverflow.com/revisions/51728225/1) of this question ended with *"Is any of these methods of importing, costly in terms of the resulting bundle size?"* It was clearly the main thrust of the question. (Which is why I immediately commented asking what bundler he used [I've deleted that question since it was answered].) – T.J. Crowder Aug 07 '18 at 13:59