-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for __PURE__ annotations on tagged template literals #4035
Comments
As this syntax is originally adapted from terser/uglifyjs, Rollup is trying to stick to their behaviour. Trying this in their REPL, it seems they do not support this for tagged template literals. I wonder if there is a deeper reason, maybe someone from their side can shed some light, e.g. @fabiosantoscode? |
I already opened an issue with terser: terser/terser#975 |
Hello! This is a touchy subject especially when keeping compatibility with UglifyJS. /*#__PURE__*/ makeMacro`some code`("arg for some code")
/*#__PURE__*/ makeMacro("some thing")`Hello` You can have two tools remove different parts of the code here. My alternative ideaCreate a new annotation /*#__PURE__*/ ( /*#__PURETPL__*/ makeMacro`some code` )("arg for some code")
/*#__PURETPL__*/ ( /*#__PURE__*/ makeMacro("some thing") )`Hello` Interested to hear what @kzc and @alexlamsl have to say on this, not only because they know more about annotations than me, but also because ideally this is also implemented in UglifyJS. Side note:If you'd like to mark any expression entirely pure, you can use this awkward workaround: /*#__PURE__*/ (() => template`string`)() |
Related discussion: mishoo/UglifyJS#4763 (comment) I think a new pure annotation with a different spelling for each purpose would be confusing. The main concern is an ambiguous pure annotation where the tag is a function call itself: /*@__PURE__*/foo.bar(effect1())`baz ${effect2()}`, moo(); By the original uglify-js pure annotation rules, all this code would be retained since the annotation applies to The question is whether a non-backwards compatible change should be made to transform the code fragment above to:
Under this proposal the side effects in the tag would be dropped completely - as is the case with the function expression in a pure annotated function call under the original rules. Likewise, the side effects in the template component would be retained - just as function parameter side effects are retained in the original pure annotation rules. However, retaining the side effects in the template part of the tagged template may be unexpected and possibly undesirable. A pure annotated IIFE, although awkward, does not have these issues. Rather than extending I'm afraid that we will not reach consensus on this matter. This has all been hashed over before. But the status quo is not necessarily a bad thing. The awkward pure anotated IIFEs can readily be reduced away by optimizing minfiers and bundlers. |
It's useful for css-in-js library. It's important to tree-shaking unused tagged template. for example // 'common-style' module
import { css } from 'emotion'
export const ShadowColor = 'rgba(0,0,0,.2)'
export const BorderColor = 'blue'
export const LightShadowStyle = css`box-shadow: ${ShadowColor}`
export const BorderStyle = css`border: ${BorderColor}`
// index.ts
import { LightShadowStyle } from 'common-style'
ReactDOM.render(<div css={LightShadowStyle}/>, document.body) Expected: |
Hi, @lukastaegert @fabiosantoscode The obvious reason that Uglify not supporting PURE for tagged template call, is that, Uglify is a very old libary, which not intend to support es6... Tagged template call is completely a syntax sugar for function call: f`${effect()}`; // completely equal to f([ ... ], effect()) Uglify also not support If we too care about "compatibility", then any new design will be not "compatibility", because maybe some user in some world, they write If we really care about "compatibility", I think the best way may be something like So it's amazing for rollup and terser authors to confuse about this question... Am I right? One opinion more, I think in this matter, the responsibility of bundler is bigger than minifier. Because almost no one nowadays use minifier without after bundling step, minifier's tree shaking can almost do nothing left, after all, we cann't minify |
uglify-js now supports ES2020+. rollup and esbuild were both tested against uglify-js' test cases.
This is insulting. Minify tool authors are very familiar with bundling and its impact on minification. Indeed, I first implemented pure annotations in uglify-js to accommodate webpack and browserify.
There's no haziness about the current semantics of pure annotations. uglify-js and its forks wouldn't perform that optimization because it would likely be less efficient making multiple calls instead of using the variable set to the return value of Using comments to annotate code is not ideal because they are not first class citizens in ECMAScript as they are considered whitespace and do not survive code transformations (or even parentheses) very well in third party tools. I recommend to not alter the semantics of |
Thanks for your responses to follow up this issuse!
Emmm... Isn't "tagged call" a "call"? Making If uglify supports es6 now, and its |
But worry about backwards compatible still make sense in the real world, let's discuss about the detials:
By the original rule, the If it's really a problem which block the process, then maybe we can go ahead to support /*#__PURE__*/fn``; // shaked
/*#__PURE__*/mod.fn``; // also shaked
/*#__PURE__*/fn()``; // keep the orignal rule to preserve, until there is a consensus, use below currently:
/*#__PURE__*/( fn() )``; // shaked -- really better enough than /*#__PURE__*/( () => fn()`` )(); because there could be hundreds of samples in front end project... I think this won't be dangrous? And these helps most use cases easier. |
FYI this method works fine with Rollup |
Feature Use Case
https://rollupjs.org/repl/?version=2.44.0&shareable=JTdCJTIybW9kdWxlcyUyMiUzQSU1QiU3QiUyMm5hbWUlMjIlM0ElMjJtYWluLmpzJTIyJTJDJTIyY29kZSUyMiUzQSUyMmltcG9ydCUyMCU3QiUyMGElMjAlN0QlMjBmcm9tJTIwJTVDJTIyLiUyRmxpdCU1QyUyMiU1Q25jb25zb2xlLmxvZyhhKSUyMiUyQyUyMmlzRW50cnklMjIlM0F0cnVlJTdEJTJDJTdCJTIybmFtZSUyMiUzQSUyMmxpdC5qcyUyMiUyQyUyMmNvZGUlMjIlM0ElMjJmdW5jdGlvbiUyMGdxbChzdHJpbmdzJTJDJTIwLi4udmFsdWVzKSUyMCU3QiU1Q24lMjAlMjByZXR1cm4lMjBzdHJpbmdzLmZsYXRNYXAoKHMlMkMlMjBpKSUyMCUzRCUzRSUyMCU1QnMlMkMlMjB2YWx1ZXMlNUJpJTVEJTVEKS5qb2luKCcnKSU1Q24lN0QlNUNuJTVDbmV4cG9ydCUyMGNvbnN0JTIwYSUyMCUzRCUyMCUyRiolMjNfX1BVUkVfXyolMkYlMjBncWwlNjBhJTYwJTVDbmV4cG9ydCUyMGNvbnN0JTIwYiUyMCUzRCUyMCUyRiolMjNfX1BVUkVfXyolMkYlMjBncWwlNjBiJTIwJTI0JTdCYSU3RCU2MCUyMiU3RCU1RCUyQyUyMm9wdGlvbnMlMjIlM0ElN0IlMjJmb3JtYXQlMjIlM0ElMjJlcyUyMiUyQyUyMm5hbWUlMjIlM0ElMjJteUJ1bmRsZSUyMiUyQyUyMmFtZCUyMiUzQSU3QiUyMmlkJTIyJTNBJTIyJTIyJTdEJTJDJTIyZ2xvYmFscyUyMiUzQSU3QiU3RCU3RCUyQyUyMmV4YW1wbGUlMjIlM0FudWxsJTdE
Feature Proposal
Just like the
/*# __PURE__ */
annotation works on function calls, it should work on tagged template literals as well. After all, a tagged template literal is basically just a function call.The text was updated successfully, but these errors were encountered: