Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Treeshaking does not work when excluding components #718

Open
BafS opened this issue Dec 6, 2021 · 6 comments
Open

Treeshaking does not work when excluding components #718

BafS opened this issue Dec 6, 2021 · 6 comments
Labels

Comments

@BafS
Copy link

BafS commented Dec 6, 2021

The documentation explains how to remove components (https://github.com/fingerprintjs/fingerprintjs/blob/master/docs/extending.md#extending-fingerprintjs) but unfortunately it doesn't seems to work well with treeshaking, the components stay in the compiled source.

It's possible to get the "sources" and whitelist components but the blobs are still not treeshaked. I tried with webpack 5.64 and rollup 2.42.

Example of what I had in mind:

import('@fingerprintjs/fingerprintjs').then(fp => {
  const sources = {
    audio: f.sources.audio, // I would expect to only have the audio component in the compiled source
  };
  const pp = fp.loadSources(fp.sources, {debug: true}, [])();

  pp.then(result => {
    console.log(result);
  });
}),

Another solution would be to be able to import every component individually (like import { audio } from '...'), threeshaking should work then.

Thanks in advance

@Valve
Copy link
Member

Valve commented Dec 6, 2021

@BafS thanks for submitting this issue, we'll take a deeper look and reply shortly

@Finesse Finesse added the backlog label Dec 7, 2021
@Finesse
Copy link
Member

Finesse commented Dec 7, 2021

Hi @BafS. The library is not designed to tree-shake individual entropy sources. We consider adding this feature in a future release, but we can't say when exactly and whether we'll do it.

At the moment the only option for you is modifying the library source code. Remove the entropy sources that you don't need or add exports for individual sources. Some ways to modify the library code:

  • Use patch-package to change the library's Node package on your computer (edit the node_modules/@fingerprintjs/fingerprintjs/dist/fp.esm.js file) and save the changes inside your project
  • Download the library JS script on your computer, change the code, and add the file to you version control system
  • Fork this repository, change the code and install your fork from GitHub

Please notice that you use an undocumented API (sources, loadSources). It may change in future versions without a warning, so be careful.

@BafS
Copy link
Author

BafS commented Dec 7, 2021

Thanks for your answer, another solution would be to clone the repository and import the needed typescript modules directly which is maybe the easiest to be sync with the library.

@BafS
Copy link
Author

BafS commented Dec 7, 2021

If it can help anyone, I finally achieve it by doing a babel plugin to visit the AST and remove the nodes I don't need.

For example, in your webpack.common.js:

/**
 * @param {string[]} functionsToRemove
 */
const removeFunctions = (functionsToRemove) => () => ({
  visitor: {
    /** @param {import('@babel/core').NodePath} path */
    Identifier(path) {
      // Remove the functions from "sources"
      // https://github.com/fingerprintjs/fingerprintjs/blob/master/src/sources/index.ts
      if (path.node.name === 'sources' && path.parent.type === 'VariableDeclarator') {
        path.parent.init.properties.forEach((p, i) => {
          if (functionsToRemove.includes(p.value.name)) {
            path.parent.init.properties.splice(i, 1)
          }
        })
      }
    },
    /** @param {import('@babel/core').NodePath} path */
    FunctionDeclaration(path) {
      // Remove the function
      if (functionsToRemove.includes(path.node.id.name)) {
        path.remove();
      }
    },
  },
});

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /fp.esm.js$/,
        include: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            plugins: [removeFunctions(['getAudioFingerprint', 'startRenderingAudio'])],
          }
        },
      },
    ],
  },
  // ...
}

Use at your own risks

@Finesse
Copy link
Member

Finesse commented Mar 25, 2022

A related discussion: #757

@Finesse
Copy link
Member

Finesse commented Sep 12, 2022

A related discussion: #815

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants