国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

前端實(shí)現(xiàn)多文件編譯器

原創(chuàng) 精選
開(kāi)發(fā) 前端
一個(gè)前端可執(zhí)行的小型打包工具就已實(shí)現(xiàn),可以直接在前端進(jìn)行多文件的編輯和執(zhí)行。實(shí)時(shí)上,此過(guò)程僅適用于不方便借助服務(wù)器的場(chǎng)景,如果有條件允許可以借助服務(wù)器,那么編譯過(guò)程最好在服務(wù)端完成,甚至還可以借助 webpack 或 rollup 等打包工具實(shí)現(xiàn)更好的編譯效果。

作者 | 景遇

一、概要

在前端工程中,有時(shí)我們需要在瀏覽器編譯并執(zhí)行一些代碼,這種需求常見(jiàn)于低代碼場(chǎng)景中。例如我們?cè)诖罱〞r(shí)需自定義一部分代碼,這些代碼需要在渲染時(shí)執(zhí)行。為了方便起見(jiàn),我們寫(xiě)的代碼一定是 ES6 語(yǔ)法,如果要在瀏覽器執(zhí)行,那么就必須經(jīng)過(guò)編譯。下面是前端編譯 JS 代碼的一些實(shí)踐。

二、需求描述

  1. 低碼搭建時(shí)需要自定義一部分代碼
  2. 希望代碼是以多文件形式組織的
  3. 可以使用 ESModule 形式導(dǎo)入/導(dǎo)出

三、需求分析

  1. 在瀏覽器編譯代碼必然需要使用 babel 完成;
  2. 如果只有一個(gè) JS 文件,那么可以直接使用 babel 的 transform 函數(shù)編譯;
  3. 如果存在多文件,則文件內(nèi)的變量必須相互隔離,且文件之間能夠通過(guò)某種形式相互引用,并且需要考慮文件之間的依賴(lài)關(guān);

四、核心設(shè)計(jì)

流程

1.變量隔離

由于我們的需求是多文件編輯,各個(gè)文件內(nèi)的變量應(yīng)該相互隔離。最簡(jiǎn)單的辦法是將每個(gè)文的內(nèi)容轉(zhuǎn)成一個(gè)閉包,再通過(guò)固定的接口將每個(gè)文件連接起來(lái)。

假設(shè)有 a.js,內(nèi)容如下:

const a = 1;
const b = 2;

function sum () {
return a + b'
}

sum();

可以將其轉(zhuǎn)為如下形式:

(function() {
const a = 1;
const b = 2;

function sum () {
return a + b'
}

sum();
})();

轉(zhuǎn)成這種形式之后,每個(gè)文件內(nèi)的變量就只會(huì)存在于各自的閉包之內(nèi),互不影響。

五、文件引用

文件之間的相互引用可以通過(guò)定義一種接口規(guī)則實(shí)現(xiàn):

  • 所有文件的引用都將通過(guò)全局變量 module 進(jìn)行;
  • 每個(gè)文件都將對(duì)應(yīng)到 module 上的一個(gè)對(duì)象,key 根據(jù)文件名而定。

1.導(dǎo)出

原文件:

https://back-media.51cto.com/editor/h6e90be6-D8rA67LO

編譯后:

(function() {
__filename = 'a.js';
const a = 1;
var mod = {};
mod.a = a;
module[__filename] = mod;
})()

2.導(dǎo)入

源文件:

// b.js
import { hello } from './a'

hello();

編譯后:

(function() {
__filename = 'b.js';
var $$a = module['a.js'];
$$a.hello();
var mod = {};
module[__filename] = mod;
})()

六、依賴(lài)樹(shù)解析

假設(shè)有一堆文件,我們通過(guò)解析(babel 或正則)后得到他們之間的關(guān)系如下:

他們之間存在循環(huán)依賴(lài)。

根據(jù)這個(gè)依賴(lài)圖可以梳理出幾條依賴(lài)路線(xiàn):

  • A -> B -> D -> C -> F -> 循環(huán)依賴(lài)B
  • A -> B -> E -> F -> 循環(huán)依賴(lài) B
  • A -> C -> F -> B -> E -> 循環(huán)依賴(lài) F
  • A -> C -> G

