12

あなたのほとんどは、おそらくGoogleアナリティクスで提供されているこの小さなトラッキングコードに精通しています。GoogleアナリティクスのようにJavaScriptを小さくするには?

<script> 
(
    function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ 
    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), 
    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) 
    } 
)(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); 

ga('create', 'UA-00000000-0', 'auto'); 
ga('send', 'pageview'); 
</script> 

興味深いことに、この小さな抜粋には、isogramという語を構成する引数が含まれています。また、このスクリプトは引数を使用して変数を宣言し、最終ファイルサイズからいくつかのビットを削減します。おそらく、あなたはコード(?)を書くときにこのパターンを使用しないだろう。だから私の質問は、Googleがコードをどのようにして縮小しているのか、これらのテクニックは単なる人間にも利用できるのだろうか?

私はこれをオンライン化しました。これを縮小する前に書いたようなコードを含むStephen Morleyのexampleが見つかりました。私はそのコードをとり、高度な最適化についてはGoogle独自のClosure Compilerで実行しました。期待どおり、結果のコードはGoogleアナリティクスで使用される実際のスクリプトとはまったく異なります。

(function(){window.b="ga";"ga"in window||(window.a=function(){window.a.q.push(arguments)},window.a.q=[]);window.a.c=(new Date).getTime();var c=document.createElement("script");c.src="//www.google-analytics.com/analytics.js";c.async=!0;var d=document.getElementsByTagName("script")[0];d.parentNode.insertBefore(c,d)})(); 

今回は、2つの余分なコマンドがなくても、コードはDRYより大きく、大きくなりません。

明らかに、Googleのエンジニアが上記の結果にどのようになったのか(私のコードは実際にはStephenの例のコードのようには思えません)、あなたがパートではなくてもこのプロセスを複製できますGoogleの前もって感謝します!

+3

私は分かりませんが、それは非常に小さなスクリプトなので、必要な関数パラメータ名を使用して手作業で簡単に行うことができます。 –

+2

...興味深いのは、 'ga'スクリプトが大文字のリテラルで' {[GoogleAnalyticsObject '] '、大文字小文字のコンパイラを含む)通常はドット構文に変換するブラケット記法を使用していることです。おそらく手で行われます。ブラケットはCCで実行される場合にのみ使用されるため、 'window.b =" ga "'に変換しません。 –

+0

@squintありがとう!ええ、それは手で行われているように思える、私は何かが欠けているのではないかと思っていた – lmenus

答えて

2

"isogram"という単語は、このコードを細分化したGoogleの従業員からのちょっとしたヒントです。

isogramはa word with no repeating charactersなので、パラメータと他の変数名を一意にする必要があるため、正確な論理を表現できます。

この用語はミニファイアに焼き付けられているため、ミニマム変数の最初のコレクションは、ユニークな文字シーケンスのロジックについて少し知っていることを示しています。

単語isogramはそれ自体がisogramなので、minificationロジックを作成した人は、7つの引数/パラメータがある場合のパラメータまたは引数リストをチェックするように設定することができます。単語 "isogram"に対応する文字。これによりオーバーヘッドが増えますが、そのようなケースはまれであり、Googleはスクリプトを最適化するために多くのサーバーとネットワークエンジニアを抱えています。

3

実際には、このようなスクリプトを書くのはかなり簡単で楽しい作業です。

私は架空のスクリプトで起動したい:

は、ここでは、このようなものの中に、通常の機能を有効にする方法長い一例です。このように呼ばれると

window.loadScript = function(src){ 
    const scriptTag = document.createElement('script'); 
    scriptTag.async = true; 
    scriptTag.src = src; 

    const anyOtherScriptTag = document.getElementsByTagName('script')[0]; 
    anyOtherScriptTag.parentNode.insertBefore(scriptTag, anyOtherScriptTag); 
} 

:私は、非同期のJavaScriptファイルをロードscriptLoaderを含めましたloadScript("/url.js")それはDOMとブラウザに(最初のスクリプトタグの前に)新しいスクリプトタグを挿入するスクリプトをダウンロードします。

これまでのところとても良いです。このスクリプト引数がロードされる前に引数を渡したいとしましょう。読み込まれるスクリプトの中で、私は一意のグローバルオブジェクトにアクセスします。それをwindow.myScriptArgsとしましょう。理想的には、スクリプトが読み込まれるとwindow.myScriptArgsが読み込まれ、それに応じて実行されます。

