如何“压缩”JavaScript代码

110

JQuery 有两个版本可供下载,一个是生产版(19KB,缩小和压缩),另一个是开发版(120KB,未压缩代码)

现在这个紧凑的19kb版本,如果你下载它,你会看到它仍然是一个JavaScript可执行代码。他们如何压缩它?我也该如何像他们一样“压缩”我的代码呢?


1
特别是,有没有在线工具可以让我做到这一点? - KalEl
2
我偶然发现了这篇旧帖子,里面有相同的问题,问得好!这里有一些很好的基础信息:http://www.thiscouldbeuseful.com/2012/09/minified-js-for-beginners.html。 - Aries51
10个回答

54

自己动手压缩代码

任何压缩工具都无法很好地压缩糟糕的代码。

这个例子只是想展示一下压缩工具的作用。

在压缩之前应该做什么

至于jQuery...我不使用jQuery。jQuery是为了兼容旧版本浏览器而创建的。可以查看caniuse.com,几乎所有浏览器都能正常工作(包括ie10现在已经标准化),我认为现在它只会减慢你的网络应用...如果你喜欢$(),你可以创建自己的简单函数。如果你的客户端需要每次下载100kb的jquery脚本,那么为什么要费心压缩你的代码呢?你的未压缩代码有多大?5-6kb..?更别提你添加的许多插件以使其更易于使用。

原始代码

当你编写一个函数时,你有一个想法,开始写一些东西,有时你最终得到的代码如下。这段代码可以工作。现在大多数人停止思考并将其添加到压缩工具中发布。

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;
}

以下是经过压缩的代码(我添加了新行):

使用 (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
}

但是所有这些变量、条件语句、循环和定义都是必要的吗?

大多数时候不需要

  1. 删除不必要的if、loop、var
  2. 保留原始代码副本
  3. 使用压缩工具

可选项(可以提高性能和缩短代码)

  1. 使用简写运算符
  2. 使用位运算符(不要使用Math
  3. 使用a、b、c等作为临时变量
  4. 使用旧的语法(whilefor...而不是forEach
  5. 在某些情况下将函数参数用作占位符
  6. 删除不必要的"{}","()",";",spaces,newlines
  7. 使用压缩工具

现在如果一个压缩工具可以压缩你的代码,那么你做错了。

没有任何压缩工具可以适当地压缩糟糕的代码。

自己动手

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

它与上面的代码完全相同。

性能

http://jsperf.com/diyminify

你总是需要思考你所需:

在你说“没有人会写出下面这样的代码”之前,先看看这里的前10个问题...

以下是我每十分钟都会看到的一些常见例子。

想要一个可重复使用的条件

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

仅在存在时警报

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

警告是或否

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

将数字转换为字符串或反之。

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

四舍五入一个数字

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

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

switch case

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);

尝试捕获

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);

更多内容

如果
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');

但是 indexOf 的速度较慢,请参考此链接:https://dev59.com/E3VC5IYBdhLWcg3wnCj6#30335438

数字

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;

我发现了一些关于位运算和缩写的不错的文章/站点:

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

http://www.140byt.es/

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

如果您使用您喜欢的搜索引擎搜索,还有许多 jsperf 网站显示缩写和位运算的性能。

我可以继续讲个几小时...但是我认为现在足够了。

如果您有任何问题,请随时问。

记住:

没有压缩器可以正确压缩糟糕的代码。


50
没有太多理由手动压缩代码。编写易于其他开发人员(或您10个月后)理解的代码。是的,简单就是更好。在自动化构建过程中使用压缩过的代码,并保留原始代码。几乎在每种情况下,手动优化带来的任何速度提升都远远被开发人员破译压缩代码的代价所抵消。 - alttag
5
取决于你在做什么。如果你正在处理动画/画布、大型数据集和文件操作等任务,那么快速的代码非常重要,特别是在移动设备上...关键是,对于一些开发者来说,阅读代码很困难。是的......我从 Pentium 2 开始写代码,大概是1998年,我能够读懂代码,并且在我的经验中,我需要检查的错误代码更少。至于速度...嗯,你错了。在复杂函数中使用位运算/与运算符缩写可以极大地提高性能,特别是在各种设备/浏览器上进行测试。搜索 Google Shorthand Bitwise JavaScript,你会找到许多例子。 - cocco
关于您的四舍五入示例:(10.4899845 +.5)|0 的结果为10而不是11。 - DanMan
DIY代码刚被添加到我的“过度优化”文件中。当提供一个小于零的值(myNumber或a)时,它并不完全像原始代码那样工作。原始代码会抛出异常,而“改进”的代码则会进入无限循环。 - Donald Rich
2
从可维护性的角度来看,那听起来像是一个非常糟糕的建议。 - donkz

