Gain from importing component by component from a UI library?

I currently have a ton of imports at the top of files like

import { Card, CardTitle } from 'material-ui/Card';
import MenuItem from 'material-ui/MenuItem';

Is there a gain from doing this? Is there a penalty for just doing this:

import { Card, CardTitle, MenuItem } from 'material-ui';

I don’t “know” the answer to your question, but it piqued my interest because I’m currently working on enhancing the import-js package to better support Meteor applications. import-js is a package with editor plugins that can automatically add the import statements to a module that are necessary to resolve unresolved variables.

This also piqued my interest because of its support for referencing material-ui/Card instead of material-ui. I just went and looked at how they implemented it.

Their implementation disturbs me because there is nothing to explicitly tell a build tool or a tool like import-js to know that the index.js files in the subdirectories are designed to support direct import. That isn’t surprising though because npm does not offer anything to directly support this. The totality of npm’s support for describing a package’s interface is the “main” specification which in the material-ui/package.json file is currently pointing to the index.js in the root. Meteor’s package.js is worlds ahead of npm in the subject area of explicit package interface definition.

But none of that answers your question.

I believe that the answer would depend on the build system used.

In the best case, the build system will go from your imports and ignore the implications of the material-ui/package.json file and the main index.js it points to. In that case, importing directly from the component will likely result in eliminating the code from unused components. I checked out the index.js files in the component directories, and they are carefully written to pull in only what is necessary for that component.

In the worst case, the build system is going to find the package.js and pull in all components regardless of which method you use to import. I can argue that the build system should always do that because there could be components that aren’t directly used but have important side-effects as well as important package initialization code within the package’s main index.js. The best case scenario above is actually relying on the publisher to be explicitly importing side-effect components in the component indexes without any clue as to whether the package has been designed for this or a package consumer is misusing the package’s interface.

In any case, I’d advise building both ways and looking at what Meteor sends to the browser.

I can tell you that I can’t imagine the automatic importing package I’m collaborating on to ever automatically utilize the component-by-component import method in this case (though we do provide means to manually spec that it should be used). There simply isn’t enough explicit definition in npm’s interface to do this. Painful or not, publishers of packages like this should be breaking them up so that every component has its own package and also offering an alternative package for those who just want to pull it all in.

npm does have a little explicit support for this package-per-component organization in the form of the npm scope, but I don’t see a lot of advantage to publishers using it. It just gathers the components into a directory without providing support for things that might be desirable like a unified scope initialization at the higher level.