Cách 'rút gọn' mã Javascript


99

JQuery có hai phiên bản để tải xuống, một là Sản xuất (19KB, Minified và Gzipped) và phiên bản còn lại là Phát triển (120KB, Mã không nén) .

Bây giờ là phiên bản nhỏ gọn 19kb, nếu tải về bạn sẽ thấy vẫn là mã thực thi javascript. Làm thế nào họ đã tổng hợp nó? Và làm cách nào để tôi có thể 'rút gọn' mã của mình như vậy?


1
Đặc biệt, có tiện ích trực tuyến nào cho phép tôi làm điều này không?
KalEl

2
Tôi tình cờ đọc được bài viết cũ này với những câu hỏi tương tự, câu hỏi rất hay! Một số thông tin cơ bản hữu ích: thiscouldbeuseful.com/2012/09/minified-js-for-beginners.html .
Aries51

Câu trả lời:


48

DIY Minification

Không có trình thu nhỏ nào có thể nén đúng một mã xấu.

Trong ví dụ này, tôi chỉ muốn hiển thị mức độ hoạt động của một bộ thu nhỏ.

Bạn nên làm gì trước khi thu nhỏ

Và liên quan đến jQuery ... tôi không sử dụng jQuery. JQuery là cho các trình duyệt cũ, nó được tạo ra vì lý do tương thích .. hãy kiểm tra caniuse.com, hầu hết mọi thứ hoạt động trên mọi trình duyệt (cũng tức là 10 đã được chuẩn hóa), tôi nghĩ bây giờ là chỉ ở đây để làm chậm ứng dụng web của bạn ... nếu bạn thích, $()bạn nên tạo một chức năng đơn giản của riêng mình Và tại sao phải nén mã của bạn nếu khách hàng của bạn cần tải xuống tập lệnh jquery 100kb mọi thứ? Mã không nén của bạn lớn như thế nào? 5-6kb ..? Không phải nói về hàng tấn plugin bạn thêm vào để làm cho nó dễ dàng hơn.

Mã gốc

Khi bạn viết một hàm, bạn có ý tưởng, hãy bắt đầu viết nội dung và đôi khi bạn kết thúc với một đoạn mã như sau. Đoạn mã hoạt động. Bây giờ hầu hết mọi người ngừng suy nghĩ và thêm nó vào một trình thu nhỏ và xuất bản nó.

function myFunction(myNumber){
     var myArray = new Array(myNumber);
     var myObject = new Object();
     var myArray2 = new Array();
     for(var myCounter = 0 ; myCounter < myArray.length ; myCounter++){
         myArray2.push(myCounter);
         var myString = myCounter.toString()
         myObject[ myString ] = ( myCounter + 1 ).toString();
     }
    var myContainer = new Array();
    myContainer[0] = myArray2;
    myContainer[1] = myObject;
    return myContainer;
}

Đây là mã được rút gọn (tôi đã thêm các dòng mới)