37

我知道 YUI 压缩器已经被弃用,建议使用 UglifyJS (演示),(myLastName&text=var+hello+%3D+function%28myFirstName%2C+myLastName%29+%7B%0A++alert%28%22Hello+%22+%2B+myFirstName+%2B+%27+%27+%2B+myLastName%29%3B%0A%7D%3B%0Ahello%28%22John%22%2C+%22Smith%22%29%3B)。 - MartyIX

13

Google刚刚发布了一款JavaScript编译器,可以对您的代码进行缩小,消除无用代码分支和更多优化。

谷歌JavaScript编译器

敬礼
K


8
如果您正在使用VSCode编辑器,那么有许多插件/扩展可供选择。比如说,MinifyAll就是一个非常好的插件 - 兼容很多扩展。安装它并重新加载VSCode后,点击您的文件,打开命令面板(Ctrl+Shift+p),输入minify this document (Ctrl+alt+m),还有其他可用选项,如保留原始文档等!简单易用!

3

除了最小化,您还可以进行Base64编码。这会使您的文件更加压缩。我相信您已经看到过js文件,它们被包装在带有参数(p,a,c,k,e,r)的eval()函数中。我在这篇文章中读到的 如何最小化Javascript文件?


1
Base64编码不会压缩您的代码,它实际上是相反的,最终您会得到更多的字符。 您可以使用LZH压缩字符串,有人在GitHub上创建了一个名为lz-string的JS脚本,可对字符串进行LZH压缩,您可以使用它来压缩您的代码: http://pieroxy.net/blog/pages/lz-string/index.html - beliha

3

最近我需要执行同样的任务。虽然 The JavaScript CompressorRater 列出的压缩器非常好,该工具也非常有用,但是这些压缩器无法处理我正在使用的一些 jQuery 代码($.getScript 和 jQuery.fn 检查)。即使 Google Closure Compressor 都在同一行上出现问题。虽然我最终可以解决问题,但这需要我不停地费眼睛。

最终没有任何问题的是 UglifyJS(感谢 @Aries51),而且压缩仅略低于其他所有压缩工具。与 Google 相似,它还有一个 HTTP API。 Packer 也很好,并且在 Perl、PHP 和 .NET 中都有语言实现。


3

我写了一个小脚本,调用API来压缩你的脚本,请看一下:

#!/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;
    }
}

使用方法:

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

0

目前有两种压缩代码的方法:

  1. 在应用程序的后端应用压缩器 - 这里的优点是您可以应用版本控制,并更好地控制您的代码 - 您可以实际上完全自动化压缩过程,最佳实践是在将代码上传到服务器之前应用它 - 当您有大量需要压缩的前端JavaScript和CSS代码时,这是最好的选择:

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

对于Node和npm也有许多这样的工具可用 - 自动化使用Grunt压缩Javascript是一个好习惯。

  1. 您可以使用一些现有的免费在线压缩工具 - 这些工具实际上允许您手动完成相同的操作。我建议在您的javascript / css代码量较小时使用它们 - 不要太多文件。

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


你也可以尝试使用这些在线工具,如CSS的https://www.minify-beautify.com/minify-css-online和SQL的https://www.minify-beautify.com/sql-formatter-online。 - user13993546

-1

试用一下来自fixcode.orgJavaScript压缩器。 这是一个非常有效的工具,可以压缩JavaScript代码

  • 通过URL导入代码
  • 从文件中导入
  • 复制/下载输出

-1
你可以使用ubercompute.com的javascript minifier来压缩你的代码,它可以将你的javascript代码压缩到原始版本的75%。

由于网站本身出现问题,上传按钮无法使用。当尝试上传文件时,无法正常工作。 - Mohit Swami
感谢@MohitSwami告知我们有关错误的信息,但是您所报告的错误并不存在,但由于临时服务器故障,这可能会发生在您身上。 - Abhishek Singh
是的,没错,那是由于临时服务器故障造成的。现在已经恢复正常了。谢谢。 - Mohit Swami

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接