從開(kāi)始出現(xiàn)的第一個(gè)循環(huán)依賴(lài)截?cái)嘁蕾?lài)路線(xiàn),分別統(tǒng)計(jì)統(tǒng)計(jì)每個(gè)節(jié)點(diǎn)的深度,按深度依次放入隊(duì)列中。

如果兩個(gè)節(jié)點(diǎn)深度相同,則分析兩個(gè)節(jié)點(diǎn)的依賴(lài)關(guān)系,被依賴(lài)的先進(jìn)隊(duì)列,故最終形成的隊(duì)列如下:

  • F E B C D G A

為什么要得到一個(gè)編譯順序呢?

以上得出的編譯順序是為了盡可能解決如下的引用情況,但也不能解決所有:

// a.js
export const a = 2

// b.js
import { a } from 'a.js';
console.log(a + 2);

這時(shí)候,假設(shè)執(zhí)行 b 的時(shí)候,a 還沒(méi)被執(zhí)行,那么 b 內(nèi)部拿到的 a 實(shí)際上是 undefined,顯然不是我們所希望的。所以此時(shí)必須保證 a 先于 b 執(zhí)行。

但這種使用方式在存在循環(huán)引用時(shí)無(wú)法解決,只能調(diào)整文件組織形式。

事實(shí)上,假設(shè)存在循環(huán)依賴(lài)時(shí),下面的在函數(shù)內(nèi)或在類(lèi)內(nèi)引用方式是沒(méi)有問(wèn)題的,有問(wèn)題的只是直接使用:

// a.js
export const a = 2

// b.js
import { a } from 'a.js';
export function test () {
return a + 1;
}

這樣,即使 b 有依賴(lài) a,test 只要不是立即執(zhí)行函數(shù)也不會(huì)產(chǎn)生影響。

七、編譯

1.ESModule 轉(zhuǎn)換

此過(guò)程可以通過(guò)自定義一個(gè) Babel 插件完成,在語(yǔ)法編譯時(shí)將文件編譯成一個(gè)閉包,同時(shí)處理好 ESModule 語(yǔ)法。

該 Babel 插件很簡(jiǎn)單,在此就不展開(kāi)去寫(xiě)了。

2.文件隊(duì)列編譯

對(duì)單個(gè)文件的編譯可封裝成一個(gè)方法,假設(shè)函數(shù)名為:compileFile。

按照上面解析到的文件隊(duì)列按照順序逐個(gè)調(diào)用 compileFile 進(jìn)行編譯,并將結(jié)果直接拼接起來(lái),形成一個(gè)巨大的字符串,該字符串的樣子應(yīng)該是如下的格式:

(function() {
__filename = 'b.js';
var $$a = module['a.js'];
// ...
var mod = {};
module[__filename] = mod;
})();

(function() {
__filename = 'a.js';
var $$b = module['b.js'];
// ...
var mod = {};
module[__filename] = mod;
})();

// ...

3.JS 執(zhí)行

最后一步,執(zhí)行上面得到的編譯結(jié)果即可,此步驟可直接使用 new Function 的方式完成,例如:

(假設(shè)以上的字符串內(nèi)容保存在 compiledScript 中)。

const exec = new Functioon(`
var module = {};
${compiledScript};
return module;
`);

const module = exec();

module['a.js'] // a.js 的導(dǎo)出內(nèi)容
module['b.js'] // b.js 的導(dǎo)出內(nèi)容

八、總結(jié)

至此,一個(gè)前端可執(zhí)行的小型打包工具就已實(shí)現(xiàn),可以直接在前端進(jìn)行多文件的編輯和執(zhí)行。

實(shí)時(shí)上,此過(guò)程僅適用于不方便借助服務(wù)器的場(chǎng)景,如果有條件允許可以借助服務(wù)器,那么編譯過(guò)程最好在服務(wù)端完成,甚至還可以借助 webpack 或 rollup 等打包工具實(shí)現(xiàn)更好的編譯效果。

參考

