Skip to content
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

feat(es/minifier): Implement minifier #1302

Merged
merged 1,235 commits into from
May 20, 2021
Merged

feat(es/minifier): Implement minifier #1302

merged 1,235 commits into from
May 20, 2021

Conversation

kdy1
Copy link
Member

@kdy1 kdy1 commented Dec 30, 2020

Postponed

To simplify management, I'll merge this PR as incomplete state and implement more rules with follow-up PRs.

swc_bundler:

  • Add option for minification.

swc_ecma_minifier:

  • Implement.
  • Provide js api.

@kdy1 kdy1 self-assigned this Dec 30, 2020
@soilSpoon
Copy link
Contributor

Are you thinking of implementing it using UglifyJS?

@kdy1
Copy link
Member Author

kdy1 commented Dec 30, 2020

@soilSpoon Yes, but mainly because I don't know well about internals of minifiers.
Is there something better than uglifyjs?

Or I can add some passes after implementing it using uglifyjs.

@soilSpoon
Copy link
Contributor

soilSpoon commented Dec 30, 2020

uglifyjs doesn't seem to be able to minify ECMAScript 2015 or above. So, to use this, you need to use it after transpile it to ECMAScript 2015 or lower. I think this can adversely affect performance. So I look better to use terser that can minify ECMAScript 2015 or above.

It seems good to understand minify in the future and implement it yourself.

Reference

terser vs uglifyjs
Benchmarks
terser ESTree/SpiderMonkey AST

@kdy1
Copy link
Member Author

kdy1 commented Dec 30, 2020

@soilSpoon Oh. I got it. Thanks!
I'll port terser instead.

@divmain
Copy link

divmain commented Jan 2, 2021

You may also want to look at babel-minify for inspiration. From what I recall, it doesn't achieve quite the same size wins as Uglify or Terser. But the port may be significantly more straightforward - the minifier is split into discrete operations for the different types of transformations that it applies.

@probins probins mentioned this pull request Jan 4, 2021
4 tasks
@kdy1 kdy1 changed the title feat(ecmascript/minifier): Implement a javascript minifier feat(ㄸㄴ/minifier): Implement a javascript minifier Jan 13, 2021
@kdy1 kdy1 changed the title feat(ㄸㄴ/minifier): Implement a javascript minifier feat(ES/minifier): Implement a javascript minifier Jan 13, 2021
@kdy1 kdy1 changed the title feat(ES/minifier): Implement a javascript minifier feat(es/minifier): Implement a javascript minifier Jan 14, 2021
@kdy1 kdy1 force-pushed the minifier branch 3 times, most recently from 5ba891c to f12de1e Compare January 25, 2021 09:23
@kdy1 kdy1 changed the title feat(es/minifier): Implement a javascript minifier feat(es/minifier): Implement minifier partially Feb 1, 2021
@kdy1 kdy1 changed the title feat(es/minifier): Implement minifier partially feat(es/minifier): Implement minifier partially [Incomplete] Feb 1, 2021
@kdy1 kdy1 changed the title feat(es/minifier): Implement minifier partially [Incomplete] feat(es/minifier): Implement minifier Feb 1, 2021
/// throw x();
/// }
/// ```
pub(super) fn optimize_in_fn_termiation(&mut self, e: &mut Expr) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo

Suggested change
pub(super) fn optimize_in_fn_termiation(&mut self, e: &mut Expr) {
pub(super) fn optimize_in_fn_termination(&mut self, e: &mut Expr) {

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, thanks!

@fabiosantoscode
Copy link
Contributor

Hey, I maintain Terser, and it's helplessly slow. Recently I started a port to rust (in a very early stage) but I don't think it's useful to keep two separate projects that are essentially the same. How can I help?

@kdy1
Copy link
Member Author

kdy1 commented Mar 23, 2021

@fabiosantoscode I implemented many rules but there are many rules left.
If you don't mind implementing it as a part of swc, I will add lots of comment how the minifier works and about some design decisions.

Note that being in-tree would make version management much simpler, as bundler depends on minifier and minifier depends on ast / visitor while those crates live in a momorepo.

@fabiosantoscode
Copy link
Contributor

Ok, I'll go on your fork and send PRs when I have the time.

I'm interested in how to implement reduce_vars, unused, and inline, because in Terser they're kind of the same for speed reasons. They're also very relevant for tree shaking.

@Austaras
Copy link
Member

Any possible to expose as webpack plugin like terser

fabiosantoscode and others added 8 commits May 19, 2021 23:59
When developing the property mangler, I'd commented out the lines in this 'if' statement so I could run tests faster.

So I came up with this PR to enable us to filter tests when desired, and run them quickly, but also allow to run everything by omitting filter arguments.

If you have a better idea for testing quickly please let me know :) this is still pretty slow.
@kdy1 kdy1 marked this pull request as ready for review May 20, 2021 04:50
@kdy1 kdy1 merged commit c6b22c5 into swc-project:master May 20, 2021
@kdy1 kdy1 deleted the minifier branch May 20, 2021 04:51
@kdy1
Copy link
Member Author

kdy1 commented May 20, 2021

Eventually I'd like to test this against every single Terser test. Not all of them require exact output. Some of them run the resulting code using node's VM module and compare the result.

👍 That's also my goal.
Terser has strength in the output and I want to make minification faster without degrading output. (while migrating)

@SoloJiang
Copy link
Contributor

However, I see this PR had beed merged, but how can I try it out? At now, it only removes comment and space in my code.

@kdy1
Copy link
Member Author

kdy1 commented Jun 24, 2021

@SoloJiang It's not published yet because it's not done

@fabiosantoscode
Copy link
Contributor

So much excitement for this port, I love it 💖

I need to try to reduce my hours in my side gig so I can give this more attention.

There's some transforms Terser itself doesn't do that are feasible here (such as a dictionary for common immutable constants or cross-module intelligence used in combination with spack) that can reduce this port's output bytes to a point that makes it a viable alternative to Terser.

@kdy1
Copy link
Member Author

kdy1 commented Jun 27, 2021

I'm glad to hear that and thank you!

There's some transforms Terser itself doesn't do that are feasible here (such as a dictionary for common immutable constants or cross-module intelligence used in combination with spack) that can reduce this port's output bytes to a point that makes it a viable alternative to Terser.

Sounds interesting. I expect such cross-module transforms to reduce final output by a margin because libraries used a lot along with UI frameworks like react encourages such code.

@swc-project swc-project locked as resolved and limited conversation to collaborators Nov 9, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

Successfully merging this pull request may close these issues.

8 participants