rails / importmap-rails

Use ESM with importmap to manage modern JavaScript in Rails without transpiling or bundling.
MIT License
1.07k stars 120 forks source link

Asset precompilation is broken when using uglifier #5

Closed MrBananaLord closed 3 years ago

MrBananaLord commented 3 years ago

I have tried to use Uglifier in harmony mode and one of the es-shims dependencies (es-module-lexer) is breaking the asset precompilation. It's working when using Terser.

I hope to have it fixed with https://github.com/guybedford/es-module-lexer/pull/84 but for now Terser seem to be the solution :)

dhh commented 3 years ago

I'm not a big fan of uglifying since it makes it harder for others to learn via view source, but thanks for taking a look none the less! ✌️

tleish commented 3 years ago

From my perspective, uglifying is not about obfuscating the code so other can't learn from it. It's about faster download speeds for 99% of your users. For example:

react.js

Even with HTTP2 asynchronous downloads, many browsers have limited bandwidth to download all the modules quickly.

Then for the 1% interested in learning from the sourcecode, use sourcemaps if they want to download the extra data to their browser. Why make 99% of your users download the larger version so the 1% can see the source code easier?

dhh commented 3 years ago

A) Use brotli and the difference shrinks. B) Reference libs that have already been minified if you like. C) Don’t sweat 10kb when you probably have a hero image that takes up 5x that somewhere. D) Use a JS build pipeline if you must squeeze out every kb (but then also, don’t use SPA! 😄)

tleish commented 3 years ago

We actually use the hotwired stack (love it btw). Just used react.js as an example. In one of our application we have 30+ stimulus controllers. Individually they are small, but collectively they are large and want them both minified and compressed.

dhh commented 3 years ago

Curious how large those 30 stimulus controllers are? Surprised that’s a problem. We are about to launch HEY on import maps, unminifined, and we have about 130 controllers. Tiny difference of the whole load picture.

dhh commented 3 years ago

But clearly your priorities can be different. If you’re optimizing for rural areas on 3G or developing countries with very low data cap limits, then it’s a different story. You should definitely use a bundler approach then. But for 99% of the popular sites, that’s clearly not their optimization target. Gmail loads 3mb of JS for Christ sake and is used by billions 😄. Sweating 10-20kb for a far more complicated dev stack doesn’t make sense to me.

dhh commented 3 years ago

Alternatively, you can use a minifying CDN: https://support.cloudflare.com/hc/en-us/articles/200168196-How-do-I-minify-HTML-CSS-and-JavaScript-to-optimize-my-site-

tleish commented 3 years ago

We are about to launch HEY on import maps, unminifined, and we have about 130 controllers.

I've heard you talk about hey.com javascript assets being 40 to 60k. I'm curious to see what 1) the overall payload will change to and 2) how it might impact download over http2 on slower connections.

If you’re optimizing for rural areas on 3G or developing countries with very low data cap limits, then it’s a different story.

Slow mobile connections occur in 1st world countries for multiple reasons (building interference, full mobile cache, background apps taking up bandwidth, etc)

Sweating 10-20kb for a far more complicated dev stack doesn’t make sense to me.

Yeah, I'm a bit of a speed enthusiast. I feel impatient with slow sites that have MB of javascript.

Alternatively, you can use a minifying CDN

I didn't know about CDN minifying, thanks for the tip.

dhh commented 3 years ago

I'm equally keen on fast apps. But it's worth keeping in mind that two of the most popular business apps in the world are on this scale:

Gmail:

gmail js

Slack:

slack js

So while I agree we should focus on performance, we shouldn't let 10s of KB hold us back from a better development experience or readable web.

Either way, the original issue seems fixed now.

natematykiewicz commented 2 years ago

I just ran into this as well. To fix it, I simply uninstalled uglifier and installed terser. https://github.com/ahorek/terser-ruby

Install Terser:

$ bundle add terser
$ bundle install

Then use it instead of Uglifier:

Rails.application.configure do
  config.assets.js_compressor = :terser
end