目前我們?cè)?ali-lowcode-engine 之上的源碼插件(@ali/lowcode-plugin-code-editor)內(nèi)部實(shí)現(xiàn)了多文件的支持,目前僅做了最簡(jiǎn)單的實(shí)現(xiàn):模塊引用直接采用了 UMD 規(guī)范,暫時(shí)也沒(méi)有考慮循環(huán)依賴(lài)和執(zhí)行順序。

后續(xù)會(huì)嚴(yán)格按照以上步驟進(jìn)行優(yōu)化。

責(zé)任編輯:武曉燕 來(lái)源: 阿里開(kāi)發(fā)者
相關(guān)推薦

2022-11-24 13:05:27

ClangiOS

2010-01-27 16:39:48

C++編譯器

2016-11-08 18:53:08

編譯器

2021-06-25 10:38:05

JavaScript編譯器前端開(kāi)發(fā)

2021-06-08 07:48:26

lambda表達(dá)式編譯器

2025-01-03 11:43:53

2010-01-18 10:34:21

C++編譯器

2010-01-21 09:11:38

C++編譯器

2010-01-22 18:33:17

C++編譯器

2017-03-20 18:01:55

編譯器匯編

2009-08-10 17:12:54

C#編譯器

2013-03-29 10:02:37

編譯器語(yǔ)言編譯開(kāi)發(fā)

2010-03-23 11:17:16

Python 動(dòng)態(tài)編譯

2010-10-20 13:43:37

C++編譯器

2019-08-06 08:20:07

編譯器工具開(kāi)發(fā)者

2010-01-13 13:42:55

C++編譯器

2015-03-23 10:04:43

c++編譯器c++實(shí)現(xiàn)原理總結(jié)

2020-04-02 15:39:51

代碼編譯器前端

2009-08-06 14:59:36

C#編譯器

2011-05-18 11:06:25

java編譯器
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

