@@ -88,13 +88,13 @@ const external: rollup.ExternalOption = (source) => {
8888 return externals . some ( external => source === external || source . startsWith ( `${ external } /` ) )
8989}
9090
91- export default ( args : Record < string , string > ) : rollup . RollupOptions => {
91+ export default ( args : Record < string , string > ) : rollup . RollupOptions [ ] => {
9292 const vscodeVersion = args [ 'vscode-version' ]
9393 delete args [ 'vscode-version' ]
9494 if ( vscodeVersion == null ) {
9595 throw new Error ( 'Vscode version is mandatory' )
9696 }
97- return rollup . defineConfig ( {
97+ return rollup . defineConfig ( [ {
9898 cache : false ,
9999 treeshake : {
100100 annotations : true ,
@@ -303,17 +303,85 @@ export default (args: Record<string, string>): rollup.RollupOptions => {
303303 right : ').then(module => module.default ?? module)'
304304 }
305305 }
306- } , {
307- name : 'cleanup' ,
308- renderChunk ( code ) {
309- return cleanup ( code , null , {
310- comments : 'none' ,
311- sourcemap : false
312- } ) . code
313- }
314306 }
315307 ]
316- } )
308+ } , {
309+ // 2nd pass to improve treeshaking
310+ cache : false ,
311+ treeshake : {
312+ annotations : true ,
313+ preset : 'smallest' ,
314+ propertyReadSideEffects : false ,
315+ moduleSideEffects ( id ) {
316+ return id . startsWith ( SRC_DIR ) || id . endsWith ( '.css' )
317+ }
318+ } ,
319+ external,
320+ input : Object . values ( input ) . map ( f => `./dist/${ path . basename ( f , '.ts' ) } ` ) ,
321+ output : [ {
322+ format : 'esm' ,
323+ dir : 'dist' ,
324+ entryFileNames : '[name].js' ,
325+ chunkFileNames : '[name].js' ,
326+ hoistTransitiveImports : false
327+ } ] ,
328+ plugins : [ {
329+ name : 'improve-treeshaking' ,
330+ transform ( code ) {
331+ const ast = recast . parse ( code , {
332+ parser : require ( 'recast/parsers/babylon' )
333+ } )
334+ let transformed : boolean = false
335+ function addComment ( node : recast . types . namedTypes . NewExpression | recast . types . namedTypes . CallExpression ) {
336+ if ( ! ( node . comments ?? [ ] ) . some ( comment => comment . value === PURE_ANNO ) ) {
337+ transformed = true
338+ node . comments = [ recast . types . builders . commentBlock ( PURE_ANNO , true ) ]
339+ return recast . types . builders . parenthesizedExpression ( node )
340+ }
341+ return node
342+ }
343+ recast . visit ( ast . program . body , {
344+ visitCallExpression ( path ) {
345+ const node = path . node
346+ if ( node . callee . type === 'MemberExpression' ) {
347+ if ( node . callee . property . type === 'Identifier' ) {
348+ const name = getMemberExpressionPath ( node . callee )
349+ if ( ( name != null && PURE_FUNCTIONS . has ( name ) ) || PURE_FUNCTIONS . has ( node . callee . property . name ) ) {
350+ path . replace ( addComment ( node ) )
351+ }
352+ }
353+ } else if ( node . callee . type === 'Identifier' && PURE_FUNCTIONS . has ( node . callee . name ) ) {
354+ path . replace ( addComment ( node ) )
355+ } else if ( node . callee . type === 'FunctionExpression' ) {
356+ // Mark IIFE as pure, because typescript compile enums as IIFE
357+ path . replace ( addComment ( node ) )
358+ }
359+ this . traverse ( path )
360+ return undefined
361+ } ,
362+ visitThrowStatement ( ) {
363+ return false
364+ }
365+ } )
366+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
367+ if ( transformed ) {
368+ code = recast . print ( ast ) . code
369+ code = code . replace ( / \/ \* # _ _ P U R E _ _ \* \/ \s + / g, '/*#__PURE__*/ ' ) // Remove space after PURE comment
370+ }
371+ return code
372+ }
373+ } , nodeResolve ( {
374+ extensions : EXTENSIONS
375+ } ) , {
376+ name : 'cleanup' ,
377+ renderChunk ( code ) {
378+ return cleanup ( code , null , {
379+ comments : 'none' ,
380+ sourcemap : false
381+ } ) . code
382+ }
383+ } ]
384+ } ] )
317385}
318386
319387function resolve ( _path : string , fromPaths : string [ ] ) {
0 commit comments