Use babel to remove ES6 Class no-use properties when bundle your code

frustigor

frustigor

Posted on December 6, 2019

Use babel to remove ES6 Class no-use properties when bundle your code

In some situation, when we bundle our code, we find some properties of a class are not needed in our project. For example, we wrote a class:

export default class A {
  a = 1
  static b = 2
  c() {}
  static d() {}
  e() {
    return false
  }
}

And we use it in our project like:

import A from './a'

const a = new A()
a.e()

We did not invoke a b c d of class A, but now, we have no idea to shake this methods/properties away from our code. Even through we have tree shaking, the tool like webpack has no idea to shake this no-use properties, it does not know which properties are used, and which are not.

After searching for ways to remove no-use properties, I did not find any good plugins or tools, so I have to write one, and published it as name babel-plugin-shake-class-properties and you can use it very easy.

npm i -D babel-plugin-shake-class-properties

And then modify your babel.config.js. (We only support babel.config.js because we need to point out the file's absolute path.)

// babel.config.js
const path = require('path')

module.exports = {
  ...
  plugins: [
    ['babel-plugin-shake-class-properties', {
      // the only properties we want to keep, other properties will be removed (except constructor)
      retain: [
        {
          file: path.resolve(__dirname, 'node_modules/tyshemo/src/store.js'), // the file's absolute path to match
          class: 'Store', // the class name from which properties will be removed
          properties: ['update', 'set'], // the properties which will be kept
        },
      ],
      // the properties we want to remove, properties even in `retain` will be removed
      remove: [
        {
          file: path.resolve(__dirname, 'node_modules/tyshemo/src/store.js'),
          class: 'Store',
          properties: ['update', 'set'], // the properties which will be removed
        },
      ],
    }],
    ...
  ],
}

In a item string of properties, you can use static async get set * keywords to match certain properties, for example:

class A {
  static a = 1
  get name() {}
  set name() {}
  * f() {}
  async fetch() {}
  async * r() {}
  static async * p() {}
  static get e() {}
}

If you want to remove all properties, aha?? you should use retain with properties: [''], however, to match strict, you could do like:

remove: {
  ...
  properties: [
    'static a',
    'get name',
    'set name',
    '* f',
    'async fetch',
    'async * r',
    'static async * p',
    'static get e',
  ],
}

Notice here, there should must be a space ' ' between * and the name of property.

Only ES6+ source class properties will be matched. The following situation will not work with this plugin. Computed properties will not work as possible:

class A {
  // will never be remove
  constructor() {
    // will not be realized
    this.a = '1'
  }

  // will not be realized
  [`some${a}`]() {}

  // will not be realized
  [Symbol('xxx')]() {}

  // will be treated as dd
  'dd'() {}

  // will be treated as ["dd"]
  ['dd']() {}

  // will be treated as [dd]
  [dd]() {}

  // will be treated as [dd]
  [dd] = 1

  // will be treated as ["dd"]
  ['dd'] = 1
}

function B() {}

// will not be realized
B.prototype.a = function() {}

// will not be realized
// you can use https://github.com/tangshuang/babel-plugin-transform-class-remove-static-properties to remove this
B.b = 'xxx'

If you are interested in this project, follow it on github https://github.com/tangshuang/babel-plugin-shake-class-properties and give a star.

💖 💪 🙅 🚩
frustigor
frustigor

Posted on December 6, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related