瀹炵幇涓€涓唬鐮佺紪璇戝櫒锛?00琛孞S浠g爜锛?/h1> Posted 鍏ㄦ爤鍓嶇绮鹃€?/a>
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了瀹炵幇涓€涓唬鐮佺紪璇戝櫒锛?00琛孞S浠g爜锛?/h1>
相关的知识,希望对你有一定的参考价值。
鉂?/span>
鉂?/span>
鍏堥棶澶у涓€鍙ワ紝鏃ュ父椤圭洰寮€鍙戜腑浣犺兘绂诲紑 ES6 鍚楋紵
涓€銆佸墠瑷€
瀵逛簬鍓嶇鍚屽鏉ヨ锛岀紪璇戝櫒鍙兘閫傚悎绁炲鐨勯瓟鐩掟煄侊紝琛ㄩ潰鏅€氾紝浣嗗父甯哥粰鎴戜滑鎯婂枩銆?br>缂栬瘧鍣紝椤惧悕鎬濅箟锛岀敤鏉ョ紪璇戯紝缂栬瘧浠€涔堝憿锛熷綋鐒舵槸缂栬瘧浠g爜鍜煂广€?br>
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-20">銆?00琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒銆?/strong>銆?/p>
浜屻€佺紪璇戝櫒浠嬬粛
2.1 绋嬪簭杩愯鏂瑰紡
鐜颁唬绋嬪簭涓昏鏈変袱绉嶇紪璇戞ā寮忥細闈欐€佺紪璇戝拰鍔ㄦ€佽В閲娿€傛帹鑽愪竴绡囨枃绔犮€夾ngular 2 JIT vs AOT銆嬩粙缁嶅緱闈炲父璇︾粏銆?/p>
闈欐€佺紪璇?/span>
绠€绉?銆孉OT銆?/strong>锛圓head-Of-Time锛夊嵆 銆屾彁鍓嶇紪璇戙€?/strong> 锛岄潤鎬佺紪璇戠殑绋嬪簭浼氬湪鎵ц鍓嶏紝浼氫娇鐢ㄦ寚瀹氱紪璇戝櫒锛屽皢鍏ㄩ儴浠g爜缂栬瘧鎴愭満鍣ㄧ爜銆?br>
锛堝浘鐗囨潵鑷細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>锛堝浘鐗囨潵鑷細https://segmentfault.com/a/1190000008739157[1]锛?br>
鍦?Angular 鐨?JIT 缂栬瘧妯″紡寮€鍙戞祦绋嬪涓嬶細
-
浣跨敤 TypeScript 寮€鍙?Angular 搴旂敤
-
杩愯 tsc 缂栬瘧 TypeScript 浠g爜
-
浣跨敤 Webpack 鎴?Gulp 绛夊叾浠栧伐鍏锋瀯寤洪」鐩紝濡備唬鐮佸帇缂┿€佸悎骞剁瓑
-
閮ㄧ讲搴旂敤
AOT vs JIT
AOT 缂栬瘧娴佺▼锛?/strong>锛堝浘鐗囨潵鑷細https://segmentfault.com/a/1190000008739157锛?/p>
JIT 缂栬瘧娴佺▼锛?/strong>锛堝浘鐗囨潵鑷細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-107">[2]宸ヤ綔娴佺▼浠嬬粛锛?/p>
鉂?/span>
涓€涓幇浠g紪璇戝櫒鐨勪富瑕佸伐浣滄祦绋嬪涓嬶細婧愪唬鐮侊紙source code锛夆啋 棰勫鐞嗗櫒锛坧reprocessor锛夆啋 缂栬瘧鍣紙compiler锛夆啋 姹囩紪绋嬪簭锛坅ssembler锛夆啋 鐩爣浠g爜锛坥bject code锛夆啋 閾炬帴鍣紙linker锛夆啋 鍙墽琛屾枃浠讹紙executables锛夛紝鏈€鍚庢墦鍖呭ソ鐨勬枃浠跺氨鍙互缁欑數鑴戝幓鍒よ杩愯浜嗐€?/p>
鉂?/span>
杩欓噷鏇村己璋冧簡缂栬瘧鍣ㄧ殑浣滅敤锛?span class="mq-115">銆屽皢鍘熷绋嬪簭浣滀负杈撳叆锛岀炕璇戜骇鐢熺洰鏍囪瑷€鐨勭瓑浠风▼搴忋€?/strong>銆?/p>
鐩墠缁濆ぇ澶氭暟鐜颁唬缂栬瘧鍣ㄥ伐浣滄祦绋嬪熀鏈被浼硷紝鍖呮嫭涓変釜鏍稿績闃舵锛?/p>
-
銆岃В鏋愶紙Parsing锛夈€?/strong> 锛氶€氳繃璇嶆硶鍒嗘瀽鍜岃娉曞垎鏋愶紝灏嗗師濮嬩唬鐮佸瓧绗︿覆瑙f瀽鎴?
銆屾娊璞¤娉曟爲锛圓bstract Syntax Tree锛夈€?/strong>锛?
-
銆岃浆鎹紙Transformation锛夈€?/strong>锛氬鎶借薄璇硶鏍戣繘琛岃浆鎹㈠鐞嗘搷浣滐紱
-
銆岀敓鎴愪唬鐮侊紙Code Generation锛夈€?/strong>锛氬皢杞崲涔嬪悗鐨?AST 瀵硅薄鐢熸垚鐩爣璇█浠g爜瀛楃涓层€?
涓夈€佺紪璇戝櫒瀹炵幇
鏈枃灏嗛€氳繃 銆?span class="mq-135">The Super Tiny Compiler[3]銆?/strong> 婧愮爜瑙h锛屽涔犲浣曞疄鐜颁竴涓交閲忕紪璇戝櫒锛屾渶缁?span class="mq-137">銆屽疄鐜板皢涓嬮潰鍘熷浠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>3.1 The Super Tiny Compiler 宸ヤ綔娴佺▼
鐜板湪瀵圭収鍓嶉潰缂栬瘧鍣ㄧ殑涓変釜鏍稿績闃舵锛屼簡瑙d笅 The Super Tiny Compiler 缂栬瘧鍣ㄦ牳蹇冨伐浣滄祦绋嬶細
鍥句腑璇︾粏娴佺▼濡備笅锛?/strong>
-
鎵ц
銆屽叆鍙e嚱鏁般€?/strong>锛岃緭鍏?
銆屽師濮嬩唬鐮佸瓧绗︿覆銆?/strong>浣滀负鍙傛暟锛?
// 鍘熷浠g爜瀛楃涓?/span>
(add 2 (subtract 4 2))
-
杩涘叆
銆岃В鏋愰樁娈碉紙Parsing锛夈€?/strong>锛屽師濮嬩唬鐮佸瓧绗︿覆閫氳繃
銆岃瘝娉曞垎鏋愬櫒锛圱okenizer锛?span class="mq-180">銆?/strong>杞崲涓?
銆?/strong>璇嶆硶鍗曞厓鏁扮粍銆?/strong>锛?/strong>鐒跺悗鍐嶉€氳繃
銆岃瘝娉曞垎鏋愬櫒锛圥arser锛?span class="mq-185">銆?/strong>灏?
銆?/strong>璇嶆硶鍗曞厓鏁扮粍銆嶈浆鎹负
銆?/strong>鎶借薄璇硶鏍戯紙Abstract Syntax Tree 绠€绉?AST锛夈€嶏紝骞惰繑鍥烇紱
-
杩涘叆
銆岃浆鎹㈤樁娈碉紙Transformation锛夈€?/strong>锛屽皢涓婁竴姝ョ敓鎴愮殑
銆孉ST 瀵硅薄銆?/strong> 瀵煎叆
銆岃浆鎹㈠櫒锛圱ransformer锛夈€?/strong>锛岄€氳繃
銆岃浆鎹㈠櫒銆?/strong>涓殑
銆岄亶鍘嗗櫒锛圱raverser锛夈€?/strong>锛屽皢浠g爜杞崲涓烘垜浠墍闇€鐨?
銆屾柊鐨?AST 瀵硅薄銆?/strong>锛?
-
杩涘叆
銆屼唬鐮佺敓鎴愰樁娈碉紙Code Generation锛夈€?/strong>锛屽皢涓婁竴姝ヨ繑鍥炵殑
銆屾柊 AST 瀵硅薄銆?/strong>閫氳繃
銆屼唬鐮佺敓鎴愬櫒锛圕odeGenerator锛夈€?/strong>锛岃浆鎹㈡垚
銆孞avaScript Code銆?/strong>锛?
-
銆屼唬鐮佺紪璇戠粨鏉熴€?/strong>锛岃繑鍥?
銆孞avaScript Code銆?/strong>銆?
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-240">銆岃瘝娉曞垎鏋愬櫒鏂规硶銆?/strong> tokenizer
鍜?span class="mq-242">銆岃娉曞垎鏋愬櫒鏂规硶銆?/strong> parser
鐒跺悗鍒嗗埆瀹炵幇锛?br>
// 璇嶆硶鍒嗘瀽鍣?鍙傛暟锛氬師濮嬩唬鐮佸瓧绗︿覆 input
function tokenizer(input) {};
// 璇硶鍒嗘瀽鍣?鍙傛暟锛氳瘝娉曞崟鍏冩暟缁則okens
function parser(tokens) {};
璇嶆硶鍒嗘瀽鍣?/span>
銆岃瘝娉曞垎鏋愬櫒鏂规硶銆?/strong> tokenizer
鐨勪富瑕佷换鍔★細閬嶅巻鏁翠釜鍘熷浠g爜瀛楃涓诧紝灏嗗師濮嬩唬鐮佸瓧绗︿覆杞崲涓?span class="mq-264">銆岃瘝娉曞崟鍏冩暟缁勶紙tokens锛夈€?/strong>锛屽苟杩斿洖銆?br>鍦ㄩ亶鍘嗚繃绋嬩腑锛屽尮閰嶆瘡绉嶅瓧绗﹀苟澶勭悊鎴?span class="mq-265">銆岃瘝娉曞崟鍏冦€?/strong>鍘嬪叆銆岃瘝娉曞崟鍏冩暟缁勩€?/strong>锛屽褰撳尮閰嶅埌宸︽嫭鍙凤紙 (
锛夋椂锛屽皢寰€銆岃瘝娉曞崟鍏冩暟缁勶紙tokens锛?span>銆屽帇鍏ヤ竴涓€?/strong>璇嶆硶鍗曞厓瀵硅薄銆?/strong>锛?code class="mq-269">{type: 'paren', value:'('}锛夈€?br>
// 璇嶆硶鍒嗘瀽鍣?鍙傛暟锛氬師濮嬩唬鐮佸瓧绗︿覆 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-365">銆岃瘝娉曞垎鏋愬櫒銆?/strong>杩斿洖鐨?span class="mq-366">銆岃瘝娉曞崟鍏冩暟缁勩€?/strong>锛岃浆鎹负鑳藉鎻忚堪璇硶鎴愬垎鍙婂叾鍏崇郴鐨勪腑闂村舰寮忥紙銆屾娊璞¤娉曟爲 AST銆?/strong>锛夈€?br>
// 璇硶鍒嗘瀽鍣?鍙傛暟锛氳瘝娉曞崟鍏冩暟缁則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-493">銆岃浆鎹㈠櫒銆?/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-537">銆岀淮鎶ゆ柊鏃?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>
鍏跺疄澶氭暟缂栬瘧鍣ㄧ殑宸ヤ綔娴佺▼閮藉ぇ鑷寸浉鍚岋細
鍥涖€佹墜鍐?Webpack 缂栬瘧鍣?/span>
鏍规嵁涔嬪墠浠嬬粛鐨?The Super Tiny Compiler缂栬瘧鍣ㄦ牳蹇冨伐浣滄祦绋嬶紝鍐嶆潵鎵嬪啓 Webpack 鐨勭紪璇戝櫒锛屼細璁╀綘鏈夌浼椾韩涓濇粦鐨勬劅瑙墌
璇濊锛屾湁浜涢潰璇曞畼鍠滄闂繖涓憿銆傚綋鐒讹紝鎵嬪啓涓€閬嶈兘璁╂垜浠洿浜嗚В Webpack 鐨勬瀯寤烘祦绋嬶紝杩欎釜绔犺妭鎴戜滑绠€瑕佷粙缁嶄竴涓嬨€?/p>
4.1 Webpack 鏋勫缓娴佺▼鍒嗘瀽
浠庡惎鍔ㄦ瀯寤哄埌杈撳嚭缁撴灉涓€绯诲垪杩囩▼锛?/p>
-
銆屽垵濮嬪寲鍙傛暟銆?/strong>
瑙f瀽 Webpack 閰嶇疆鍙傛暟锛屽悎骞?Shell 浼犲叆鍜?webpack.config.js
鏂囦欢閰嶇疆鐨勫弬鏁帮紝褰㈡垚鏈€鍚庣殑閰嶇疆缁撴灉銆?br>
-
銆屽紑濮嬬紪璇戙€?/strong>
涓婁竴姝ュ緱鍒扮殑鍙傛暟鍒濆鍖?compiler
瀵硅薄锛屾敞鍐屾墍鏈夐厤缃殑鎻掍欢锛屾彃浠剁洃鍚?Webpack 鏋勫缓鐢熷懡鍛ㄦ湡鐨勪簨浠惰妭鐐癸紝鍋氬嚭鐩稿簲鐨勫弽搴旓紝鎵ц瀵硅薄鐨?run
鏂规硶寮€濮嬫墽琛岀紪璇戙€?br>
-
銆岀‘瀹氬叆鍙c€?/strong>
浠庨厤缃殑 entry
鍏ュ彛锛屽紑濮嬭В鏋愭枃浠舵瀯寤?AST 璇硶鏍戯紝鎵惧嚭渚濊禆锛岄€掑綊涓嬪幓銆?br>
-
銆岀紪璇戞ā鍧椼€?/strong>
閫掑綊涓牴鎹?span class="mq-655">銆屾枃浠剁被鍨嬨€?/strong>鍜?銆宭oader 閰嶇疆銆?/strong>锛岃皟鐢ㄦ墍鏈夐厤缃殑 loader 瀵规枃浠惰繘琛岃浆鎹紝鍐嶆壘鍑鸿妯″潡渚濊禆鐨勬ā鍧楋紝鍐嶉€掑綊鏈楠ょ洿鍒版墍鏈夊叆鍙d緷璧栫殑鏂囦欢閮界粡杩囦簡鏈楠ょ殑澶勭悊銆?br>
-
銆屽畬鎴愭ā鍧楃紪璇戝苟杈撳嚭銆?/strong>
閫掑綊瀹屼簨鍚庯紝寰楀埌姣忎釜鏂囦欢缁撴灉锛屽寘鍚瘡涓ā鍧椾互鍙婁粬浠箣闂寸殑渚濊禆鍏崇郴锛屾牴鎹?entry
閰嶇疆鐢熸垚浠g爜鍧?chunk
銆?br>
-
銆岃緭鍑哄畬鎴愩€?/strong>
杈撳嚭鎵€鏈夌殑 chunk
鍒版枃浠剁郴缁熴€?br>
娉ㄦ剰锛氬湪鏋勫缓鐢熷懡鍛ㄦ湡涓湁涓€绯诲垪鎻掍欢鍦ㄥ仛鍚堥€傜殑鏃舵満鍋氬悎閫備簨鎯咃紝姣斿 UglifyPlugin
浼氬湪 loader 杞崲閫掑綊瀹屽缁撴灉浣跨敤 UglifyJs
鍘嬬缉銆岃鐩栦箣鍓嶇殑缁撴灉銆?/strong>銆?br>
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-771">銆岃娉曞垎鏋愬櫒銆?/strong>銆?span class="mq-772">銆岄亶鍘嗗櫒銆?/strong>鍜?span class="mq-773">銆岃浆鎹㈠櫒銆?/strong>鐨勫熀鏈疄鐜帮紝鏈€鍚庨€氳繃銆屼唬鐮佺敓鎴愬櫒銆?/strong>锛屽皢鍚勪釜闃舵浠g爜缁撳悎璧锋潵锛屽疄鐜颁簡杩欎釜鍙风О銆屽彲鑳芥槸鏈夊彶浠ユ潵鏈€灏忕殑缂栬瘧鍣ㄣ€傘€?/strong>
鏈枃涔熺畝瑕佷粙缁嶄簡銆屾墜鍐?Webpack 鐨勫疄鐜般€?/strong>锛岄渶瑕佽鑰呰嚜琛屽畬鍠勫拰娣卞叆鍝燂紒
銆屾槸涓嶆槸瑙夊緱寰堢濂噡銆?/strong>
褰撶劧閫氳繃鏈枃瀛︿範锛屼篃浠呬粎鏄紪璇戝櫒鐩稿叧鐭ヨ瘑鐨勮竟灞变竴鑴氾紝瑕佸鐨勭煡璇嗚繕鏈夐潪甯稿锛屼笉杩囧ソ鐨勫紑澶达紝鏇磋兘淇冭繘鎴戜滑瀛︿範鍔ㄥ姏銆傚姞娌癸紒
鏈€鍚庯紝鏂囦腑浠嬬粛鍒扮殑浠g爜锛屾垜瀛樻斁鍦?Github 涓婏細
-
[learning]the-super-tiny-compiler.js
[4]
-
[writing]webpack-compiler.js
[5]
鍏€佸弬鑰冭祫鏂?/span>
-
銆奣he Super Tiny Compiler銆?
[6]
-
銆婃湁鍙蹭互鏉ユ渶灏忕殑缂栬瘧鍣ㄦ簮鐮佽В鏋愩€?
[7]
-
銆夾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
以上是关于瀹炵幇涓€涓唬鐮佺紪璇戝櫒锛?00琛孞S浠g爜锛?/h1>
Posted 鍏ㄦ爤鍓嶇绮鹃€?/a>
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了瀹炵幇涓€涓唬鐮佺紪璇戝櫒锛?00琛孞S浠g爜锛?/h1>
鉂?/span> 鉂?/span>
鍏堥棶澶у涓€鍙ワ紝鏃ュ父椤圭洰寮€鍙戜腑浣犺兘绂诲紑 ES6 鍚楋紵
涓€銆佸墠瑷€
瀵逛簬鍓嶇鍚屽鏉ヨ锛岀紪璇戝櫒鍙兘閫傚悎绁炲鐨勯瓟鐩掟煄侊紝琛ㄩ潰鏅€氾紝浣嗗父甯哥粰鎴戜滑鎯婂枩銆?br>缂栬瘧鍣紝椤惧悕鎬濅箟锛岀敤鏉ョ紪璇戯紝缂栬瘧浠€涔堝憿锛熷綋鐒舵槸缂栬瘧浠g爜鍜煂广€?br>
浣跨敤鍦烘櫙闈炲父涔嬪锛屾垜鐨勫弻鎵嬮兘鏁颁笉杩囨潵浜嗐€傪煒?br>铏界劧鐜板湪绀惧尯宸茬粡鏈夐潪甯稿宸ュ叿鑳戒负鎴戜滑瀹屾垚涓婅堪宸ヤ綔锛屼絾浜嗚В涓€浜涚紪璇戝師鐞嗘槸寰堟湁蹇呰鐨勩€傛帴涓嬫潵杩涘叆鏈枃涓婚锛?span class="mq-20">銆?00琛孞S浠g爜锛屽甫浣犲疄鐜颁唬鐮佺紪璇戝櫒銆?/strong>銆?/p>
浜屻€佺紪璇戝櫒浠嬬粛
2.1 绋嬪簭杩愯鏂瑰紡
鐜颁唬绋嬪簭涓昏鏈変袱绉嶇紪璇戞ā寮忥細闈欐€佺紪璇戝拰鍔ㄦ€佽В閲娿€傛帹鑽愪竴绡囨枃绔犮€夾ngular 2 JIT vs AOT銆嬩粙缁嶅緱闈炲父璇︾粏銆?/p>
闈欐€佺紪璇?/span>
绠€绉?銆孉OT銆?/strong>锛圓head-Of-Time锛夊嵆 銆屾彁鍓嶇紪璇戙€?/strong> 锛岄潤鎬佺紪璇戠殑绋嬪簭浼氬湪鎵ц鍓嶏紝浼氫娇鐢ㄦ寚瀹氱紪璇戝櫒锛屽皢鍏ㄩ儴浠g爜缂栬瘧鎴愭満鍣ㄧ爜銆?br>
锛堝浘鐗囨潵鑷細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>锛堝浘鐗囨潵鑷細https://segmentfault.com/a/1190000008739157[1]锛?br>
鍦?Angular 鐨?JIT 缂栬瘧妯″紡寮€鍙戞祦绋嬪涓嬶細
-
浣跨敤 TypeScript 寮€鍙?Angular 搴旂敤 -
杩愯 tsc 缂栬瘧 TypeScript 浠g爜 -
浣跨敤 Webpack 鎴?Gulp 绛夊叾浠栧伐鍏锋瀯寤洪」鐩紝濡備唬鐮佸帇缂┿€佸悎骞剁瓑 -
閮ㄧ讲搴旂敤
AOT vs JIT
AOT 缂栬瘧娴佺▼锛?/strong>锛堝浘鐗囨潵鑷細https://segmentfault.com/a/1190000008739157锛?/p>
JIT 缂栬瘧娴佺▼锛?/strong>锛堝浘鐗囨潵鑷細https://segmentfault.com/a/1190000008739157锛?/p>
闄ゆ涔嬪 AOT 杩樻湁浠ヤ笅浼樼偣锛?/p>
鎽樻妱缁村熀鐧剧涓 缂栬瘧鍣?sup class="mq-107">[2]宸ヤ綔娴佺▼浠嬬粛锛?/p>
涓€涓幇浠g紪璇戝櫒鐨勪富瑕佸伐浣滄祦绋嬪涓嬶細婧愪唬鐮侊紙source code锛夆啋 棰勫鐞嗗櫒锛坧reprocessor锛夆啋 缂栬瘧鍣紙compiler锛夆啋 姹囩紪绋嬪簭锛坅ssembler锛夆啋 鐩爣浠g爜锛坥bject code锛夆啋 閾炬帴鍣紙linker锛夆啋 鍙墽琛屾枃浠讹紙executables锛夛紝鏈€鍚庢墦鍖呭ソ鐨勬枃浠跺氨鍙互缁欑數鑴戝幓鍒よ杩愯浜嗐€?/p>
鉂?/span>
杩欓噷鏇村己璋冧簡缂栬瘧鍣ㄧ殑浣滅敤锛?span class="mq-115">銆屽皢鍘熷绋嬪簭浣滀负杈撳叆锛岀炕璇戜骇鐢熺洰鏍囪瑷€鐨勭瓑浠风▼搴忋€?/strong>銆?/p>
鐩墠缁濆ぇ澶氭暟鐜颁唬缂栬瘧鍣ㄥ伐浣滄祦绋嬪熀鏈被浼硷紝鍖呮嫭涓変釜鏍稿績闃舵锛?/p>
鏈枃灏嗛€氳繃 銆?span class="mq-135">The Super Tiny Compiler[3]銆?/strong> 婧愮爜瑙h锛屽涔犲浣曞疄鐜颁竴涓交閲忕紪璇戝櫒锛屾渶缁?span class="mq-137">銆屽疄鐜板皢涓嬮潰鍘熷浠g爜瀛楃涓诧紙Lisp 椋庢牸鐨勫嚱鏁拌皟鐢級缂栬瘧鎴?JavaScript 鍙墽琛岀殑浠g爜銆?/strong>銆?br> 鐜板湪瀵圭収鍓嶉潰缂栬瘧鍣ㄧ殑涓変釜鏍稿績闃舵锛屼簡瑙d笅 The Super Tiny Compiler 缂栬瘧鍣ㄦ牳蹇冨伐浣滄祦绋嬶細 鍥句腑璇︾粏娴佺▼濡備笅锛?/strong> 3.2 鍏ュ彛鏂规硶
棣栧厛瀹氫箟涓€涓叆鍙f柟娉? 鍦ㄨВ鏋愰樁娈典腑锛屾垜浠畾涔?span class="mq-240">銆岃瘝娉曞垎鏋愬櫒鏂规硶銆?/strong> 銆岃瘝娉曞垎鏋愬櫒鏂规硶銆?/strong> 銆岃娉曞垎鏋愬櫒鏂规硶銆?/strong> 鍦ㄨ浆鎹㈤樁娈典腑锛屽畾涔変簡杞崲鍣? 鎺ヤ笅鏉ュ埌浜嗘渶鍚庝竴姝ワ紝鎴戜滑瀹氫箟銆屼唬鐮佺敓鎴愬櫒銆?/strong> 鎴涓婁竴姝ワ紝鎴戜滑瀹屾垚绠€鏄撶紪璇戝櫒鐨勪唬鐮佸紑鍙戙€傛帴涓嬫潵閫氳繃鍓嶉潰鍘熷闇€姹傜殑浠g爜锛屾祴璇曠紪璇戝櫒鏁堟灉濡備綍锛?br> 鎬荤粨 The Super Tiny Compiler 缂栬瘧鍣ㄦ暣涓伐浣滄祦绋嬶細 鍏跺疄澶氭暟缂栬瘧鍣ㄧ殑宸ヤ綔娴佺▼閮藉ぇ鑷寸浉鍚岋細 鏍规嵁涔嬪墠浠嬬粛鐨?The Super Tiny Compiler缂栬瘧鍣ㄦ牳蹇冨伐浣滄祦绋嬶紝鍐嶆潵鎵嬪啓 Webpack 鐨勭紪璇戝櫒锛屼細璁╀綘鏈夌浼椾韩涓濇粦鐨勬劅瑙墌 浠庡惎鍔ㄦ瀯寤哄埌杈撳嚭缁撴灉涓€绯诲垪杩囩▼锛?/p>
瑙f瀽 Webpack 閰嶇疆鍙傛暟锛屽悎骞?Shell 浼犲叆鍜? 涓婁竴姝ュ緱鍒扮殑鍙傛暟鍒濆鍖? 浠庨厤缃殑 閫掑綊涓牴鎹?span class="mq-655">銆屾枃浠剁被鍨嬨€?/strong>鍜?銆宭oader 閰嶇疆銆?/strong>锛岃皟鐢ㄦ墍鏈夐厤缃殑 loader 瀵规枃浠惰繘琛岃浆鎹紝鍐嶆壘鍑鸿妯″潡渚濊禆鐨勬ā鍧楋紝鍐嶉€掑綊鏈楠ょ洿鍒版墍鏈夊叆鍙d緷璧栫殑鏂囦欢閮界粡杩囦簡鏈楠ょ殑澶勭悊銆?br> 閫掑綊瀹屼簨鍚庯紝寰楀埌姣忎釜鏂囦欢缁撴灉锛屽寘鍚瘡涓ā鍧椾互鍙婁粬浠箣闂寸殑渚濊禆鍏崇郴锛屾牴鎹? 杈撳嚭鎵€鏈夌殑 鎵嬪啓 Webpack 闇€瑕佸疄鐜颁互涓嬩笁涓牳蹇冩柟娉曪細 鏈枃浠庣紪璇戝櫒姒傚康鍜屽熀鏈伐浣滄祦绋嬪紑濮嬩粙缁嶏紝鐒跺悗閫氳繃 The Super Tiny Compiler 璇戝櫒婧愮爜锛岃缁嗕粙缁嶆牳蹇冨伐浣滄祦绋嬪疄鐜帮紝鍖呮嫭銆岃瘝娉曞垎鏋愬櫒銆?/strong>銆?span class="mq-771">銆岃娉曞垎鏋愬櫒銆?/strong>銆?span class="mq-772">銆岄亶鍘嗗櫒銆?/strong>鍜?span class="mq-773">銆岃浆鎹㈠櫒銆?/strong>鐨勫熀鏈疄鐜帮紝鏈€鍚庨€氳繃銆屼唬鐮佺敓鎴愬櫒銆?/strong>锛屽皢鍚勪釜闃舵浠g爜缁撳悎璧锋潵锛屽疄鐜颁簡杩欎釜鍙风О銆屽彲鑳芥槸鏈夊彶浠ユ潵鏈€灏忕殑缂栬瘧鍣ㄣ€傘€?/strong> https://segmentfault.com/a/1190000008739157: https://segmentfault.com/a/1190000008739157 缂栬瘧鍣? https://zh.wikipedia.org/wiki/%E7%B7%A8%E8%AD%AF%E5%99%A8?wprov=srpw1_0 The Super Tiny Compiler: https://the-super-tiny-compiler.glitch.me/ [learning]the-super-tiny-compiler.js: https://github.com/pingan8787/Leo-JavaScript/blob/master/Cute-Frontend/learningSourceCode/%5Blearning%5Dthe-super-tiny-compiler.js [writing]webpack-compiler.js: https://github.com/pingan8787/Leo-JavaScript/blob/master/Cute-Frontend/learningSourceCode/%5Bwriting%5Dwebpack-compiler.js 銆奣he Super Tiny Compiler銆? https://the-super-tiny-compiler.glitch.me/ 銆婃湁鍙蹭互鏉ユ渶灏忕殑缂栬瘧鍣ㄦ簮鐮佽В鏋愩€? https://segmentfault.com/a/1190000016402699 銆夾ngular 2 JIT vs AOT銆? https://segmentfault.com/a/1190000008739157
鐗规€?/th>
AOT
JIT
缂栬瘧骞冲彴
(Server) 鏈嶅姟鍣?/td>
(Browser) 娴忚鍣?/td>
缂栬瘧鏃舵満
Build (鏋勫缓闃舵)
Runtime (杩愯鏃?
鍖呭ぇ灏?/td>
杈冨皬
杈冨ぇ
鎵ц鎬ц兘
鏇村ソ
-
鍚姩鏃堕棿
鏇寸煭
-
2.2 鐜颁唬缂栬瘧鍣ㄥ伐浣滄祦绋?/span>
鉂?/span>
涓夈€佺紪璇戝櫒瀹炵幇
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>3.1 The Super Tiny Compiler 宸ヤ綔娴佺▼
// 鍘熷浠g爜瀛楃涓?/span>
(add 2 (subtract 4 2))
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瀽闃舵
tokenizer
鍜?span class="mq-242">銆岃娉曞垎鏋愬櫒鏂规硶銆?/strong> parser
鐒跺悗鍒嗗埆瀹炵幇锛?br>// 璇嶆硶鍒嗘瀽鍣?鍙傛暟锛氬師濮嬩唬鐮佸瓧绗︿覆 input
function tokenizer(input) {};
// 璇硶鍒嗘瀽鍣?鍙傛暟锛氳瘝娉曞崟鍏冩暟缁則okens
function parser(tokens) {};璇嶆硶鍒嗘瀽鍣?/span>
tokenizer
鐨勪富瑕佷换鍔★細閬嶅巻鏁翠釜鍘熷浠g爜瀛楃涓诧紝灏嗗師濮嬩唬鐮佸瓧绗︿覆杞崲涓?span class="mq-264">銆岃瘝娉曞崟鍏冩暟缁勶紙tokens锛夈€?/strong>锛屽苟杩斿洖銆?br>鍦ㄩ亶鍘嗚繃绋嬩腑锛屽尮閰嶆瘡绉嶅瓧绗﹀苟澶勭悊鎴?span class="mq-265">銆岃瘝娉曞崟鍏冦€?/strong>鍘嬪叆銆岃瘝娉曞崟鍏冩暟缁勩€?/strong>锛屽褰撳尮閰嶅埌宸︽嫭鍙凤紙 (
锛夋椂锛屽皢寰€銆岃瘝娉曞崟鍏冩暟缁勶紙tokens锛?span>銆屽帇鍏ヤ竴涓€?/strong>璇嶆硶鍗曞厓瀵硅薄銆?/strong>锛?code class="mq-269">{type: 'paren', value:'('}锛夈€?br>// 璇嶆硶鍒嗘瀽鍣?鍙傛暟锛氬師濮嬩唬鐮佸瓧绗︿覆 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>
parser
鐨勪富瑕佷换鍔★細灏?span class="mq-365">銆岃瘝娉曞垎鏋愬櫒銆?/strong>杩斿洖鐨?span class="mq-366">銆岃瘝娉曞崟鍏冩暟缁勩€?/strong>锛岃浆鎹负鑳藉鎻忚堪璇硶鎴愬垎鍙婂叾鍏崇郴鐨勪腑闂村舰寮忥紙銆屾娊璞¤娉曟爲 AST銆?/strong>锛夈€?br>// 璇硶鍒嗘瀽鍣?鍙傛暟锛氳瘝娉曞崟鍏冩暟缁則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-493">銆岃浆鎹㈠櫒銆?/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-537">銆岀淮鎶ゆ柊鏃?AST 瀵硅薄銆?/strong>锛岀鐞嗘柟渚匡紝閬垮厤姹℃煋鏃?AST 瀵硅薄銆?br>3.5 浠g爜鐢熸垚
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>
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 43.7 宸ヤ綔娴佺▼灏忕粨
銆?銆乮nput => tokenizer => tokens銆?/strong>
銆?銆乼okens => parser => ast銆?/strong>
銆?銆乤st => transformer => newAst銆?/strong>
銆?銆乶ewAst => generator => output銆?/strong>鍥涖€佹墜鍐?Webpack 缂栬瘧鍣?/span>
璇濊锛屾湁浜涢潰璇曞畼鍠滄闂繖涓憿銆傚綋鐒讹紝鎵嬪啓涓€閬嶈兘璁╂垜浠洿浜嗚В Webpack 鐨勬瀯寤烘祦绋嬶紝杩欎釜绔犺妭鎴戜滑绠€瑕佷粙缁嶄竴涓嬨€?/p>
4.1 Webpack 鏋勫缓娴佺▼鍒嗘瀽
webpack.config.js
鏂囦欢閰嶇疆鐨勫弬鏁帮紝褰㈡垚鏈€鍚庣殑閰嶇疆缁撴灉銆?br>
compiler
瀵硅薄锛屾敞鍐屾墍鏈夐厤缃殑鎻掍欢锛屾彃浠剁洃鍚?Webpack 鏋勫缓鐢熷懡鍛ㄦ湡鐨勪簨浠惰妭鐐癸紝鍋氬嚭鐩稿簲鐨勫弽搴旓紝鎵ц瀵硅薄鐨?run
鏂规硶寮€濮嬫墽琛岀紪璇戙€?br>
entry
鍏ュ彛锛屽紑濮嬭В鏋愭枃浠舵瀯寤?AST 璇硶鏍戯紝鎵惧嚭渚濊禆锛岄€掑綊涓嬪幓銆?br>
entry
閰嶇疆鐢熸垚浠g爜鍧?chunk
銆?br>
chunk
鍒版枃浠剁郴缁熴€?br>
娉ㄦ剰锛氬湪鏋勫缓鐢熷懡鍛ㄦ湡涓湁涓€绯诲垪鎻掍欢鍦ㄥ仛鍚堥€傜殑鏃舵満鍋氬悎閫備簨鎯咃紝姣斿 UglifyPlugin
浼氬湪 loader 杞崲閫掑綊瀹屽缁撴灉浣跨敤 UglifyJs
鍘嬬缉銆岃鐩栦箣鍓嶇殑缁撴灉銆?/strong>銆?br>4.2 浠g爜瀹炵幇
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}})
`
}浜斻€佹€荤粨
鏈枃涔熺畝瑕佷粙缁嶄簡銆屾墜鍐?Webpack 鐨勫疄鐜般€?/strong>锛岄渶瑕佽鑰呰嚜琛屽畬鍠勫拰娣卞叆鍝燂紒
銆屾槸涓嶆槸瑙夊緱寰堢濂噡銆?/strong>
褰撶劧閫氳繃鏈枃瀛︿範锛屼篃浠呬粎鏄紪璇戝櫒鐩稿叧鐭ヨ瘑鐨勮竟灞变竴鑴氾紝瑕佸鐨勭煡璇嗚繕鏈夐潪甯稿锛屼笉杩囧ソ鐨勫紑澶达紝鏇磋兘淇冭繘鎴戜滑瀛︿範鍔ㄥ姏銆傚姞娌癸紒
鏈€鍚庯紝鏂囦腑浠嬬粛鍒扮殑浠g爜锛屾垜瀛樻斁鍦?Github 涓婏細
鍏€佸弬鑰冭祫鏂?/span>
Reference
以上是关于瀹炵幇涓€涓唬鐮佺紪璇戝櫒锛?00琛孞S浠g爜锛?/h1>