Output tree-shakeable friendly classes when compiling ES5
See original GitHub issueWhat happens and why it is wrong
I’ve been investigating why one of my React Typescript component libraries doesn’t treeshake nicely. An important fact is that I’m outputting ES5 target.
The cause I’ve come down to is because terser works best with es2015 modules and defaults to a more safe output. Since ES5 doesn’t have import/export type situations it’s hard terser to know what is safe to strip out. However with typescript I think there is a solution and I ran into it here specifically this custom plugin:
plugins: [
resolve({ jsnext: true, module: true }),
{
transform(code, id) {
return code.replace(/\/\*\* @class \*\//g, "\/*@__PURE__*\/");
}
},
uglify(uglify_options),
],
When typescript compiles, it adds a /** @class */
comment in front of every class object it transpiles. Simply replacing this class comment with Terser’s __PURE__
comment allows Terser to know it can tree shake these objects.
I further checked to make sure if prop-types is being used it wont remove the function. For example the following would be tree-shaked
export class Example1Component extends React.Component {
render() {
return 'hello1';
}
}
but the following would not due to it having possible unintended consequences
export class Example1Component extends React.Component {
render() {
return 'hello1';
}
}
Example1Component.defaultValues = {
wheee: 123,
};
So the ask here is that rollup-plugin-typescript2 does the replacement of /** @class */
to /*@__PURE__*/
so that the ES5 outputs would be tree-shaken down stream.
Environment
N/A
Versions
- typescript: 3.6.4
- rollup: 1.23.1
- rollup-plugin-typescript2: 0.24.3
rollup.config.js
import pkg from './package.json';
import typescript from 'rollup-plugin-typescript2';
export default {
external: [...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {})],
input: 'src/index.ts',
output: [
{
file: pkg.main,
format: 'cjs',
},
{
file: pkg.module,
format: 'es',
},
],
plugins: [
typescript({ tsconfig: 'tsconfig.json' }),
],
};
tsconfig.json
{
"compilerOptions": {
"declaration": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"lib": ["es5"],
"module": "es2015",
"moduleResolution": "node",
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noUnusedLocals": false,
"outDir": "./dist/",
"sourceMap": true,
"strictNullChecks": true,
"target": "es5"
},
"exclude": ["./src/**/*.test.ts", "./src/**/*.test.tsx", "./test/**/*.ts", "./test/**/*.tsx"],
"include": ["./src/**/*.ts", "./src/**/*.tsx", "src/index.ts"]
}
package.json
Only relevant part is my build script
rollup -c rollup.config.js
plugin output with verbosity 3
N/A
Issue Analytics
- State:
- Created 4 years ago
- Comments:6 (1 by maintainers)
Top GitHub Comments
This looks like something a separate plugin should do, either rollup plugin like you had, or a typescript transformer. I’d rather not modify typescript output for everybody, too many possible unintended consequences.
Sigh, I hate replying when I know people are going to thumbs down it. Here are the changes I made to get this to work:
out
tooutDir
.Again, not the answer a rollup repository is going to want to hear, however it did remove a ton of dependencies and complications for me which actually made maintenance easier.