今私はwindow.myScriptArgs = []を行い、一日それを呼び出すだけ単一スクリプトファイルをロードします私の仮説的な例以来、私もloadScript関数にロジックを追加することができます。

window.loadScript = function(src){ 
    window.myScriptArgs = window.myScriptArgs || []; 
    const scriptTag = document.createElement('script'); 
    scriptTag.async = true; 
    scriptTag.src = src; 

    const anyOtherScriptTag = document.getElementsByTagName('script')[0]; 
    anyOtherScriptTag.parentNode.insertBefore(scriptTag, anyOtherScriptTag); 
} 
loadScript("/my-script.js"); 

わかりましたので、私はmyScriptArgsが既に存在しているかどうかをチェックし、そうでない場合、私は空の配列に設定します。 my-script.jsはグローバルなmyScript()メソッドを公開しています。だから私はそれのためのスタブを書く。

window.myScript =() => { 
    window.myScriptArgs = window.myScriptArgs || []; 
    window.myScriptArgs.push(arguments); 
} 

今私はloadScriptを呼び出すと、すぐに指定された引数でのMyScriptを()を呼び出すことができます:このスタブは、すべての引数がmyScriptArgs配列にそれを受け入れます。ローディングの問題やその他のことについて心配する必要はありません。 「my-script.js」が読み込まれると、window.myScriptArgsとなり、例外として動作します。コードは次のようになります。

window.myScript =() => { 
    window.myScriptArgs = window.myScriptArgs || []; 
    window.myScriptArgs.push(arguments); 
} 

window.loadScript = function(src){ 
    window.myScriptArgs = window.myScriptArgs || []; 
    const scriptTag = document.createElement('script'); 
    scriptTag.async = true; 
    scriptTag.src = src; 

    const anyOtherScriptTag = document.getElementsByTagName('script')[0]; 
    anyOtherScriptTag.parentNode.insertBefore(scriptTag, anyOtherScriptTag); 
} 
loadScript("/my-script.js"); 
myScript('command', 'args', 'args1'); 
myScript('command2', 'args3', 'args4'); 

これは正常に動作します。それを最適化しましょう。最初に私はinitMyScript()という単一の関数にloadScriptmyScriptスタブを組み合わせる:

window.initMyScript = function(src){ 
    window.myScriptArgs = window.myScriptArgs || []; 
    window.myScript = window.myScript || function(){ 
     window.myScriptArgs.push(arguments); 
    } 

    const scriptTag = document.createElement('script'); 
    scriptTag.async = true; 
    scriptTag.src = src; 

    const anyOtherScriptTag = document.getElementsByTagName('script')[0]; 
    anyOtherScriptTag.parentNode.insertBefore(scriptTag, anyOtherScriptTag); 
} 
initMyScript("/my-script.js"); 
myScript('command', 'args', 'args1'); 
myScript('command2', 'args3', 'args4'); 

それは何があまりにも空想気圧ません。今度はwindowを引数としてinitMyScriptに渡して、複数のwindow.コールを取り除くつもりです。私はdocumentでこれをやります。

window.initMyScript = function(p, a, src){ 
    p.myScriptArgs = p.myScriptArgs || []; 
    p.myScript = p.myScript || function(){ 
     p.myScriptArgs.push(arguments); 
    } 

    const scriptTag = a.createElement('script'); 
    scriptTag.async = true; 
    scriptTag.src = src; 

    const anyOtherScriptTag = a.getElementsByTagName('script')[0]; 
    anyOtherScriptTag.parentNode.insertBefore(scriptTag, anyOtherScriptTag); 
} 
initMyScript(window, document, "/my-script.js"); 

今、私はいくつかのより多くのビットを保存するために自分自身を繰り返してどこを見てみましょう:

スクリプトは次のようになります。私は、二回myScriptに同じ文字列をscriptを使用します。私の旅で

window.initMyScript = function(p, a, s, c, src){ 
    p.myScriptArgs = p.myScriptArgs || []; 
    p[c] = p[c] || function(){ 
     p.myScriptArgs.push(arguments); 
    } 

    const scriptTag = a.createElement(s); 
    scriptTag.async = true; 
    scriptTag.src = src; 

    const anyOtherScriptTag = a.getElementsByTagName(s)[0]; 
    anyOtherScriptTag.parentNode.insertBefore(scriptTag, anyOtherScriptTag); 
} 
initMyScript(window, document, 'script', 'myScript', "/my-script.js"); 

