Skip to content
This repository has been archived by the owner on Apr 9, 2022. It is now read-only.

@angular-devkit/build-optimizer purify marks PURE on namespace for packages built by cli #934

Closed
shlomiassaf opened this issue May 17, 2018 · 2 comments

Comments

@shlomiassaf
Copy link

shlomiassaf commented May 17, 2018

Bug Report or Feature Request (mark with an x)

- [x] bug report -> please search issues before submitting
- [ ] feature request

Area

- [x] devkit
- [ ] schematics

Versions

node 9.10.1

In @angular-devkit/build-optimizer the Purify transformation marks a namespace as PURE when it's coming from a library built by the cli.

Consider the following file in a library built with the cli :

export function MyFunction() { }

export namespace MyFunction {
    export function subFunction() { }
}

After publishing to NPM, the FESM5 bundle will look something like this:

function MyFunction() { }

(function (MyFunction) {
    function subFunction() { }
    MyFunction.subFunction = subFunction;
})(MyFunction || (MyFunctionn = {}));

export { MyFunction }

If we use this package in an angular application and build to prod the purify loader kicks in and the namespace implementation is treated as PURE:

```js
function MyFunction() { }

/*@__PURE__*/ (function (MyFunction) {
    function subFunction() { }
    MyFunction.subFunction = subFunction;
})(MyFunction || (MyFunctionn = {}));

export { MyFunction }

Even if MyFunction.subFunction is used within the application it is removed by uglify the compilation result is that MyFunction exists but MyFunction.subFunction does not.

That PURE is added by the getPrefixFunctionsTransformer transformer which thinks it's a function. I guess that there's not enough information as it deals with JS files and not TS.

If MyFunction is used it will not get dropped, and since it is user in the next instruction as an input to the IIFE it probably means that the IIFE is used and should not be dropped.

Of course I can mark this file and other with the same structure as sideEffect in package.json but because it's FESM bundle it will skip the entire package... not just parts of it.

I don't know maybe it's not even an issue, this is hard to grasp.

@shlomiassaf
Copy link
Author

shlomiassaf commented May 20, 2018

@filipesilva The above is an issue but I think the problem might actually be broader...

When marking sideEffects in webpack, one can mark the whole package but also specific files in the package.

With ng-packagr this is not an option because all output files are bundles (UMD/EDM/FESM).

Maybe the solution is to set a special token for purify that will instruct it not to mark the next instruction as PURE no matter what.

This can be a module level token, function level, maybe both...

Once this is set inangular-devkit/build-optimizer, ng-packger can take place and read the package.json of the library and auto-add this to every module.

@clydin
Copy link
Member

clydin commented May 22, 2018

The build optimizer can be corrected to not mark downlevel namespace structures with the pure annotation. However, doing so still leaves the problem that webpack itself will still consider the module as side effect free which could potentially cause webpack to errantly optimize the module. The core of the problem is that downlevel namespaces in the above form are side effects by definition and therefore usage of them prevents the module from being marked with sideEffects: false.

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

No branches or pull requests

3 participants