minify icon indicating copy to clipboard operation
minify copied to clipboard

Remove unused imports

Open hiendv opened this issue 7 years ago • 14 comments

// Map won't be eliminated when bundling
import Map from 'lodash.map'

There are non-pure modules with side effects. Is there any way to remove the unused import regardless of side-effect. Possible related rollup feature Thank you.

hiendv avatar Jun 16 '17 03:06 hiendv

In my case, I have a lib.esm.js file where the Map is used by one of the sub-module

import Map from 'lodash.map'
class Foo {}
const Bar = {}
class Acme {
// Map is used here
}
export { Foo, Bar, Acme }

When importing Foo from lib.esm.js and bundling

import { Foo } from './lib.esm.js'
console.log(Foo)

The bundle contains Map

hiendv avatar Jun 16 '17 04:06 hiendv

I think this is currently out of scope for Babili - imported module can have side-effects for example -

// https://example.com/foo.js
function foo() {
  console.log("foo");
}

foo(); // side effect

export default foo;
// https://example.com/bar.js
import foo from "/foo.js";
// foo is unused

Also, babili doesn't understand ES6 modules and doesn't resolve them - probably will not any time soon - as the resolution depends on the context where the modules are used - NodeJS, browsers, bundlers(webpack, rollup, browserify) with custom resolvers.

boopathi avatar Jun 18 '17 18:06 boopathi

@boopathi You could remove the unused named exports (and then an empty {}), then remove the unused default export:

import foo, { bar, baz } from './quux'
import foo, {} from './quux'
import foo from './quux'
import './quux'

This way, you could shorten the imports without side effects.

j-f1 avatar Jun 18 '17 18:06 j-f1

Oh yeah. True. That is possible. Thanks.

This could also be a part of DCE before bundling - related - https://github.com/webpack-contrib/babili-webpack-plugin/issues/8

boopathi avatar Jun 18 '17 18:06 boopathi

@boopathi

Also, babili doesn't understand ES6 modules and doesn't resolve them

Okay, I thought babili is "an ES6+ aware minifier based on the Babel toolchain" and does some magics behind the scene to resolve them. I also understand modules may have side effects but wondering if we can leverage babili for features like rollup's. Possible related rollup feature @j-f1 Sorry, could you explain more? Especially in my case. Thanks.

hiendv avatar Jun 19 '17 02:06 hiendv

@hiendv I guess the difference is that tools like Babel/Babili are designed to operate either on single modules or the bundle as a whole; while tools like webpack or rollup take single modules and turn them into a bundle.

For example, how would Babili parse these statements?

import foo from 'bar'
// This could be any path — many bundlers let you choose how to resolve these

import foo from 'super-duper-loader?./bar'
// What if webpack changes their syntax?
// What if `super-duper-loader` actually loads content from a different file?
// What if it loads `./bar.superscript`?

Although Babili can’t necessarily understand the contents of imported files, it can remove unused parts of the imports, from import foo, { bar, baz } from './quux' toimport './quux' where possible.

j-f1 avatar Jun 19 '17 10:06 j-f1

@j-f1 Thank you. So I guess the burden of pruning unused pure external imports should be on the bundler end, not babili.

hiendv avatar Jun 20 '17 03:06 hiendv

You could remove the unused named exports (and then an empty {}), then remove the unused default export:

import foo, { bar, baz } from './quux' import foo, {} from './quux' import foo from './quux' import './quux' This way, you could shorten the imports without side effects.

import foo where foo is unused is much the same as var foo where foo is unused, and ISTM that babili should handle both in the same way. But unused variables are a waste of space and developers should remove them from their code anyway. That's why we have linters to highlight the things :-)

probins avatar Jul 23 '17 08:07 probins

@probins You may want to read my comment for the scenario.

hiendv avatar Jul 24 '17 07:07 hiendv

This would be a great feature, you could only check if import is used or if export binds to a declared syntax, then remove when unused. You don't need to care about file location.

Alphapage avatar Aug 21 '17 08:08 Alphapage

Did you find a solution for this ?

abumalick avatar Sep 24 '18 15:09 abumalick

The feature should go in minify-dead-code-elimination right? And it should never remove and import entirely, it should only only removed unused symbols, shortening at most to import "path/to/file";.

Seems like it should be pretty easy to write.

conartist6 avatar May 27 '19 02:05 conartist6

Looks like the hardest part of supporting this is going to be figuring out how to make the tests. The current fixtures are all parsed as scripts, and scripts can't contain import or export keywords. So far I can't even figure out where the heck these fixture test cases are being searched for and loaded, let along how to configure whatever is loading and parsing them to treat some of them as modules.

conartist6 avatar May 27 '19 02:05 conartist6

Ah I figured it out. Utils is a lerna root, so test-runner is local code. It supports babel.json to set babel settings on the file. PR is up.

conartist6 avatar May 27 '19 15:05 conartist6