銆怞S銆?200琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒锛堜汉浜洪兘鑳藉浼氾級

Posted 鍓嶇妗冨洯

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了銆怞S銆?200琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒锛堜汉浜洪兘鑳藉浼氾級相关的知识,希望对你有一定的参考价值。


銆怞S銆?200琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒锛堜汉浜洪兘鑳藉浼氾級

鉂?/span> 鉂?/span>

鍏堥棶澶у涓€鍙ワ紝鏃ュ父椤圭洰寮€鍙戜腑浣犺兘绂诲紑 ES6 鍚楋紵

涓€銆佸墠瑷€

瀵逛簬鍓嶇鍚屽鏉ヨ锛岀紪璇戝櫒鍙兘閫傚悎绁炲鐨勯瓟鐩掟煄侊紝琛ㄩ潰鏅€氾紝浣嗗父甯哥粰鎴戜滑鎯婂枩銆?br>缂栬瘧鍣紝椤惧悕鎬濅箟锛岀敤鏉ョ紪璇戯紝缂栬瘧浠€涔堝憿锛熷綋鐒舵槸缂栬瘧浠g爜鍜煂广€?br>銆怞S銆?200琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒锛堜汉浜洪兘鑳藉浼氾級
鍏跺疄鎴戜滑涔熺粡甯告帴瑙﹀埌缂栬瘧鍣ㄧ殑浣跨敤鍦烘櫙锛?/p>

  • React 涓?JSX 杞崲鎴?JS 浠g爜锛?
  • 閫氳繃 Babel 灏?ES6 鍙婁互涓婅鑼冪殑浠g爜杞崲鎴?ES5 浠g爜锛?
  • 閫氳繃鍚勭 Loader 灏?Less / Scss 浠g爜杞崲鎴愭祻瑙堝櫒鏀寔鐨?CSS 浠g爜锛?
  • 灏?TypeScript 杞崲涓?javascript 浠g爜銆?
  • and so on...


浣跨敤鍦烘櫙闈炲父涔嬪锛屾垜鐨勫弻鎵嬮兘鏁颁笉杩囨潵浜嗐€傪煒?br>铏界劧鐜板湪绀惧尯宸茬粡鏈夐潪甯稿宸ュ叿鑳戒负鎴戜滑瀹屾垚涓婅堪宸ヤ綔锛屼絾浜嗚В涓€浜涚紪璇戝師鐞嗘槸寰堟湁蹇呰鐨勩€傛帴涓嬫潵杩涘叆鏈枃涓婚锛?span class="mq-23">銆?00琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒銆?/strong>銆?/p>

浜屻€佺紪璇戝櫒浠嬬粛

2.1 绋嬪簭杩愯鏂瑰紡

鐜颁唬绋嬪簭涓昏鏈変袱绉嶇紪璇戞ā寮忥細闈欐€佺紪璇戝拰鍔ㄦ€佽В閲娿€傛帹鑽愪竴绡囨枃绔犮€夾ngular 2 JIT vs AOT銆嬩粙缁嶅緱闈炲父璇︾粏銆?/p>

闈欐€佺紪璇?/span>

绠€绉?銆孉OT銆?/strong>锛圓head-Of-Time锛夊嵆 銆屾彁鍓嶇紪璇戙€?/strong> 锛岄潤鎬佺紪璇戠殑绋嬪簭浼氬湪鎵ц鍓嶏紝浼氫娇鐢ㄦ寚瀹氱紪璇戝櫒锛屽皢鍏ㄩ儴浠g爜缂栬瘧鎴愭満鍣ㄧ爜銆?br>銆怞S銆?200琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒锛堜汉浜洪兘鑳藉浼氾級
锛堝浘鐗囨潵鑷細https://segmentfault.com/a/1190000008739157锛?br>
鍦?Angular 鐨?AOT 缂栬瘧妯″紡寮€鍙戞祦绋嬪涓嬶細

  • 浣跨敤 TypeScript 寮€鍙?Angular 搴旂敤
  • 杩愯 ngc 缂栬瘧搴旂敤绋嬪簭
    • 浣跨敤 Angular Compiler 缂栬瘧妯℃澘锛屼竴鑸緭鍑?TypeScript 浠g爜
    • 杩愯 tsc 缂栬瘧 TypeScript 浠g爜
  • 浣跨敤 Webpack 鎴?Gulp 绛夊叾浠栧伐鍏锋瀯寤洪」鐩紝濡備唬鐮佸帇缂┿€佸悎骞剁瓑
  • 閮ㄧ讲搴旂敤

鍔ㄦ€佽В閲?/span>

绠€绉?銆孞IT銆?/strong>锛圝ust-In-Time锛夊嵆 銆屽嵆鏃剁紪璇戙€?/strong> 锛屽姩鎬佽В閲婄殑绋嬪簭浼氫娇鐢ㄦ寚瀹氳В閲婂櫒锛屼竴杈圭紪璇戜竴杈规墽琛岀▼搴忋€?br>銆怞S銆?200琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒锛堜汉浜洪兘鑳藉浼氾級锛堝浘鐗囨潵鑷細https://segmentfault.com/a/1190000008739157[1]锛?br>
鍦?Angular 鐨?JIT 缂栬瘧妯″紡寮€鍙戞祦绋嬪涓嬶細

  • 浣跨敤 TypeScript 寮€鍙?Angular 搴旂敤
  • 杩愯 tsc 缂栬瘧 TypeScript 浠g爜
  • 浣跨敤 Webpack 鎴?Gulp 绛夊叾浠栧伐鍏锋瀯寤洪」鐩紝濡備唬鐮佸帇缂┿€佸悎骞剁瓑
  • 閮ㄧ讲搴旂敤

AOT vs JIT

AOT 缂栬瘧娴佺▼锛?/strong>銆怞S銆?200琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒锛堜汉浜洪兘鑳藉浼氾級锛堝浘鐗囨潵鑷細https://segmentfault.com/a/1190000008739157锛?/p>