Giảm thiểu bằng cách sử dụng ( http://javascript-minifier.com/ )

function myFunction(r){
 for(var n=new Array(r),t=new Object,e=new Array,a=0;a<n.length;a++){
  e.push(a);
  var o=a.toString();
  t[o]=(a+1).toString()
 }
 var i=new Array;
 return i[0]=e,i[1]=t,i
}

Nhưng tất cả các vars, ifs, loop & định nghĩa đó có cần thiết không?

Hầu hết thời gian KHÔNG !

  1. Loại bỏ if, loop, var không cần thiết
  2. Giữ một bản sao mã gốc của bạn
  3. Sử dụng bộ thu nhỏ

TÙY CHỌN (tăng hiệu suất và mã ngắn hơn)

  1. sử dụng toán tử tốc ký
  2. sử dụng toán tử bitwise (không sử dụng Math)
  3. sử dụng a, b, c ... cho các vars tạm thời của bạn
  4. sử dụng cú pháp cũ ( while, for... không phải forEach)
  5. sử dụng các đối số của hàm làm trình giữ chỗ (trong một số trường hợp)
  6. loại bỏ không cần thiết "{}","()",";",spaces,newlines
  7. Sử dụng bộ thu nhỏ

Bây giờ nếu một trình thu nhỏ có thể nén mã của bạn làm sai.

Không có trình thu nhỏ nào có thể nén đúng một mã xấu.

DIY

function myFunction(a,b,c){
 for(b=[],c={};a--;)b[a]=a,c[a]=a+1+'';
 return[b,c]
}

Nó thực hiện chính xác những điều tương tự như các mã ở trên.

Hiệu suất

http://jsperf.com/diyminify

Bạn luôn cần nghĩ những gì bạn cần:

Trước khi bạn nói "Không ai muốn viết mã như câu dưới đây", hãy kiểm tra 10 câu hỏi đầu tiên tại đây ...

Dưới đây là một số ví dụ phổ biến mà tôi thấy cứ sau mười phút.

Muốn có điều kiện tái sử dụng

if(condition=='true'){
 var isTrue=true;
}else{
 var isTrue=false;
}
//same as
var isTrue=!!condition

Chỉ cảnh báo có nếu nó tồn tại

if(condition==true){
 var isTrue=true;
}else{
 var isTrue=false;
}
if(isTrue){
 alert('yes');
}
//same as
!condition||alert('yes')
//if the condition is not true alert yes

Cảnh báo có hoặc không

if(condition==true){
 var isTrue=true;
}else{
 var isTrue=false;
}
if(isTrue){
 alert('yes');
}else{
 alert('no');
}
//same as
alert(condition?'yes':'no')
//if the condition is true alert yes else no

Chuyển đổi một số thành một chuỗi hoặc phó bản

var a=10;
var b=a.toString();
var c=parseFloat(b)
//same as
var a=10,b,c;
b=a+'';
c=b*1

//shorter
var a=10;
a+='';//String
a*=1;//Number

Làm tròn một số

var a=10.3899845
var b=Math.round(a);
//same as
var b=(a+.5)|0;//numbers up to 10 decimal digits (32bit)

Số tầng

var a=10.3899845
var b=Math.floor(a);
//same as
var b=a|0;//numbers up to 10 decimal digits (32bit)

chuyển trường hợp

switch(n)
{
case 1:
  alert('1');
  break;
case 2:
  alert('2');
  break;
default:
  alert('3');
}

//same as
var a=[1,2];
alert(a[n-1]||3);

//same as
var a={'1':1,'2':2};
alert(a[n]||3);

//shorter
alert([1,2][n-1]||3);
//or
alert([1,2][--n]||3);

cố gắng bắt

if(a&&a[b]&&a[b][c]&&a[b][c][d]&&a[b][c][d][e]){
 console.log(a[b][c][d][e]);
}

//this is probably the onle time you should use try catch
var x;
try{x=a.b.c.d.e}catch(e){}
!x||conole.log(x);

nhiều hơn nếu

if(a==1||a==3||a==5||a==8||a==9){
 console.log('yes')
}else{
 console.log('no');
}

console.log([1,3,5,8,9].indexOf(a)!=-1?'yes':'no');

nhưng indexOfđọc chậm https://stackoverflow.com/a/30335438/2450730

con số

1000000000000
//same as
1e12

var oneDayInMS=1000*60*60*24;
//same as
var oneDayInMS=864e5;

var a=10;
a=1+a;
a=a*2;
//same as
a=++a*2;

Một số bài viết / trang web hay mà tôi tìm thấy về bitwise / tốc ký:

http://mudcu.be/journal/2011/11/bitwise-gems-and-other-optimizations/

http://www.140byt.es/

http://www.jquery4u.com/javascript/shorthand-javascript-techniques/

Ngoài ra còn có nhiều trang web jsperf hiển thị hiệu suất của tốc ký & bitwsie nếu bạn tìm kiếm bằng searchhengine yêu thích của mình.

Tôi có thể đi một trong nhiều giờ .. nhưng tôi nghĩ bây giờ là đủ.

nếu bạn có một số câu hỏi chỉ cần hỏi.

Và hãy nhớ

Không có trình thu nhỏ nào có thể nén đúng một mã xấu.


30
Hầu như không có bất kỳ lý do gì để rút gọn mã thủ công. Viết mã dễ hiểu bởi các nhà phát triển khác (hoặc bạn, 10 tháng sau). Vâng, đơn giản hơn là tốt hơn. Sử dụng một bản thu nhỏ trong một quy trình xây dựng tự động để giữ nguyên bản gốc. Trong hầu hết mọi trường hợp, bất kỳ mức tăng tốc độ nào từ việc tối ưu hóa bằng tay đều vượt xa, vượt xa chi phí của các nhà phát triển khi giải mã mã được rút gọn.
alttag

4
phụ thuộc vào những gì bạn đang làm. nếu bạn làm việc với hoạt ảnh / canvas, bộ dữ liệu khổng lồ và thao tác tệp, chẳng hạn, thì mã nhanh là rất quan trọng, đặc biệt là trên thiết bị di động ... vấn đề là, đối với một số nhà phát triển, nó rất khó đọc. vâng ... tôi viết mã từ đó pentium 2 .. vì vậy có lẽ là năm 1998, tôi có thể đọc mã và theo kinh nghiệm của tôi, tôi có ít mã hơn để kiểm tra lỗi. Và về tốc độ .. mh, sai của bạn. Hiệu suất tăng sử dụng Bitwise / và viết tắt trong các chức năng phức tạp được insane.expecially thử nghiệm trên các thiết bị khác nhau / browsers.use google shorthandbitwise javascript và bạn tìm thấy nhiều ví dụ
cocco

Re dụ làm tròn của bạn: (10.4899845 +.5)|0kết quả trong 10 thay vì 11.
DanMan

Mã DIY vừa được thêm vào tệp "được tối ưu hóa quá mức" của tôi. Nó KHÔNG làm chính xác những gì mã gốc thực hiện khi giá trị nhỏ hơn 0 được cung cấp (myNumber hoặc a). Mã ban đầu ném một ngoại lệ và mã "cải tiến" đi vào một vòng lặp vô hạn.
Donald Rich

Điều đó nghe có vẻ như một lời khuyên tồi từ góc độ khả năng hỗ trợ
donkz



3

Cùng với việc thu nhỏ, bạn cũng có thể mã hóa base64. Nó làm cho tệp của bạn được nén nhiều hơn. Tôi chắc rằng bạn đã thấy các tệp js được bao bọc bên trong một hàm eval () với các tham số (p, a, c, k, e, r) được truyền vào. Tôi đã đọc nó trong bài viết này Làm thế nào để thu nhỏ tệp Javascript?


Mã hóa base64 không nén mã của bạn, nó hoàn toàn ngược lại, bạn sẽ có nhiều ký tự hơn. Bạn có thể LZH Nén chuỗi của mình, ai đó đã tạo một tập lệnh JS trên github để Nén LZH trên các chuỗi có tên: lz-string, bạn có thể sử dụng nó để nén mã của mình: pieroxy.net/blog/pages/lz-string/index.html
beliha 18/02/19

3

Tôi đã viết một tập lệnh nhỏ gọi API để rút gọn tập lệnh của bạn, hãy kiểm tra:

#!/usr/bin/perl
use strict;
use warnings;
use LWP::UserAgent;
use HTTP::Request;
use Fcntl;

my %api = ( css => 'https://cssminifier.com/raw', js => 'https://javascript-minifier.com/raw' );

my $DEBUG = 0;

my @files = @ARGV;

unless ( scalar(@files) ) {
    die("Filename(s) not specified");
}

my $ua = LWP::UserAgent->new;

foreach my $file (@files) {
    unless ( -f $file ) {
        warn "Ooops!! $file not found...skipping";
        next;
    }

    my ($extn) = $file =~ /\.([a-z]+)/;

    unless ( defined($extn) && exists( $api{$extn} ) ) {
        warn "type not supported...$file...skipping...";
        next;
    }

    warn "Extn: $extn, API: " . $api{$extn};

    my $data;

    sysopen( my $fh, $file, O_RDONLY );
    sysread( $fh, $data, -s $file );
    close($fh);

    my $output_filename;

    if ( $file =~ /^([^\/]+)\.([a-z]+)$/ ) {
        $output_filename = "$1.min.$2";
    }

    my $resp = $ua->post( $api{$extn}, { input => $data } );

    if ( $resp->is_success ) {
        my $resp_data = $resp->content;
        print $resp_data if ($DEBUG);
        print "\nOutput: $output_filename";

        sysopen( my $fh, $output_filename, O_CREAT | O_WRONLY | O_TRUNC );
        if ( my $sz_wr = syswrite( $fh, $resp_data ) ) {
            print "\nOuput written $sz_wr bytes\n";
            my $sz_org = -s $file;

            printf( "Size reduction %.02f%%\n\n", ( ( $sz_org - $sz_wr ) / $sz_org ) * 100 );
        }   
        close($fh);
    }
    else {
      warn: "Error: $file : " . $resp->status_line;
    }
}

Sử dụng:

./minifier.pl a.js c.css b.js cc.css t.js j.js [..]

1

Gần đây tôi cần thực hiện cùng một nhiệm vụ. Mặc dù các trình nén được liệt kê tại The JavaScript CompressorRater hoạt động rất tốt và công cụ này rất hữu ích, nhưng các trình nén này không hoạt động tốt với một số mã jQuery mà tôi đang sử dụng (kiểm tra $ .getScript và jQuery.fn). Ngay cả Trình nén đóng cửa của Google cũng bị nghẹn những dòng tương tự. Mặc dù cuối cùng tôi có thể ủi được những chỗ gấp khúc thì còn lâu mới phải nheo mắt liên tục.

Cái cuối cùng đã hoạt động mà không gặp sự cố là UglifyJS (cảm ơn @ Aries51 ) và độ nén chỉ hơi ít hơn tất cả những cái khác. Và tương tự như Google, nó có một API HTTP. Packer cũng tốt và có triển khai ngôn ngữ trong Perl, PHP và .NET.


1

Hiện tại có 2 cách để giảm thiểu mã của bạn:

  1. bạn áp dụng trình thu nhỏ ở phía phụ trợ của ứng dụng - ở đây lợi thế là bạn có thể áp dụng lập phiên bản và kiểm soát nhiều hơn mã của mình - bạn thực tế có thể tự động hóa hoàn toàn quá trình thu nhỏ và phương pháp tốt nhất là áp dụng nó trước khi mã của bạn được tải lên máy chủ - điều này được sử dụng tốt nhất khi bạn có nhiều giao diện người dùng (được rút gọn) mã Javascript và CSS:

http://yui.github.io/yuicompressor/

Nhiều công cụ như vậy cũng có sẵn cho Node và npm - bạn nên tự động hóa việc hợp nhất Javascript với Grunt.

  1. bạn có thể sử dụng một số công cụ miễn phí hiện có để thu nhỏ đang chạy trực tuyến - những công cụ này thực tế cho phép bạn làm điều tương tự, nhưng theo cách thủ công. Tôi khuyên bạn nên sử dụng chúng khi lượng mã javascript / css của bạn nhỏ hơn - không nhiều tệp

http://www.modify-anything.com/


0

Bạn có thể sử dụng trình thu nhỏ javascript của ubercompute.com để giảm thiểu mã của mình, Nó sẽ thu nhỏ mã javascript của bạn tối đa 75% so với phiên bản gốc của chúng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.