Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Minify Ruby Code

Avatar for Koichi ITO Koichi ITO
August 04, 2024

Minify Ruby Code

Avatar for Koichi ITO

Koichi ITO

August 04, 2024
Tweet

More Decks by Koichi ITO

Other Decks in Programming

Transcript

  1. w ൃද࣌ͷ࠷৽ͷ3VCZͰ͋ΔEFWͱɺ 1SJTNͷ࣍ͷ։ൃ൛Λલఏʹͯ͠·͢ ຊτʔΫʹ͓͚Δόʔδϣϯ $ ruby -rprism -ve 'p Prism::VERSION'

    ruby 3.4.0dev (2024-07-30T06:31:58Z master 1870505f47) [x86_64-darwin23] "0.30.0" # ݫີʹ͸0.31.0޲͚ͷ։ൃ൛ rbenv install 3.4-devͳͲͰ͓खݩʹΠϯετʔϧ
  2. +BWB4DSJQUઌഐͰͷ.JOJGZྫ function greet(name) { console.log(`Hello! ${name}`); } greet("Osaka RubyKaigi 04");

    // Hello, Osaka RubyKaigi 04! HSFFUKT $ npx terser greet.js function greet(name){console.log(`Hello! ${name}`)}\ greet("Osaka RubyKaigi 04"); .JOJGZ͢Δ εϖʔεͷ౎߹ʹ͖࣮ͭࡍ͸ߦ
  3. w ಈ࡞͢ΔͨΊʹඞཁͷͳ͍εϖʔεɺվߦɺ ίϝϯτɺηϛίϩϯͷྨΛআڈ͢Δ w ϨΠΞ΢τ΍ߦؒΛ่͠ɺݟͨ໨Λ6HMJGZ͢Δ w ʮಈ࡞͢Δ͖Ε͍ͳίʔυʯͱҟͳΔՁ஋؍ ಈ࡞͢Δ୹͍ίʔυ $ npx

    terser greet.js | tee >(node) function greet(name){console.log(`Hello! ${name}`)} greet("Osaka RubyKaigi 04"); Hello! Osaka RubyKaigi 04 UFSTFSͷ݁ՌΛϓϩηεஔ׵Ͱ࣮ߦͨ݁͠Ռ
  4. w ໝ૝ͦͷɻSVCZXBTNͷίʔυͰ֎෦Ϧιʔ εΛཁٻͨ͠ࡍʹɺ*4FRͳͲͷதؒදݱͰͳ͍ QMBJOͳ3VCZίʔυͷωοτϫʔΫసૹྔݮʁ w ໝ૝ͦͷɻΤοδίϯϐϡʔςΟϯάͰɺΤο δαʔόʔ $%/ ΍ΤοδσόΠε *P5

    ΁ͷ ίϯςϯπ΍σʔλͷ഑෍ʹ͓͍ͯ༗༻ʁ ະདྷͷ͓࢓ࣄ3VCZͩͱͲ͏ʁ NJOJGZ͸1JDP3VCZͷϝϞϦ࡟ݮʹ࢖͑Δ͸ͣͳͷͰ஫໨͍ͯ͠·͢ɻ IUUQTYDPNIBTVNJLJOTUBUVT
  5. w γϯϘϧΛҾ਺ʹͨ͠ϝιουݺͼग़͠ τʔΫϯྻͷαϯϓϧ puts :hello [:IDENTIFIER, :SYMBOL_BEGIN, :IDENTIFIER, :EOF] puts

    : hello %w(foo) [:PERCENT_LOWER_W, :STRING_CONTENT, :STRING_END, :EOF] w ཁૉͻͱͭͷXϦςϥϧ %w( foo )
  6. ߏจ໦ͷαϯϓϧ $ ruby -rprism -e 'p Prism.parse("42").value' @ ProgramNode (location:

    (1,0)-(1,2)) ├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,2)) ├── flags: ∅ └── body: (length: 1) └── @ IntegerNode (location: (1,0)-(1,2)) ├── flags: newline, static_literal, decimal └── value: 42 Prism.parseͰPrism::ParseResultΛಘΔ
  7. w LexResult.valueͰτʔΫϯΛද͢ Prism::TokenͱMFYTUBUF CJU஋ ͷ഑ྻ֫ಘ w MFYTUBUF஋͸Լهࢀর ຊฤະ࢖༻ʹׂ͖ͭѪ 1SJTN-FY3FTVMU require

    'prism' result = Prism.lex('puts :hello') result.value.class #=> Array result.value.first #=> [#<Prism::Token>, 32] IUUQTHJUIVCDPNSVCZQSJTNCMPCWJODMVEFQSJTNQBSTFSI--
  8. w LexResult.valueͷ഑ྻͷୈҰཁૉ Prism::Token͸ܕɺ஋ɺҐஔ৘ใΛ࣋ͭ 1SJTN5PLFO result = Prism.lex('puts :hello') token, _state

    = result.value.first token.class #=> Prism::Token token.type #=> :IDENTIFIER token.value #=> "puts" token.location.class #=> Prism::Location
  9. w ParseToken.locationͰτʔΫϯͷҐஔ ৘ใΛ࣋ͭPrism::LocationΛಘΒΕΔ 1SJTN-PDBUJPO result = Prism.lex('puts :hello') token, _state

    = result.value.first location = token.location location.first_line #=> 1 location.start_offset #=> 0 location.length #=> 4
  10. τʔΫϯॲཧͷఆੴαϯϓϧ tokens = Prism.lex(source).value tokens.each_cons(2)do|(token,_),(next_token,_)| case token.type when :COMMENT #

    do_something when :IDENTIFIER # do_something end prev_token = token end FBDI@DPOT  Ͱ࣍ͷτʔΫϯ৘ใΛઌಡΈ͢Δ QSFW@UPLFOͰલͷτʔΫϯ৘ใΛอ͓࣋ͯ͘͠ ͜ͷ͋ͱ঺հ͢Δ.JOJGZ3VCZ͸͜ͷͭ͘Γ UPLFOUZQFͷछྨͰॲཧΛ൑ผ͢Δ ࠨ͔Βӈ΁ͷτʔΫϯྻͷϧʔϓ
  11. w {}ϕʔεͷߏจͱͳΔ+BWB4DSJQUͰ͸ྫ͑͹ functionΛҰߦͰෳ਺ఆٛͰ͖Δ +BWB4DSJQUͷϫϯϥΠφʔʹֶͿ $ cat example.js | tee >(npx

    terser) function foo() { console.log(bar()); } function bar() { 42; } function foo(){console.log(bar())}function bar(){42} εϖʔεɺηϛίϩϯෆཁ ಡΈ΍͢͞ͷվߦΛ͢Δ
  12. Prism.lex͸&SSPS5PMFSBODFʹͳͬͯΔ &SSPS5PMFSBODF $ ruby -ce 'cond(arg)?x:y' # εϖʔεͳ͠ѹॖ͸ߏจΤϥʔͷྫ -e:1: syntax

    error, unexpected symbol literal, expecting 'do' or '{' or '(' cond(arg)?x:y ruby: compile error (SyntaxError) $ ruby -ce 'cond(arg)?x: y' # ͜ͷ৔߹:ͱyͷؒʹཁεϖʔε Syntax OK $ ruby -rprism -e "p Prism.lex('cond(arg)?x:y').value" [[#<Prism::Token:0x0000000104c87b70 @source=#<Prism::ASCIISource:0x000000011f7f5dd0 ͍ͭ͜ಈͧ͘ʂ
  13. w ͜ͷվߦ͕ͳ͘ͳͬͯ΋ߏจͱͯ͠ଥ౰Ͱ͋Δ w ηϛίϩϯͳ͠Ͱվߦ࡟আ͸Ͳ͜·ͰͰ͖Δʁ *(/03&%@/&8-*/&τʔΫϯ begin rescue CustomError=>e else ensure

    end ݩ͸όΠτ aOͷ৔߹ begin rescue CustomError=>e else ensure end *(/03&%@/&8-*/&ద༻ όΠτ begin rescue CustomError=>e;else ensure end ࢀߟผ్ηϛίϩϯஔ׵ όΠτ
  14. w ʮಈ࡞͢Δ͖Ε͍Ͱ͸ͳ ͍ίʔυʯ͕ຊτʔΫͷ ςʔϚͰ͢Α w .JOJGZͱ53*$,೴͸ີ઀ ʹؔ࿈͢ΔԾઆ w 53*$,ͷLJOBCB͞ Μ࡞඼ͷཧղʹ͚ۙͮΔʁ

    ͜ͷτʔΫϯ͔ΒಘΒΕΔֶͼ IUUQTHJUIVCDPNUSJDUSJDLCMPCNBTUFSLJOBCBFOUSZSC 53*$,໊࡞ͷͻͱͭ
  15. w BMJBTFRM ͕BMJBTFRM ͸ߏจΤϥʔ w GPP 'PP͕GPP 'PP͸ҙຯ͕มΘΔ w BSSBZ͕

    BSSBZ͸ߏจΤϥʔ w GPPX BCD ͕GPPX BCD ͸ҙຯ͕มΘΔ w GPPX BGPSC ͕GPPX BGPSC ͸ߏจΤϥʔ ݁߹ͯ͠͸͍͚ͳ͍γϦʔζͷҰ෦ unexpected char literal unexpected operator assignment unexpected ')'
  16. w ด͡Χοίલͷվߦ͸IGNORED_NEWLINEʹͰ͖Δ ͸͕ͣͩɺΧϯϚͳͩ͠ͱNEWLINEͱ͞ΕΔ ҙਤతͳ3JQQFSޓ׵ɺSVCZQSJTNࢀর  w ;΁ͷ୯७ͳஔ׵͸[foo, bar, baz;]ͷߏจΤϥʔ <ิ଍>୯७ͳηϛίϩϯஔ׵͸ෆՄ

    [ foo, bar, baz ] :BRACKET_LEFT_ARRAY,:IGNORED_NEWLINE :IDENTIFIER, :COMMA,:IGNORED_NEWLINE :IDENTIFIER, :COMMA,:IGNORED_NEWLINE :IDENTIFIER, :NEWLINE :BRACKET_RIGHT, :NEWLINE, :EOF
  17. վߦͷτʔΫϯॲཧ֓ཁ tokens.each(2) do |(token, _), (next_token, _)| case token.type when

    :IGNORED_NEWLINE # noop when :NEWLINE token_value = if next_token.type == :EOF token.value elsif CLOSING_DELIMITER_TYPES.include?(next_token.type) # noop else ';' end 104*9ͷΞϨ΁ͷOFXMJOFରԠ Ճ͑ͯɺdeffooͳͲ༧໿ޠ͕݁߹͠ͳ͍Α͏ͳॲཧΛผ్͍ͯ͠Δ > ^ͷτʔΫϯͷఆ਺ɻຊདྷ*(/03&%@/&8-*/&͔΋ͳύον
  18. IFSFEPDͷτʔΫϯॲཧ֓ཁ tokens.each(2) do |(token, _), (next_token, _)| case token.type when

    :HEREDOC_START @in_heredoc = true squiggly_heredoc = token.value.start_with?('<<~') # SNIP: <<'HEREDOC', <<"HEREDOC", <<`HEREDOC`΁ͷॲཧׂѪ when :HEREDOC_END heredoc_contents = @heredoc_content_tokens.join # SNIP: <<~΁ͷdedentॲཧΛׂѪ @minified_values << heredoc_contents @minified_values << (@string_quote == '`' ? '`' : '"') @heredoc_content_tokens.clear @in_heredoc = false IFSFEPDதͷτʔΫϯॲཧΛ༗ޮԽ IFSFEPDதͷτʔΫϯॲཧΛແޮԽ EFEFOUॲཧ͕ඞཁ͔ঢ়ଶΛ࣋ͨͤΔ IFSFEPD͸ແҹҎ֎ΫΥʔτ͕ͱ͓Γ IFSFEPDຊจͷτʔΫϯ஋ͷ഑ྻΛ݁߹
  19. ࠓޙͷ֦ுʹ޲͚ͨ஫ҙ఺ def m(a) bar unless cond end def m(a)bar unless

    cond end w Ҿ਺Χοί͋Γͷɺվߦ΍ηϛίϩϯͳ͠Ͱॻ͚ΔFOE͋Γͷ ϫϯϥΠφʔϝιουఆٛʹ͍ͭͯߟ͑Δ ಉ͡ߏจ໦
  20. # Original $ find . -name '*.rb' -type f -print0

    | \ xargs -0 wc -c | awk 'END{print $1}' 49825 # Original $ find . -name '*.rb' -type f -print0 | \ xargs -0 wc -c | awk 'END{print $1}' 49825 # Minify $ bundle exec rake minify $ find . -name '*.rb' -type f -print0 | \ xargs -0 wc -c | awk 'END{print $1}' 31598 # Original $ find . -name '*.rb' -type f -print0 | \ xargs -0 wc -c | awk 'END{print $1}' 49825 # Minify $ bundle exec rake minify $ find . -name '*.rb' -type f -print0 | \ xargs -0 wc -c | awk 'END{print $1}' 31598 # Ratio $ ruby -e 'p 31598 / 49825.0' 0.6341796287004515 .JOJGZͰͲΕ͘Β͍ݮΔʁ
  21. w MJC͸ όΠτ͔Β όΠτʹͳΓɺ TQFD͸ όΠτ͔Β όΠτʹ ͳΔ w ͭ·Γ࡟ݮ͞Εͨίʔυ͸34QFDͷํ͕ߴ͍

    w ࣮ફత ͱ͸ʁ ʹ͸ϓϩμΫτίʔυ΁ͷޮ Ռ͕ߴ͍ํ͕͍͍Μ͚ͩͲݱ࣮͸͜͏Β͍͠ ଌఆͱධՁΛ΋͏গ͠