JIT 缂栬瘧娴佺▼锛?/strong>銆怞S銆?200琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒锛堜汉浜洪兘鑳藉浼氾級锛堝浘鐗囨潵鑷細https://segmentfault.com/a/1190000008739157锛?/p>

鐗规€?/th> AOT JIT
缂栬瘧骞冲彴 (Server) 鏈嶅姟鍣?/td> (Browser) 娴忚鍣?/td>
缂栬瘧鏃舵満 Build (鏋勫缓闃舵) Runtime (杩愯鏃?
鍖呭ぇ灏?/td> 杈冨皬 杈冨ぇ
鎵ц鎬ц兘 鏇村ソ -
鍚姩鏃堕棿 鏇寸煭 -

闄ゆ涔嬪 AOT 杩樻湁浠ヤ笅浼樼偣锛?/p>

  • 鍦ㄥ鎴风鎴戜滑涓嶉渶瑕佸鍏ヤ綋绉簽澶х殑 angular 缂栬瘧鍣紝杩欐牱鍙互鍑忓皯鎴戜滑 JS 鑴氭湰搴撶殑澶у皬銆?
  • 浣跨敤 AOT 缂栬瘧鍚庣殑搴旂敤锛屼笉鍐嶅寘鍚换浣?html 鐗囨锛屽彇鑰屼唬涔嬬殑鏄紪璇戠敓鎴愮殑 TypeScript 浠g爜锛岃繖鏍风殑璇?TypeScript 缂栬瘧鍣ㄥ氨鑳芥彁鍓嶅彂鐜伴敊璇€傛€昏€岃█涔嬶紝閲囩敤 AOT 缂栬瘧妯″紡锛屾垜浠殑妯℃澘鏄被鍨嬪畨鍏ㄧ殑銆?


2.2 鐜颁唬缂栬瘧鍣ㄥ伐浣滄祦绋?/span>

鎽樻妱缁村熀鐧剧涓 缂栬瘧鍣?sup class="mq-110">[2]宸ヤ綔娴佺▼浠嬬粛锛?/p>

鉂?/span>

涓€涓幇浠g紪璇戝櫒鐨勪富瑕佸伐浣滄祦绋嬪涓嬶細婧愪唬鐮侊紙source code锛夆啋 棰勫鐞嗗櫒锛坧reprocessor锛夆啋 缂栬瘧鍣紙compiler锛夆啋 姹囩紪绋嬪簭锛坅ssembler锛夆啋 鐩爣浠g爜锛坥bject code锛夆啋 閾炬帴鍣紙linker锛夆啋 鍙墽琛屾枃浠讹紙executables锛夛紝鏈€鍚庢墦鍖呭ソ鐨勬枃浠跺氨鍙互缁欑數鑴戝幓鍒よ杩愯浜嗐€?/p> 鉂?/span>

銆怞S銆?200琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒锛堜汉浜洪兘鑳藉浼氾級

杩欓噷鏇村己璋冧簡缂栬瘧鍣ㄧ殑浣滅敤锛?span class="mq-118">銆屽皢鍘熷绋嬪簭浣滀负杈撳叆锛岀炕璇戜骇鐢熺洰鏍囪瑷€鐨勭瓑浠风▼搴忋€?/strong>銆?/p>

銆怞S銆?200琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒锛堜汉浜洪兘鑳藉浼氾級
缂栬瘧鍣ㄤ笁涓牳蹇冮樁娈?png

鐩墠缁濆ぇ澶氭暟鐜颁唬缂栬瘧鍣ㄥ伐浣滄祦绋嬪熀鏈被浼硷紝鍖呮嫭涓変釜鏍稿績闃舵锛?/p>

  1. 銆岃В鏋愶紙Parsing锛夈€?/strong> 锛氶€氳繃璇嶆硶鍒嗘瀽鍜岃娉曞垎鏋愶紝灏嗗師濮嬩唬鐮佸瓧绗︿覆瑙f瀽鎴? 銆屾娊璞¤娉曟爲锛圓bstract Syntax Tree锛夈€?/strong>锛?
  2. 銆岃浆鎹紙Transformation锛夈€?/strong>锛氬鎶借薄璇硶鏍戣繘琛岃浆鎹㈠鐞嗘搷浣滐紱
  3. 銆岀敓鎴愪唬鐮侊紙Code Generation锛夈€?/strong>锛氬皢杞崲涔嬪悗鐨?AST 瀵硅薄鐢熸垚鐩爣璇█浠g爜瀛楃涓层€?

涓夈€佺紪璇戝櫒瀹炵幇

鏈枃灏嗛€氳繃 銆?span class="mq-138">The Super Tiny Compiler[3]銆?/strong> 婧愮爜瑙h锛屽涔犲浣曞疄鐜颁竴涓交閲忕紪璇戝櫒锛屾渶缁?span class="mq-140">銆屽疄鐜板皢涓嬮潰鍘熷浠g爜瀛楃涓诧紙Lisp 椋庢牸鐨勫嚱鏁拌皟鐢級缂栬瘧鎴?JavaScript 鍙墽琛岀殑浠g爜銆?/strong>銆?br>


Lisp 椋庢牸锛堢紪璇戝墠锛?/th> JavaScript 椋庢牸锛堢紪璇戝悗锛?/th>
2 + 2 (add 2 2) add(2, 2)
4 - 2 (subtract 4 2) subtract(4, 2)
2 + (4 - 2) (add 2 (subtract 4 2)) add(2, subtract(4, 2))


璇濊 The Super Tiny Compiler 鍙风О銆屽彲鑳芥槸鏈夊彶浠ユ潵鏈€灏忕殑缂栬瘧鍣ㄣ€?/strong>锛屽苟涓斿叾浣滆€?James Kyle 涔熸槸 Babel 娲昏穬缁存姢鑰呬箣涓€銆?br>銆怞S銆?200琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒锛堜汉浜洪兘鑳藉浼氾級
璁╂垜浠紑濮嬪惂~

3.1 The Super Tiny Compiler 宸ヤ綔娴佺▼

鐜板湪瀵圭収鍓嶉潰缂栬瘧鍣ㄧ殑涓変釜鏍稿績闃舵锛屼簡瑙d笅 The Super Tiny Compiler  缂栬瘧鍣ㄦ牳蹇冨伐浣滄祦绋嬶細
銆怞S銆?200琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒锛堜汉浜洪兘鑳藉浼氾級

鍥句腑璇︾粏娴佺▼濡備笅锛?/strong>

  1. 鎵ц 銆屽叆鍙e嚱鏁般€?/strong>锛岃緭鍏? 銆屽師濮嬩唬鐮佸瓧绗︿覆銆?/strong>浣滀负鍙傛暟锛?
// 鍘熷浠g爜瀛楃涓?/span>
(add 2 (subtract 4 2))
  1. 杩涘叆 銆岃В鏋愰樁娈碉紙Parsing锛夈€?/strong>锛屽師濮嬩唬鐮佸瓧绗︿覆閫氳繃 銆岃瘝娉曞垎鏋愬櫒锛圱okenizer锛?span class="mq-183">銆?/strong>杞崲涓? 銆?/strong>璇嶆硶鍗曞厓鏁扮粍銆?/strong>锛?/strong>鐒跺悗鍐嶉€氳繃 銆岃瘝娉曞垎鏋愬櫒锛圥arser锛?span class="mq-188">銆?/strong>灏? 銆?/strong>璇嶆硶鍗曞厓鏁扮粍銆嶈浆鎹负 銆?/strong>鎶借薄璇硶鏍戯紙Abstract Syntax Tree 绠€绉?AST锛夈€嶏紝骞惰繑鍥烇紱

銆怞S銆?200琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒锛堜汉浜洪兘鑳藉浼氾級銆怞S銆?200琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒锛堜汉浜洪兘鑳藉浼氾級

  1. 杩涘叆 銆岃浆鎹㈤樁娈碉紙Transformation锛夈€?/strong>锛屽皢涓婁竴姝ョ敓鎴愮殑 銆孉ST 瀵硅薄銆?/strong> 瀵煎叆 銆岃浆鎹㈠櫒锛圱ransformer锛夈€?/strong>锛岄€氳繃 銆岃浆鎹㈠櫒銆?/strong>涓殑 銆岄亶鍘嗗櫒锛圱raverser锛夈€?/strong>锛屽皢浠g爜杞崲涓烘垜浠墍闇€鐨? 銆屾柊鐨?AST 瀵硅薄銆?/strong>锛?

銆怞S銆?200琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒锛堜汉浜洪兘鑳藉浼氾級

  1. 杩涘叆 銆屼唬鐮佺敓鎴愰樁娈碉紙Code Generation锛夈€?/strong>锛屽皢涓婁竴姝ヨ繑鍥炵殑 銆屾柊 AST 瀵硅薄銆?/strong>閫氳繃 銆屼唬鐮佺敓鎴愬櫒锛圕odeGenerator锛夈€?/strong>锛岃浆鎹㈡垚  銆孞avaScript Code銆?/strong>锛?

銆怞S銆?200琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒锛堜汉浜洪兘鑳藉浼氾級

  1. 銆屼唬鐮佺紪璇戠粨鏉熴€?/strong>锛岃繑鍥? 銆孞avaScript Code銆?/strong>銆?

銆怞S銆?200琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒锛堜汉浜洪兘鑳藉浼氾級
涓婅堪娴佺▼鐪嬪畬鍚庡彲鑳戒竴鑴告嚨閫硷紝涓嶈繃娌′簨锛岃淇濇寔澶磋剳娓呴啋锛屽厛鏈変釜鏁翠釜娴佺▼鐨勫嵃璞★紝鎺ヤ笅鏉ユ垜浠紑濮嬮槄璇讳唬鐮侊細

3.2 鍏ュ彛鏂规硶

棣栧厛瀹氫箟涓€涓叆鍙f柟娉?compiler 锛屾帴鏀跺師濮嬩唬鐮佸瓧绗︿覆浣滀负鍙傛暟锛岃繑鍥炴渶缁?JavaScript Code锛?br>

// 缂栬瘧鍣ㄥ叆鍙f柟娉?鍙傛暟锛氬師濮嬩唬鐮佸瓧绗︿覆 input
function compiler(input) {
let tokens = tokenizer(input);
let ast = parser(tokens);
let newAst = transformer(ast);
let output = codeGenerator(newAst);
return output;
}

3.3 瑙f瀽闃舵

鍦ㄨВ鏋愰樁娈典腑锛屾垜浠畾涔?span class="mq-243">銆岃瘝娉曞垎鏋愬櫒鏂规硶銆?/strong> tokenizer  鍜?span class="mq-245">銆岃娉曞垎鏋愬櫒鏂规硶銆?/strong> parser 鐒跺悗鍒嗗埆瀹炵幇锛?br>

// 璇嶆硶鍒嗘瀽鍣?鍙傛暟锛氬師濮嬩唬鐮佸瓧绗︿覆 input
function tokenizer(input) {};

// 璇硶鍒嗘瀽鍣?鍙傛暟锛氳瘝娉曞崟鍏冩暟缁則okens
function parser(tokens) {};

璇嶆硶鍒嗘瀽鍣?/span>

銆岃瘝娉曞垎鏋愬櫒鏂规硶銆?/strong> tokenizer 鐨勪富瑕佷换鍔★細閬嶅巻鏁翠釜鍘熷浠g爜瀛楃涓诧紝灏嗗師濮嬩唬鐮佸瓧绗︿覆杞崲涓?span class="mq-267">銆岃瘝娉曞崟鍏冩暟缁勶紙tokens锛夈€?/strong>锛屽苟杩斿洖銆?br>鍦ㄩ亶鍘嗚繃绋嬩腑锛屽尮閰嶆瘡绉嶅瓧绗﹀苟澶勭悊鎴?span class="mq-268">銆岃瘝娉曞崟鍏冦€?/strong>鍘嬪叆銆岃瘝娉曞崟鍏冩暟缁勩€?/strong>锛屽褰撳尮閰嶅埌宸︽嫭鍙凤紙 ( 锛夋椂锛屽皢寰€銆岃瘝娉曞崟鍏冩暟缁勶紙tokens锛?span>銆屽帇鍏ヤ竴涓€?/strong>璇嶆硶鍗曞厓瀵硅薄銆?/strong>锛?code class="mq-272">{type: 'paren', value:'('}锛夈€?br>銆怞S銆?200琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒锛堜汉浜洪兘鑳藉浼氾級

// 璇嶆硶鍒嗘瀽鍣?鍙傛暟锛氬師濮嬩唬鐮佸瓧绗︿覆 input
function tokenizer(input) {
let current = 0; // 褰撳墠瑙f瀽鐨勫瓧绗︾储寮曪紝浣滀负娓告爣
let tokens = []; // 鍒濆鍖栬瘝娉曞崟鍏冩暟缁?/span>
// 寰幆閬嶅巻鍘熷浠g爜瀛楃涓诧紝璇诲彇璇嶆硶鍗曞厓鏁扮粍
while (current < input.length) {
let char = input[current];
// 鍖归厤宸︽嫭鍙凤紝鍖归厤鎴愬姛鍒欏帇鍏ュ璞?{type: 'paren', value:'('}
if (char === '(') {
tokens.push({
type: 'paren',
value: '('
});
current++;
continue; // 鑷current锛屽畬鎴愭湰娆″惊鐜紝杩涘叆涓嬩竴涓惊鐜?/span>
}
// 鍖归厤鍙虫嫭鍙凤紝鍖归厤鎴愬姛鍒欏帇鍏ュ璞?{type: 'paren', value:')'}
if (char === ')') {
tokens.push({
type: 'paren',
value: ')'
});
current++;
continue;
}

// 鍖归厤绌虹櫧瀛楃锛屽尮閰嶆垚鍔熷垯璺宠繃
// 浣跨敤 \s 鍖归厤锛屽寘鎷┖鏍笺€佸埗琛ㄧ銆佹崲椤电銆佹崲琛岀銆佸瀭鐩村埗琛ㄧ绛?/span>
let WHITESPACE = /\s/;
if (WHITESPACE.test(char)) {
current++;
continue;
}
// 鍖归厤鏁板瓧瀛楃锛屼娇鐢?[0-9]锛氬尮閰?/span>
// 鍖归厤鎴愬姛鍒欏帇鍏type: 'number', value: value}
// 濡?(add 123 456) 涓?123 鍜?456 涓轰袱涓暟鍊艰瘝娉曞崟鍏?/span>
let NUMBERS = /[0-9]/;
if (NUMBERS.test(char)) {
let value = '';
// 鍖归厤杩炵画鏁板瓧锛屼綔涓烘暟鍊?/span>
while (NUMBERS.test(char)) {
value += char;
char = input[++current];
}
tokens.push({ type: 'number', value });
continue;
}
// 鍖归厤褰㈠弻寮曞彿鍖呭洿鐨勫瓧绗︿覆
// 鍖归厤鎴愬姛鍒欏帇鍏?{ type: 'string', value: value }
// 濡?(concat "foo" "bar") 涓?"foo" 鍜?"bar" 涓轰袱涓瓧绗︿覆璇嶆硶鍗曞厓
if (char === '"') {
let value = '';
char = input[++current]; // 璺宠繃宸﹀弻寮曞彿
// 鑾峰彇涓や釜鍙屽紩鍙蜂箣闂存墍鏈夊瓧绗?/span>
while (char !== '"') {
value += char;
char = input[++current];
}
char = input[++current];// 璺宠繃鍙冲弻寮曞彿
tokens.push({ type: 'string', value });
continue;
}
// 鍖归厤鍑芥暟鍚嶏紝瑕佹眰鍙惈澶у皬鍐欏瓧姣嶏紝浣跨敤 [a-z] 鍖归厤 i 妯″紡
// 鍖归厤鎴愬姛鍒欏帇鍏?{ type: 'name', value: value }
// 濡?(add 2 4) 涓?add 涓轰竴涓悕绉拌瘝娉曞崟鍏?/span>
let LETTERS = /[a-z]/i;
if (LETTERS.test(char)) {
let value = '';
// 鑾峰彇杩炵画瀛楃
while (LETTERS.test(char)) {
value += char;
char = input[++current];
}
tokens.push({ type: 'name', value });
continue;
}
// 褰撻亣鍒版棤娉曡瘑鍒殑瀛楃锛屾姏鍑洪敊璇彁绀猴紝骞堕€€鍑?/span>
throw new TypeError('I dont know what this character is: ' + char);
}
// 璇嶆硶鍒嗘瀽鍣ㄧ殑鏈€鍚庤繑鍥炶瘝娉曞崟鍏冩暟缁?/span>
return tokens;
}

璇硶鍒嗘瀽鍣?/span>

銆岃娉曞垎鏋愬櫒鏂规硶銆?/strong> parser 鐨勪富瑕佷换鍔★細灏?span class="mq-368">銆岃瘝娉曞垎鏋愬櫒銆?/strong>杩斿洖鐨?span class="mq-369">銆岃瘝娉曞崟鍏冩暟缁勩€?/strong>锛岃浆鎹负鑳藉鎻忚堪璇硶鎴愬垎鍙婂叾鍏崇郴鐨勪腑闂村舰寮忥紙銆屾娊璞¤娉曟爲 AST銆?/strong>锛夈€?br>銆怞S銆?200琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒锛堜汉浜洪兘鑳藉浼氾級

// 璇硶鍒嗘瀽鍣?鍙傛暟锛氳瘝娉曞崟鍏冩暟缁則okens
function parser(tokens) {
let current = 0; // 璁剧疆褰撳墠瑙f瀽鐨勮瘝娉曞崟鍏冪殑绱㈠紩锛屼綔涓烘父鏍?/span>
// 閫掑綊閬嶅巻锛堝洜涓哄嚱鏁拌皟鐢ㄥ厑璁稿祵濂楋級锛屽皢璇嶆硶鍗曞厓杞垚 LISP 鐨?AST 鑺傜偣
function walk() {
// 鑾峰彇褰撳墠绱㈠紩涓嬬殑璇嶆硶鍗曞厓 token
let token = tokens[current];

// 鏁板€肩被鍨嬭瘝娉曞崟鍏?/span>
if (token.type === 'number') {
current++; // 鑷褰撳墠 current 鍊?/span>
// 鐢熸垚涓€涓?AST鑺傜偣 'NumberLiteral'锛岃〃绀烘暟鍊煎瓧闈㈤噺
return {
type: 'NumberLiteral',
value: token.value,
};
}

// 瀛楃涓茬被鍨嬭瘝娉曞崟鍏?/span>
if (token.type === 'string') {
current++;
// 鐢熸垚涓€涓?AST鑺傜偣 'StringLiteral'锛岃〃绀哄瓧绗︿覆瀛楅潰閲?/span>
return {
type: 'StringLiteral',
value: token.value,
};
}

// 鍑芥暟绫诲瀷璇嶆硶鍗曞厓
if (token.type === 'paren' && token.value === '(') {
// 璺宠繃宸︽嫭鍙凤紝鑾峰彇涓嬩竴涓瘝娉曞崟鍏冧綔涓哄嚱鏁板悕
token = tokens[++current];

let node = {
type: 'CallExpression',
name: token.value,
params: []
};

// 鍐嶆鑷 current 鍙橀噺锛岃幏鍙栧弬鏁拌瘝娉曞崟鍏?/span>
token = tokens[++current];

// 閬嶅巻姣忎釜璇嶆硶鍗曞厓锛岃幏鍙栧嚱鏁板弬鏁帮紝鐩村埌鍑虹幇鍙虫嫭鍙?锛?
while ((token.type !== 'paren') || (token.type === 'paren' && token.value !== ')')) {
node.params.push(walk());
token = tokens[current];
}

current++; // 璺宠繃鍙虫嫭鍙?/span>
return node;
}
// 鏃犳硶璇嗗埆鐨勫瓧绗︼紝鎶涘嚭閿欒鎻愮ず
throw new TypeError(token.type);
}

// 鍒濆鍖?AST 鏍硅妭鐐?/span>
let ast = {
type: 'Program',
body: [],
};

// 寰幆濉厖 ast.body
while (current < tokens.length) {
ast.body.push(walk());
}

// 鏈€鍚庤繑鍥瀉st
return ast;
}


3.4 杞崲闃舵

鍦ㄨ浆鎹㈤樁娈典腑锛屽畾涔変簡杞崲鍣?transformer 鍑芥暟锛屼娇鐢ㄨ瘝娉曞垎鏋愬櫒杩斿洖鐨?LISP 鐨?AST 瀵硅薄浣滀负鍙傛暟锛屽皢 AST 瀵硅薄杞崲鎴愪竴涓柊鐨?AST 瀵硅薄銆?br>
涓轰簡鏂逛究浠g爜缁勭粐锛屾垜浠畾涔変竴涓亶鍘嗗櫒 traverser 鏂规硶锛岀敤鏉ュ鐞嗘瘡涓€涓妭鐐圭殑鎿嶄綔銆?br>

// 閬嶅巻鍣?鍙傛暟锛歛st 鍜?visitor
function traverser(ast, visitor) {
// 瀹氫箟鏂规硶 traverseArray
// 鐢ㄤ簬閬嶅巻 AST鑺傜偣鏁扮粍锛屽鏁扮粍涓瘡涓厓绱犺皟鐢?traverseNode 鏂规硶銆?/span>
function traverseArray(array, parent) {
array.forEach(child => {
traverseNode(child, parent);
});
}

// 瀹氫箟鏂规硶 traverseNode
// 鐢ㄤ簬澶勭悊姣忎釜 AST 鑺傜偣锛屾帴鍙椾竴涓?node 鍜屽畠鐨勭埗鑺傜偣 parent 浣滀负鍙傛暟
function traverseNode(node, parent) {
// 鑾峰彇 visitor 涓婂搴旀柟娉曠殑瀵硅薄
let methods = visitor[node.type];
// 鑾峰彇 visitor 鐨?enter 鏂规硶锛屽鐞嗘搷浣滃綋鍓?node
if (methods && methods.enter) {
methods.enter(node, parent);
}

switch (node.type) {
// 鏍硅妭鐐?/span>
case 'Program':
traverseArray(node.body, node);
break;
// 鍑芥暟璋冪敤
case 'CallExpression':
traverseArray(node.params, node);
break;
// 鏁板€煎拰瀛楃涓诧紝蹇界暐
case 'NumberLiteral':
case 'StringLiteral':
break;

// 褰撻亣鍒版棤娉曡瘑鍒殑瀛楃锛屾姏鍑洪敊璇彁绀猴紝骞堕€€鍑?/span>
default:
throw new TypeError(node.type);
}
if (methods && methods.exit) {
methods.exit(node, parent);
}
}
// 棣栨鎵ц锛屽紑濮嬮亶鍘?/span>
traverseNode(ast, null);
}


鍦ㄧ湅銆岄亶鍘嗗櫒銆?/strong> traverser 鏂规硶鏃讹紝寤鸿缁撳悎涓嬮潰浠嬬粛鐨?span class="mq-496">銆岃浆鎹㈠櫒銆?/strong> transformer 鏂规硶闃呰锛?br>

// 杞寲鍣紝鍙傛暟锛歛st
function transformer(ast) {
// 鍒涘缓 newAST锛屼笌涔嬪墠 AST 绫讳技锛孭rogram锛氫綔涓烘柊 AST 鐨勬牴鑺傜偣
let newAst = {
type: 'Program',
body: [],
};

// 閫氳繃 _context 缁存姢鏂版棫 AST锛屾敞鎰?_context 鏄竴涓紩鐢紝浠庢棫鐨?AST 鍒版柊鐨?AST銆?/span>
ast._context = newAst.body;

// 閫氳繃閬嶅巻鍣ㄩ亶鍘?澶勭悊鏃х殑 AST
traverser(ast, {
// 鏁板€硷紝鐩存帴鍘熸牱鎻掑叆鏂癆ST锛岀被鍨嬪悕绉?NumberLiteral
NumberLiteral: {
enter(node, parent) {
parent._context.push({
type: 'NumberLiteral',
value: node.value,
});
},
},
// 瀛楃涓诧紝鐩存帴鍘熸牱鎻掑叆鏂癆ST锛岀被鍨嬪悕绉?StringLiteral
StringLiteral: {
enter(node, parent) {
parent._context.push({
type: 'StringLiteral',
value: node.value,
});
},
},
// 鍑芥暟璋冪敤
CallExpression: {
enter(node, parent) {
// 鍒涘缓涓嶅悓鐨凙ST鑺傜偣
let expression = {
type: 'CallExpression',
callee: {
type: 'Identifier',
name: node.name,
},
arguments: [],
};

// 鍑芥暟璋冪敤鏈夊瓙绫伙紝寤虹珛鑺傜偣瀵瑰簲鍏崇郴锛屼緵瀛愯妭鐐逛娇鐢?/span>
node._context = expression.arguments;

// 椤跺眰鍑芥暟璋冪敤绠楁槸璇彞锛屽寘瑁呮垚鐗规畩鐨凙ST鑺傜偣
if (parent.type !== 'CallExpression') {

expression = {
type: 'ExpressionStatement',
expression: expression,
};
}
parent._context.push(expression);
},
}
});
return newAst;
}


閲嶈涓€鐐癸紝杩欓噷閫氳繃 _context 寮曠敤鏉?span class="mq-540">銆岀淮鎶ゆ柊鏃?AST 瀵硅薄銆?/strong>锛岀鐞嗘柟渚匡紝閬垮厤姹℃煋鏃?AST 瀵硅薄銆?br>


3.5 浠g爜鐢熸垚

鎺ヤ笅鏉ュ埌浜嗘渶鍚庝竴姝ワ紝鎴戜滑瀹氫箟銆屼唬鐮佺敓鎴愬櫒銆?/strong> codeGenerator 鏂规硶锛岄€氳繃閫掑綊锛屽皢鏂扮殑 AST 瀵硅薄浠g爜杞崲鎴?JavaScript 鍙墽琛屼唬鐮佸瓧绗︿覆銆?br>

// 浠g爜鐢熸垚鍣?鍙傛暟锛氭柊 AST 瀵硅薄
function codeGenerator(node) {

switch (node.type) {
// 閬嶅巻 body 灞炴€т腑鐨勮妭鐐癸紝涓旈€掑綊璋冪敤 codeGenerator锛屾寜琛岃緭鍑虹粨鏋?/span>
case 'Program':
return node.body.map(codeGenerator)
.join('\n');

// 琛ㄨ揪寮忥紝澶勭悊琛ㄨ揪寮忓唴瀹癸紝骞剁敤鍒嗗彿缁撳熬
case 'ExpressionStatement':
return (
codeGenerator(node.expression) +
';'
);

// 鍑芥暟璋冪敤锛屾坊鍔犲乏鍙虫嫭鍙凤紝鍙傛暟鐢ㄩ€楀彿闅斿紑
case 'CallExpression':
return (
codeGenerator(node.callee) +
'(' +
node.arguments.map(codeGenerator)
.join(', ') +
')'
);

// 鏍囪瘑绗︼紝杩斿洖鍏?name
case 'Identifier':
return node.name;
// 鏁板€硷紝杩斿洖鍏?value
case 'NumberLiteral':
return node.value;

// 瀛楃涓诧紝鐢ㄥ弻寮曞彿鍖呰9鍐嶈緭鍑?/span>
case 'StringLiteral':
return '"' + node.value + '"';

// 褰撻亣鍒版棤娉曡瘑鍒殑瀛楃锛屾姏鍑洪敊璇彁绀猴紝骞堕€€鍑?/span>
default:
throw new TypeError(node.type);
}
}


3.6 缂栬瘧鍣ㄦ祴璇?/span>

鎴涓婁竴姝ワ紝鎴戜滑瀹屾垚绠€鏄撶紪璇戝櫒鐨勪唬鐮佸紑鍙戙€傛帴涓嬫潵閫氳繃鍓嶉潰鍘熷闇€姹傜殑浠g爜锛屾祴璇曠紪璇戝櫒鏁堟灉濡備綍锛?br>

const add = (a, b) => a + b;
const subtract = (a, b) => a - b;
const source = "(add 2 (subtract 4 2))";
const target = compiler(source); // "add(2, (subtract(4, 2));"

const result = eval(target); // Ok result is 4


3.7 宸ヤ綔娴佺▼灏忕粨

鎬荤粨 The Super Tiny Compiler 缂栬瘧鍣ㄦ暣涓伐浣滄祦绋嬶細
銆?銆乮nput => tokenizer => tokens銆?/strong>
銆?銆乼okens => parser => ast銆?/strong>
銆?銆乤st => transformer => newAst銆?/strong>
銆?銆乶ewAst => generator => output銆?/strong>

鍏跺疄澶氭暟缂栬瘧鍣ㄧ殑宸ヤ綔娴佺▼閮藉ぇ鑷寸浉鍚岋細銆怞S銆?200琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒锛堜汉浜洪兘鑳藉浼氾級

鍥涖€佹墜鍐?Webpack 缂栬瘧鍣?/span>

鏍规嵁涔嬪墠浠嬬粛鐨?The Super Tiny Compiler缂栬瘧鍣ㄦ牳蹇冨伐浣滄祦绋嬶紝鍐嶆潵鎵嬪啓 Webpack 鐨勭紪璇戝櫒锛屼細璁╀綘鏈夌浼椾韩涓濇粦鐨勬劅瑙墌
銆怞S銆?200琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒锛堜汉浜洪兘鑳藉浼氾級


璇濊锛屾湁浜涢潰璇曞畼鍠滄闂繖涓憿銆傚綋鐒讹紝鎵嬪啓涓€閬嶈兘璁╂垜浠洿浜嗚В Webpack 鐨勬瀯寤烘祦绋嬶紝杩欎釜绔犺妭鎴戜滑绠€瑕佷粙缁嶄竴涓嬨€?/p>

4.1 Webpack 鏋勫缓娴佺▼鍒嗘瀽

浠庡惎鍔ㄦ瀯寤哄埌杈撳嚭缁撴灉涓€绯诲垪杩囩▼锛?/p>

  1. 銆屽垵濮嬪寲鍙傛暟銆?/strong>

瑙f瀽 Webpack 閰嶇疆鍙傛暟锛屽悎骞?Shell 浼犲叆鍜?webpack.config.js 鏂囦欢閰嶇疆鐨勫弬鏁帮紝褰㈡垚鏈€鍚庣殑閰嶇疆缁撴灉銆?br>

  1. 銆屽紑濮嬬紪璇戙€?/strong>

涓婁竴姝ュ緱鍒扮殑鍙傛暟鍒濆鍖?compiler 瀵硅薄锛屾敞鍐屾墍鏈夐厤缃殑鎻掍欢锛屾彃浠剁洃鍚?Webpack 鏋勫缓鐢熷懡鍛ㄦ湡鐨勪簨浠惰妭鐐癸紝鍋氬嚭鐩稿簲鐨勫弽搴旓紝鎵ц瀵硅薄鐨?run 鏂规硶寮€濮嬫墽琛岀紪璇戙€?br>

  1. 銆岀‘瀹氬叆鍙c€?/strong>

浠庨厤缃殑 entry 鍏ュ彛锛屽紑濮嬭В鏋愭枃浠舵瀯寤?AST 璇硶鏍戯紝鎵惧嚭渚濊禆锛岄€掑綊涓嬪幓銆?br>

  1. 銆岀紪璇戞ā鍧椼€?/strong>

閫掑綊涓牴鎹?span class="mq-658">銆屾枃浠剁被鍨嬨€?/strong>鍜?銆宭oader 閰嶇疆銆?/strong>锛岃皟鐢ㄦ墍鏈夐厤缃殑 loader 瀵规枃浠惰繘琛岃浆鎹紝鍐嶆壘鍑鸿妯″潡渚濊禆鐨勬ā鍧楋紝鍐嶉€掑綊鏈楠ょ洿鍒版墍鏈夊叆鍙d緷璧栫殑鏂囦欢閮界粡杩囦簡鏈楠ょ殑澶勭悊銆?br>

  1. 銆屽畬鎴愭ā鍧楃紪璇戝苟杈撳嚭銆?/strong>

閫掑綊瀹屼簨鍚庯紝寰楀埌姣忎釜鏂囦欢缁撴灉锛屽寘鍚瘡涓ā鍧椾互鍙婁粬浠箣闂寸殑渚濊禆鍏崇郴锛屾牴鎹?entry 閰嶇疆鐢熸垚浠g爜鍧?chunk 銆?br>

  1. 銆岃緭鍑哄畬鎴愩€?/strong>

杈撳嚭鎵€鏈夌殑 chunk 鍒版枃浠剁郴缁熴€?br>
娉ㄦ剰锛氬湪鏋勫缓鐢熷懡鍛ㄦ湡涓湁涓€绯诲垪鎻掍欢鍦ㄥ仛鍚堥€傜殑鏃舵満鍋氬悎閫備簨鎯咃紝姣斿 UglifyPlugin 浼氬湪 loader 杞崲閫掑綊瀹屽缁撴灉浣跨敤 UglifyJs 鍘嬬缉銆岃鐩栦箣鍓嶇殑缁撴灉銆?/strong>銆?br>銆怞S銆?200琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒锛堜汉浜洪兘鑳藉浼氾級


4.2 浠g爜瀹炵幇

鎵嬪啓 Webpack 闇€瑕佸疄鐜颁互涓嬩笁涓牳蹇冩柟娉曪細

  • createAssets : 鏀堕泦鍜屽鐞嗘枃浠剁殑浠g爜锛?
  • createGraph 锛氭牴鎹叆鍙f枃浠讹紝杩斿洖鎵€鏈夋枃浠朵緷璧栧浘锛?
  • bundle : 鏍规嵁渚濊禆鍥炬暣涓唬鐮佸苟杈撳嚭锛?

1. createAssets

function createAssets(filename){
const content = fs.readFileSync(filename, "utf-8"); // 鏍规嵁鏂囦欢鍚嶈鍙栨枃浠跺唴瀹?/span>

// 灏嗚鍙栧埌鐨勪唬鐮佸唴瀹癸紝杞崲涓?AST
const ast = parser.parse(content, {
sourceType: "module" // 鎸囧畾婧愮爜绫诲瀷
})
const dependencies = []; // 鐢ㄤ簬鏀堕泦鏂囦欢渚濊禆鐨勮矾寰?/span>

// 閫氳繃 traverse 鎻愪緵鐨勬搷浣?AST 鐨勬柟娉曪紝鑾峰彇姣忎釜鑺傜偣鐨勪緷璧栬矾寰?/span>
traverse(ast, {
ImportDeclaration: ({node}) => {
dependencies.push(node.source.value);
}
});

// 閫氳繃 AST 灏?ES6 浠g爜杞崲鎴?ES5 浠g爜
const { code } = babel.transformFromAstSync(ast, null, {
presets: ["@babel/preset-env"]
});

let id = moduleId++;
return {
id,
filename,
code,
dependencies
}
}

2. createGraph

function createGraph(entry) {
const mainAsset = createAssets(entry); // 鑾峰彇鍏ュ彛鏂囦欢涓嬬殑鍐呭
const queue = [mainAsset];
for(const asset of queue){
const dirname = path.dirname(asset.filename);
asset.mapping = {};
asset.dependencies.forEach(relativePath => {
const absolutePath = path.join(dirname, relativePath); // 杞崲鏂囦欢璺緞涓虹粷瀵硅矾寰?/span>
const child = createAssets(absolutePath);
asset.mapping[relativePath] = child.id;
queue.push(child); // 閫掑綊鍘婚亶鍘嗘墍鏈夊瓙鑺傜偣鐨勬枃浠?/span>
})
}
return queue;
}

3. bunlde

function bundle(graph) {
let modules = "";
graph.forEach(item => {
modules += `
${item.id}: [
function (require, module, exports){
${item.code}
},
${JSON.stringify(item.mapping)}
],
`

})
return `
(function(modules){
function require(id){
const [fn, mapping] = modules[id];
function localRequire(relativePath){
return require(mapping[relativePath]);
}

const module = {
exports: {}
}

fn(localRequire, module, module.exports);

return module.exports;
}
require(0);
})({${modules}})
`

}


浜斻€佹€荤粨

鏈枃浠庣紪璇戝櫒姒傚康鍜屽熀鏈伐浣滄祦绋嬪紑濮嬩粙缁嶏紝鐒跺悗閫氳繃 The Super Tiny Compiler 璇戝櫒婧愮爜锛岃缁嗕粙缁嶆牳蹇冨伐浣滄祦绋嬪疄鐜帮紝鍖呮嫭銆岃瘝娉曞垎鏋愬櫒銆?/strong>銆?span class="mq-774">銆岃娉曞垎鏋愬櫒銆?/strong>銆?span class="mq-775">銆岄亶鍘嗗櫒銆?/strong>鍜?span class="mq-776">銆岃浆鎹㈠櫒銆?/strong>鐨勫熀鏈疄鐜帮紝鏈€鍚庨€氳繃銆屼唬鐮佺敓鎴愬櫒銆?/strong>锛屽皢鍚勪釜闃舵浠g爜缁撳悎璧锋潵锛屽疄鐜颁簡杩欎釜鍙风О銆屽彲鑳芥槸鏈夊彶浠ユ潵鏈€灏忕殑缂栬瘧鍣ㄣ€傘€?/strong>
鏈枃涔熺畝瑕佷粙缁嶄簡銆屾墜鍐?Webpack 鐨勫疄鐜般€?/strong>锛岄渶瑕佽鑰呰嚜琛屽畬鍠勫拰娣卞叆鍝燂紒
銆屾槸涓嶆槸瑙夊緱寰堢濂噡銆?/strong>

褰撶劧閫氳繃鏈枃瀛︿範锛屼篃浠呬粎鏄紪璇戝櫒鐩稿叧鐭ヨ瘑鐨勮竟灞变竴鑴氾紝瑕佸鐨勭煡璇嗚繕鏈夐潪甯稿锛屼笉杩囧ソ鐨勫紑澶达紝鏇磋兘淇冭繘鎴戜滑瀛︿範鍔ㄥ姏銆傚姞娌癸紒

鏈€鍚庯紝鏂囦腑浠嬬粛鍒扮殑浠g爜锛屾垜瀛樻斁鍦?Github 涓婏細

  1. [learning]the-super-tiny-compiler.js [4]
  2. [writing]webpack-compiler.js [5]

鍏€佸弬鑰冭祫鏂?/span>

  1. 銆奣he Super Tiny Compiler銆? [6]
  2. 銆婃湁鍙蹭互鏉ユ渶灏忕殑缂栬瘧鍣ㄦ簮鐮佽В鏋愩€? [7]
  3. 銆夾ngular 2 JIT vs AOT銆? [8]

Reference

[1]

https://segmentfault.com/a/1190000008739157: https://segmentfault.com/a/1190000008739157

[2]

缂栬瘧鍣? https://zh.wikipedia.org/wiki/%E7%B7%A8%E8%AD%AF%E5%99%A8?wprov=srpw1_0

[3]

The Super Tiny Compiler: https://the-super-tiny-compiler.glitch.me/

[4]

[learning]the-super-tiny-compiler.js: https://github.com/pingan8787/Leo-JavaScript/blob/master/Cute-Frontend/learningSourceCode/%5Blearning%5Dthe-super-tiny-compiler.js

[5]

[writing]webpack-compiler.js: https://github.com/pingan8787/Leo-JavaScript/blob/master/Cute-Frontend/learningSourceCode/%5Bwriting%5Dwebpack-compiler.js

[6]

銆奣he Super Tiny Compiler銆? https://the-super-tiny-compiler.glitch.me/

[7]

銆婃湁鍙蹭互鏉ユ渶灏忕殑缂栬瘧鍣ㄦ簮鐮佽В鏋愩€? https://segmentfault.com/a/1190000016402699

[8]

銆夾ngular 2 JIT vs AOT銆? https://segmentfault.com/a/1190000008739157



END





鎺ㄨ崘闃呰









以上是关于銆怞S銆?200琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒锛堜汉浜洪兘鑳藉浼氾級的主要内容,如果未能解决你的问题,请参考以下文章

200琛孞S浠g爜锛屽甫浣犲疄鐜板井鍨嬩唬鐮佺紪璇戝櫒锛堜汉浜洪兘鑳藉浼氾級

瀹炵幇涓€涓唬鐮佺紪璇戝櫒锛?00琛孞S浠g爜锛?/h1>

[娣卞叆娴呭嚭LB]鎵嬫妸鎵嬪甫浣犲疄鐜颁竴涓礋杞藉潎琛″櫒

Android MVP + 娉涘瀷锛屽疄鐜颁簡鍙嬪ソVP浜や簰鍙夾ctivity娼滃湪鐨勫唴瀛樻硠闇茬殑浼樺寲

C 鍜?C++ 浜掔浉璋冪敤

銆怞ava123銆慗ava浠g爜鐨勫彲瑙嗗寲