heyzo中文字幕在线| 精品国产乱码久久久久久图片 | 在线中文字幕-区二区三区四区| 麻豆国产一区| 国产一区二区三区四区五区美女 | 黄色动漫在线| 在线国产日韩| 精品视频一区二区不卡| 国产精品高潮在线| the porn av| 国产激情一区| 91亚洲精品久久久蜜桃| 国产亚洲精品久久久优势| 一级黄色录像免费看| 交100部在线观看| 国产精品18久久久久| 亚洲另类图片色| 亚洲午夜精品国产| 国模精品视频| 无码av中文一区二区三区桃花岛| 国产欧美日韩免费看aⅴ视频| 濑亚美莉一二区在线视频| 伊人久久大香线蕉无限次| 中文字幕一区二区在线观看| 69av在线视频| 又黄又www的网站| 91精品秘密在线观看| 午夜久久福利影院| 97人人澡人人爽| 美女国产在线| 国产成人亚洲综合a∨猫咪| 国产伦一区二区三区色一情| 成品人视频ww入口| 玖玖玖电影综合影院| 亚洲欧美国产精品专区久久 | 蜜桃视频网站在线观看| 亚洲成国产人片在线观看| 久久黄色免费看| 日韩不卡一区| 在线不卡中文字幕| 鬼打鬼之黄金道士1992林正英| huan性巨大欧美| va亚洲va日韩不卡在线观看| 日本三级久久久| 免费黄色在线网站| 欧美性猛交xxxxxxxx| 亚洲第一精品区| 免播放器亚洲一区| 欧美精品激情在线观看| 色佬视频在线观看| 亚洲一区二区三区免费视频| 国产无套精品一区二区| 欧美日韩1区| 在线观看日韩av| 日本激情免费| 日韩国产高清在线| 欧美区在线播放| 亚洲成人男人天堂| 国产综合久久久久久久久久久久| 天天综合色天天综合色hd| 久久久加勒比| 欧美午夜美女看片| 国产对白在线播放| 高清不卡在线观看av| 国产精品丝袜一区二区三区| 青草青在线视频| 久久综合色综合88| 91久久久一线二线三线品牌| 很黄很黄激情成人| 伦理中文字幕亚洲| 日韩在线免费播放| av不卡免费电影| www.99av| 老司机午夜精品| 日韩美女视频中文字幕| 欧美先锋资源| 精品国产欧美成人夜夜嗨| 夜色资源站国产www在线视频| 丁香网亚洲国际| 亚洲一区二区免费| 3d动漫一区二区三区在线观看| 丁香五六月婷婷久久激情| 亚洲精品蜜桃久久久久久| 99热国内精品| 久久精品成人欧美大片| 日本韩国在线视频爽| 亚洲国产精品激情在线观看| 精品一区国产| 精品日韩欧美一区| 色阁综合伊人av| bt在线麻豆视频| 最新91在线视频| 国产一区二区三区四区| 色老头一区二区三区在线观看| 国产精品传媒| 最新中文字幕亚洲| 国产影视精品一区二区三区| 美女被啪啪一区二区| 99久久.com| 国产91av视频在线观看| 国产精品二区一区二区aⅴ污介绍| 成人资源www网在线最新版| 一区二区成人在线观看| 你懂的av在线| 精品一区二区成人精品| 快播亚洲色图| 久久综合久久99| 韩国福利在线| 欧美日韩视频在线| 日韩精品99| 亚洲国产精品推荐| 久久国产精品高清一区二区三区| 亚洲精品美女久久| av有码在线观看| 欧美专区第一页| 人体久久天天| 久久国产精品偷| 日韩综合久久| 色99之美女主播在线视频| 你懂的视频一区二区| 日本国产一区二区三区| 精品写真视频在线观看 | 日韩精品视频网| 日日噜噜噜夜夜爽爽狠狠| 亚洲人成电影网站色xx| 日韩脚交footjobhdboots| 欧美mv日韩mv亚洲| 超碰97免费在线| 亚洲国产精品久久久久久| 日韩系列欧美系列| www.亚洲天堂网| 2020国产精品久久精品美国| 日本在线看片免费人成视1000| 秋霞成人午夜鲁丝一区二区三区| 国产伦精品一区二区三区视频青涩| 亚洲欧美国产不卡| 麻豆国产精品视频| 九色蝌蚪在线| 国产精品va在线播放| 久久天堂av综合合色蜜桃网| 成年人国产在线观看| 国产精品v欧美精品∨日韩| 亚洲人成网站精品片在线观看| 天堂影视av| 91精品国产91久久| 久久久久亚洲综合| а√最新版在线天堂| 黄色成人av网| 九九热播视频在线精品6| 国产成人精品一区二区三区| 成人羞羞动漫| 天天爱天天操天天干| 亚洲中国最大av网站| 日本国产亚洲| 97av中文字幕| 国产精品伦理在线| 香蕉影院在线| 日韩av成人在线| 国产精品污污网站在线观看| 97精品资源在线观看| 色欲色香天天天综合网www| 尤物九九久久国产精品的特点| 韩国成人在线视频| 色偷偷偷在线视频播放| 亚洲欧洲久久| 亚洲欧洲一区二区三区在线观看 | 一区二区不卡在线视频 午夜欧美不卡'| 日本韩国欧美国产| 成人免费观看在线观看| 蜜桃麻豆www久久国产精品| 欧美一级高清大全免费观看| 国产精品videossex撒尿| 97超碰蝌蚪网人人做人人爽| 久久久久国产精品人| 国产精品久久久久av蜜臀| 香蕉521av成人网| 国产精品永久免费视频| 日本道精品一区二区三区 | 最新69国产成人精品视频免费| 成人av在线资源网站| 极品粉嫩饱满一线天在线| 国产精品国产三级国产aⅴ浪潮 | 蜜臀91精品一区二区三区| 在线看女人毛片| 一区二区在线中文字幕电影视频| 亚洲国产电影在线观看| 香蕉国产成人午夜av影院| 亚洲成人精品电影在线观看| 亚洲国产一区自拍| 99re成人精品视频| 欧美另类极品| 在线观看一区二区三区三州| 尤物九九久久国产精品的分类| 久久日韩粉嫩一区二区三区| 丝袜美腿综合| av在线三区| 欧美日韩不卡在线视频| 国产成人一区二区三区| 欧美精品乱码久久久久久| 国内一区二区在线|