strothj / babel-plugin-react-docgen-typescript

Babel Plugin to generate docgen data from React components written in TypeScript.
12 stars 4 forks source link

Performance: Re-use TS Program #17

Open petermikitsh opened 4 years ago

petermikitsh commented 4 years ago

As the number of React components in my project grew, I noticed a performance issue similar to what is discussed in https://github.com/styleguidist/react-docgen-typescript/issues/112: Creating a new Typescript program (ts.createProgram) when transforming each file is expensive.

I loosely adapted https://github.com/strothj/babel-plugin-react-docgen-typescript/blob/0b72d214444bf7a48ec22637654c5bee0eaad26f/src/index.ts to re-use the TypeScript program, and got big perf gains.

It might be possible to adapt this babel plugin. Hope this info could be helpful.

./docgen.js ```js const rdt = require('react-docgen-typescript'); const template = require('@babel/template'); const ts = require('typescript'); const glob = require('glob'); const util = require('util'); const files = glob.sync('src/**/*.{ts,tsx}', { absolute: true }); const program = ts.createProgram(files, {}); module.exports = function() { return { pre() { this.fileProcessed = false; }, visitor: { Program(path, state) { if (this.fileProcessed) { return; } this.fileProcessed = true; const { filename } = state.file.opts; if (files.indexOf(filename) === -1) { files.push(file); program = ts.createProgram(files, {}); } const docs = rdt .withCompilerOptions({}, { shouldExtractLiteralValuesFromEnum: true }) .parseWithProgramProvider(filename, () => program); docs.forEach((doc) => { path.node.body.push( template.default.ast(` try { ${doc.displayName}.__docgenInfo = ${util.inspect( doc, null, 10, )}; } catch (e) {} `), ); }); }, }, }; }; ```
babel.config.js ```js const useESM = process.env.ESM === '1'; module.exports = function(api) { api.cache(true); return { presets: [ '@babel/preset-typescript', ['@babel/preset-env', { modules: useESM ? false : 'commonjs' }], ], plugins: [ '@babel/plugin-transform-react-jsx', './docgen', '@babel/plugin-transform-runtime', ], }; }; ```
$ time npm run build:esm

> ESM=1 babel src --source-maps --out-dir dist/esm --extensions .ts,.tsx

Successfully compiled 38 files with Babel.

real    0m5.006s
user    0m7.779s
sys 0m0.538s

Before, it was about 40 seconds. Nearly a full order of magnitude improved.

strothj commented 4 years ago

Sorry for the delay. I'll be looking for someone to take this over as maintainer since my work has taken me away from Storybook related things.

With that said, this should be possible.