We want to make sure that we allow tree-shaking, or at least that we don't make the situation actively worse.
We have the bundle reports from Codecov which is something but it reports on the library size, which isn't entirely relevant if the app bundler will tree-shake it all later.
Here is a proof of concept script that I made:
import path from 'node:path';
import fs from 'node:fs';
import { rollup } from 'rollup';
import virtual from '@rollup/plugin-virtual';
import { createRequire, findPackageJSON } from 'node:module';
const require = createRequire(import.meta.url);
const { ProjectDocReader } = require('../omnidoc/readProject') as typeof import('../omnidoc/readProject');
const packageJsonFilePath = findPackageJSON(import.meta.url);
const es6Entry = path.join(path.dirname(packageJsonFilePath), 'es6', 'index.js');
const packageJsonContent = JSON.parse(fs.readFileSync(packageJsonFilePath, 'utf8'));
const dependencies = Object.keys(packageJsonContent.dependencies);
const peerDependencies = Object.keys(packageJsonContent.peerDependencies);
const specialDependencies = [/^victory-vendor.*/, /^es-toolkit.*/, 'use-sync-external-store/shim/with-selector'];
const allDependencies = [...dependencies, ...peerDependencies, ...specialDependencies];
async function treeshake(entry: string | string[], used: boolean = true) {
const entries = Array.isArray(entry) ? entry : [entry];
const importList = entries.join(', ');
const source = used
? `import { ${importList} } from '${es6Entry}';\nexport const used = { ${importList} };\n`
: `import { ${importList} } from '${es6Entry}';\n`;
const bundle = await rollup({
input: 'entry',
external: allDependencies,
plugins: [
virtual({
entry: source,
}),
],
treeshake: {
moduleSideEffects: false,
},
});
const output = await bundle.generate({
format: 'esm',
});
return output.output;
}
// usage on all exports
new ProjectDocReader().getAllRuntimeExportedNames().forEach(name => {
treeshake(name, false).then(output => {
const hasCode = output.some(chunkOrAsset => {
if (chunkOrAsset.type === 'chunk') {
return chunkOrAsset.code.trim() !== '';
} else {
return chunkOrAsset.source.trim() !== '';
}
});
console.log(`${name}: ${hasCode ? 'used' : 'unused'}`);
});
});
// usage on single export
treeshake('Line').then(output => {
for (const chunkOrAsset of output) {
if (chunkOrAsset.type === 'chunk') {
console.log(`Chunk: ${chunkOrAsset.fileName}`);
console.log(chunkOrAsset.code);
} else {
console.log(`Asset: ${chunkOrAsset.fileName}`);
console.log(chunkOrAsset.source);
}
}
});
Iterate on this script.
What we want to achieve is:
- Have a script where we can input a list of components, and it will output bundle size, and list of components that are present in the output
- Use this script to generate several bundles: one for all cartesian components, one for all polar components, and then one bundle for Treemap, Sunburts, Sankey. Report the bundle sizes using
scripts/upload-bundle-analysis.js.
- Add a test suite that runs this script for each component, and flags all components with insufficient tree-shaking. The idea is that importing one component should never pull out more components than asked for. There are some pre-existing problems in the library; we expect this test suite to show some failures.
We want to make sure that we allow tree-shaking, or at least that we don't make the situation actively worse.
We have the bundle reports from Codecov which is something but it reports on the library size, which isn't entirely relevant if the app bundler will tree-shake it all later.
Here is a proof of concept script that I made:
Iterate on this script.
What we want to achieve is:
scripts/upload-bundle-analysis.js.