次のステップでは、変数を短くすることです。

(function(p, a, s, c, src){ 
    p.myScriptArgs = p.myScriptArgs || []; 
    p[c] = p[c] || function(){ 
     p.myScriptArgs.push(arguments); 
    } 

    const q = a.createElement(s); 
    q.async = true; 
    q.src = src; 

    const d = a.getElementsByTagName(s)[0]; 
    d.parentNode.insertBefore(q, d); 
})(window, document, 'script', 'myScript', "/my-script.js"); 

と私の最後の謎に:私もwindow.initMyScript定義を保存するために、自己実行機能には、この機能をオンに私は人々を混乱させ、また、さらに多くのコードを縮小化するために、関数のパラメータを編集します。実際にjavascriptの関数をコンマで連結することができます;)。

(function(p, a, s, c, A, l, i){ 
    p["myScriptArgs"]=p["myScriptArgs"]||[],p[c] = p[c]||function(){ 
     p["myScriptArgs"].push(arguments)}, 
    l = a.createElement(s);l.async = true;l[A] = A; 
    i = a.getElementsByTagName(s)[0]; 
    i.parentNode.insertBefore(l, i); 
})(window, document, 'script', 'myScript', "/my-script.js"); 
myScript("arg1", "arg2"); 
myScript("arg2", "arg3"); 

私はcreateElementによって返された要素を保存する必要があるとvarステートメントを使用したくないので、それはだ、私は関数の中で2つの追加のパラメータを追加することに注意してください。)。

あなたはこれをさらに進めることができますが、その点は分かります。小さな関数については、問題なく自分で行うことができます。 ...

さらに、あなたはUglifyJSのようなminifierを使用することができますし、その全体isogramの事に実際にあるならば、その後の変数を自分の名前を変更

:私はこのコードのいずれかをテストするものではありませんでした。ここは龍です。 想像上のコードは、Googleの難読化しにくい例の私の悪い試みです。 google-analyticsスニペットは私のカスタムスニペットとほぼ同じです。 GAはもう少し最適化します(例:1になる)が、ポイントを獲得します。

私の例で使用されるものについて詳しく読む:5を取る関数に3つの引数を渡すよう Immediately Invoked Function Expression Property accessors (especially Bracket notation)

とJavaScript特定の事柄。彼らは上で私たちに多くの事についての完全なドキュメントを与えるため

+0

私は、この答えが実際の単語 'i、s、o、g、r、a、m'を引数にするのではなく、 JSを非同期でロードする方法そしてその質問に対するあなたの答えは、「手でやってください」というようなものです。 – SergGr

+0

uglifyJSやその他のミニカーを微調整する以外に、手動で行う以外は、希望する出力を得ることができません。 –

4

Googleは、いいですhttps://developers.google.com

ご回答の多くは、上で見つけることができます:

はunminified analytics.jsの

