middleman / middleman

Hand-crafted frontend development

Home Page:https://middlemanapp.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Migrate from Uglifier to Terser

markets opened this issue · comments

ℹ️ This is more a feature request than an issue


Hi @tdreyno and Middleman community 👋🏼

First of all thank you so much for maintaining such an incredible project, still the best SSG IMO 🤘🏼

Even the External Pipeline is awesome and I love it (just created a cool template: https://github.com/ralixjs/middleman-ralix-tailwind) for new projects, I still have other MM sites with the following setup:

MM v4 + Sprockets + Bootstrap v5 gem

Which is quite easy to get it up, without the need of a js bundler. But that setup is actually crashing when using the :minify_javascript setting, as Uglifier doesn't support ES6 syntax (coming from Bootstrap gem):

error  build/javascripts/application-ec337532.js
SyntaxError: Unexpected token: expand (...)
JS_Parse_Error.get ((execjs):3538:621)
(execjs):4077:53
(execjs):1:40
Object.<anonymous> ((execjs):1:58)
Module._compile (node:internal/modules/cjs/loader:1101:14)
Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
Module.load (node:internal/modules/cjs/loader:981:32)
Function.Module._load (node:internal/modules/cjs/loader:822:12)
Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
node:internal/main/run_main_module:17:47
/Users/markets/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/execjs-2.8.1/lib/execjs/external_runtime.rb:39:in `exec'
...

To fix it, I made the following changes:

diff --git a/Gemfile b/Gemfile
index afc9a85..15a2529 100755
--- a/Gemfile
+++ b/Gemfile
@@ -4,6 +4,7 @@ gem "middleman", "~> 4.4"
 gem "middleman-livereload" , "~> 3.4"
 gem "middleman-sprockets", "~> 4.0.0"
 gem "bootstrap", "~> 5.1.0"
+gem "terser", "~> 1.1"
 
 group :development do
   gem "byebug"
diff --git a/Gemfile.lock b/Gemfile.lock
index c23ce8a..0dde00c 100755
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -163,6 +163,8 @@ GEM
       activesupport (>= 5.2)
       sprockets (>= 3.0.0)
     temple (0.8.2)
+    terser (1.1.8)
+      execjs (>= 0.3.0, < 3)
     thor (1.2.1)
     tilt (2.0.10)
     toml (0.3.0)
@@ -184,6 +186,7 @@ DEPENDENCIES
   middleman (~> 4.4)
   middleman-livereload (~> 3.4)
   middleman-sprockets (~> 4.0.0)
+  terser (~> 1.1)
 
 BUNDLED WITH
    2.2.17
diff --git a/config.rb b/config.rb
index 8beefed..2a7c1b2 100755
--- a/config.rb
+++ b/config.rb
@@ -1,3 +1,5 @@
+require 'terser'
+
 set :title, "Bajo Aragón Club de Vehículos Antiguos"
 set :email, "bajoaragonclub@hotmail.com"
 set :facebook, "bajoaragonclub"
@@ -11,7 +13,9 @@ end
 
 configure :build do
   activate :minify_css
-  activate :minify_javascript
+  activate :minify_javascript, compressor: Terser.new
   activate :asset_hash
   activate :relative_assets
 end

In the Uglifier docs you can read (https://github.com/lautis/uglifier#uglifier):

UglifyJS only works with ES5. If you need to compress ES6, ruby-terser is a better option.

So maybe it makes sense to fix it in MM itself? I mean, moving from Uglifier to Terser.

EXTRA INFO Rails also switched the default to Terser: rails/rails#42622

Best,
Marc

Just in case you're agree with the change, I submitted 2 pull requests:

  • targets v4 branch: #2531
  • targets v5 (master): #2532

@markets This is fantastic. Thank you. I had looked at this a while back, but Terser was still too new and buggy. Will merge when tests pass and release a gem.

Thanks @tdreyno much appreciated! If you cut a new release from the v4 branch 🔝 🔝

Hi @tdreyno 👋🏼

do you think we can release new version from 4.x branch? That's the diff: v4.4.2...4.x

We're now pointing to GitHub:

gem "middleman", github: "middleman", branch: "4.x"

But would be nice to have this released, as the official Bootstrap gem crashes without this fix (Terser).

Thanks again!

@markets Does this mean terser will be the default compressor in the next MM release? Or will it still have to be manually enabled / configured?

hi @swift502 👋🏼

Terser is the new default 🙌🏼 in both, next v5 rc and next 4.x release, still unreleased btw. Of course, you will be able to pass a custom compressor as usual:

activate :minify_javascript, compressor: MyCustomCompressor.new

But Terser seems a better default nowadays, as it officially supports ES6.

PS sorry, I forgot to update the changelog 😺, but this change definitely should be mentioned in the release notes. I'll send a new patch updating the changelog.

@markets @tdreyno Has this been released as a 4.x gem? if yes which one?

Hello @shaunakv1, unfortunately it was reverted on 4.X branch. See more in: #2538.

@markets that's a bummer would have loved this feature enabled by default. Especially as Terser is backward compatible.

That being said, do you know if the documentation was ever updated to show how to use terser with v4 if needed?

Update: in #2538 @tdreyno says that main documentation on v4 will be updated to show how to use it.

yes! I understand @tdreyno concerns, but I still think this should be the default on v4 branch (as I pointed out in my comments on #2538). Even more taking into account that v5 is in a uncertain situation at this point.

AFAIK the docs and the default template weren't updated for v4 yet.

thanks @markets I agree. A new minor release can help folks migrate over. I recently migrated 4 rails projects from Uglifier to Terser and had no issues compiling old ES5 code.

That said, you mentioned you were able to migrate your middleman code bases to Terser? Can you please provide some steps on how we can go about doing that without this release? Are we pretty much adding the gem ourselves and make the change in
middleman-core/lib/middleman-core/extensions/minify_javascript.rb that was reverted here ?

You just need to add the gem by yourself in your Gemfile (run bundle install too) and then in your config.rb file a couple of changes:

require 'terser'
...
activate :minify_javascript, compressor: Terser.new

That's all for moving to Terser in a v4 MM project.