(function(i, s, o, g, r, a, m){ 
    i['GoogleAnalyticsObject'] = r; // Acts as a pointer to support renaming. 

    // Creates an initial ga() function. 
    // The queued commands will be executed once analytics.js loads. 
    i[r] = i[r] || function() { 
    (i[r].q = i[r].q || []).push(arguments) 
    }, 

    // Sets the time (as an integer) this tag was executed. 
    // Used for timing hits. 
    i[r].l = 1 * new Date(); 

    // Insert the script tag asynchronously. 
    // Inserts above current tag to prevent blocking in addition to using the 
    // async attribute. 
    a = s.createElement(o), 
    m = s.getElementsByTagName(o)[0]; 
    a.async = 1; 
    a.src = g; 
    m.parentNode.insertBefore(a, m) 
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga'); 

// Creates a default tracker with automatic cookie domain configuration. 
ga('create', 'UA-XXXXX-Y', 'auto'); 

// Sends a pageview hit from the tracker just created. 
ga('send', 'pageview'); 

であり、ここで、それらが提供する縮小さバージョン(かなりバージョン)です:

(function (i, s, o, g, r, a, m) { 
    i['GoogleAnalyticsObject'] = r; 
    i[r] = i[r] || function() { 
      (i[r].q = i[r].q || []).push(arguments) 
     }, i[r].l = 1 * new Date(); 
    a = s.createElement(o), 
     m = s.getElementsByTagName(o)[0]; 
    a.async = 1; 
    a.src = g; 
    m.parentNode.insertBefore(a, m) 
})(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga'); 

ga('create', 'UA-XXXXX-Y', 'auto'); 
ga('send', 'pageview'); 

そしてhereは、閉鎖コンパイラツールで縮小さバージョン

(function (a, e, f, g, b, c, d) { 
    a.GoogleAnalyticsObject = b; 
    a[b] = a[b] || function() {(a[b].q = a[b].q || []).push(arguments)}; 
    a[b].l = 1 * new Date; 
    c = e.createElement(f); 
    d = e.getElementsByTagName(f)[0]; 
    c.async = 1; 
    c.src = g; 
    d.parentNode.insertBefore(c, d) 
})(window, document, "script", "//www.google-analytics.com/analytics.js", "ga"); 
ga("create", "UA-XXXXX-Y", "auto"); 
ga("send", "pageview"); 

それは同じように見えます。
Github repositoryでプロジェクトの詳細を確認できます。

2

私は、コードを書く方法が無数にあると思っています。 (これは当てはまらないかもしれませんが)縮小された場所にスペースを節約するためにコードを書く1つの方法は、難読化を使うことです。 は、たとえば、次のコード:

function NewObject(prefix) 
{ 
    var count=0; 
    this.SayHello=function(msg) 
    { 
      count++; 
      alert(prefix+msg); 
    } 
    this.GetCount=function() 
    { 
      return count; 
    } 
} 
var obj=new NewObject("Message : "); 
obj.SayHello("You are welcome."); 

はこのように見えるように難読化することができます:

var _0x3c28=["\x53\x61\x79\x48\x65\x6C\x6C\x6F","\x47\x65\x74\x43\x6F\x75\x6E\x74","\x4D\x65\x73\x73\x61\x67\x65\x20\x3A\x20","\x59\x6F\x75\x20\x61\x72\x65\x20\x77\x65\x6C\x63\x6F\x6D\x65\x2E"];function NewObject(_0x12c4x2){var _0x12c4x3=0;this[_0x3c28[0]]= function(_0x12c4x4){_0x12c4x3++;alert(_0x12c4x2+ _0x12c4x4)};this[_0x3c28[1]]= function(){return _0x12c4x3}}var obj= new NewObject(_0x3c28[2]);obj.SayHello(_0x3c28[3]) 

これはhttps://javascriptobfuscator.com/Javascript-Obfuscator.aspx上の自由難読化アルゴリズムを使用して行われました。

Googleには、もちろんコードを処理する独自の方法があると確信しています:)。

1

画像のフォローのようなコードの一部ました:、その後

(function(){ 
    window.GoogleAnalyticsObject = 'ga'; 
    window.ga = window.ga || function(){ 
    (window.ga.q = window.ga.q || []).push(arguments) 
    }, 
    window.ga.l =1 * new Date(); 
    var a = document.createElement('script'), 
    var m = document.getElementsByTagName('script')[0]; 
    a.async = 1; 
    a.src = '//www.google-analytics.com/analytics.js'; 
    m.parentNode.insertBefore(a, m) 
})(); 

をパラメータとして、あなたが必要とするすべてのオブジェクトを渡しするために、あなたのコードを変更:

(function(i, s, o, g, r, a, m){ 
    i['GoogleAnalyticsObject'] = r; 
    i[r] = i[r] || function(){ 
    (i[r].q = i[r].q || []).push(arguments) 
    }, 
    i[r].l =1 * new Date(); 
    a = s.createElement(o), 
    m = s.getElementsByTagName(o)[0]; 
    a.async = 1; 
    a.src = g; 
    m.parentNode.insertBefore(a, m) 
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga'); 

は、すべてのスペースを削除し、最終的にあなたは次のようになります:

(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ 
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), 
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) 
})(window,document,'script','//www.google-analytics.com/analytics.js','ga'); 

私は私が明確だったことを望みます。

:なぜ「アイソグラム」という言葉を選んだのですか?それは "既知の"アイソグラム単語の1つで、詳細なパラメータが必要な場合はWikipediaを参照してください。

-1

npmとgulpのようなタスクランナーを使用できます。 Gulpにはuglifyと呼ばれるプラグインがあり、コード内の文字数をさらに減らすために余分なスペースを取り除き、パラメータと変数を1文字に減らします。

関連する問題