前端程序員:如何用javascript開發(fā)一款在線IDE?

2024-04-25    分類: 網(wǎng)站建設(shè)

前言

3年前在AWS re:Invent 大會上AWS宣布推出Cloud9, 用于在云端編寫、運(yùn)行和調(diào)試代碼,它可以直接運(yùn)行在瀏覽器中,也就是傳說中的Web IDE。3年后的今天隨著國內(nèi)云計算的發(fā)展, 各大云計算服務(wù)廠商都在部署自己的WEB IDE, 而且已經(jīng)有非常成熟的落地方案, 對于這一塊的技術(shù)原理和實(shí)現(xiàn), 也非常值得我們?nèi)W(xué)習(xí)和剖析.

目前比較成熟的WEB IDE方案有CodeSandbox,Cloud Studio等, 接下來筆者將實(shí)現(xiàn)一個簡單的WEB IDE, 來帶大家了解其原理和實(shí)現(xiàn)過程.

正文

筆者接下來會介紹WEB IDE的實(shí)現(xiàn)原理和應(yīng)用場景, 并介紹如何在H5-Dooring中使用它.

1. web編輯器實(shí)現(xiàn)原理

我們先來看看一個成熟WEB IDE的結(jié)構(gòu):

抽象出來可以分為3個核心部分:文件導(dǎo)航區(qū)代碼編輯區(qū) * 預(yù)覽容器

如下圖所示:

在把模塊抽象出來之后我們來思考具體的功能實(shí)現(xiàn). 對于文件導(dǎo)航區(qū)我們可以很容易地使用react/vue的ui庫來實(shí)現(xiàn), 對于文件保存, 目錄樹生成等我們可以使用nodejs + DB(如mysql,Redis)來實(shí)現(xiàn). 代碼編輯區(qū)我們可以用第三方成熟的庫比如react-codemirror2或者react-monaco-editor來做. 由于預(yù)覽容器我們不清楚預(yù)覽類型(如小程序,web頁面還是app), 所以這里我們暫時考慮web頁面容器, 也就是我們比較熟悉的iframe. 那么我們可以畫出如下技術(shù)實(shí)現(xiàn)圖:

實(shí)際上WEB IED實(shí)現(xiàn)過程遠(yuǎn)比上面的復(fù)雜, 我們這里只做簡單的抽象. 我們接下來梳理一下在線代碼編輯器的需求:支持在線編寫前端代碼(html,javascript,css)支持實(shí)時預(yù)覽 * 支持代碼在線下載

1.1 技術(shù)選型

在了解了以上實(shí)現(xiàn)方式之后, 我們開始來搭建環(huán)境并進(jìn)行代碼開發(fā). 以下列舉我們的技術(shù)選型:koa基于nodejs的服務(wù)端框架koa-static基于koa的靜態(tài)資源中間件koa-body解析請求體的中間件koa2-cors處理跨域的中間件koa-logger處理請求日志的中間件react前端框架react-codemirror2代碼編輯器antd基于react的前端組件庫

以下是筆者實(shí)現(xiàn)的效果圖:

1.2 實(shí)現(xiàn)細(xì)節(jié)

對于以上筆者列出的koa和react的技術(shù)方案不熟悉的大家可以先了解一下,筆者這里直接實(shí)現(xiàn)具體邏輯。

我們先用umi來創(chuàng)建工程,然后在根目錄新建server.js文件。該文件主要用來處理nodejs相關(guān)邏輯,在稍后我會詳細(xì)介紹。

界面的實(shí)現(xiàn)筆者不一一介紹了,前端模塊筆者來介紹一下如何配置代碼編輯器。react-codemirror2基本使用方式如下:

import{UnControlledasCodeMirror}fromreact-codemirror2;require(codemirror/mode/xml/xml);require(codemirror/mode/javascript/javascript);exportdefaultfunction(){// ...return(<CodeMirrorclassName={styles.codeWrap}value={html}options={{mode:xml,theme:material,lineNumbers:true}}onChange={handleChange}cursor={cursor}onCursor={onCursorChange}/>); }

通過以上方式我們就能生成一個基本的代碼編輯器,需要注意的是我們需要再單獨(dú)引入對應(yīng)的主題樣式文件:

@import~codemirror/lib/codemirror.css;@import~codemirror/theme/material.css;

為了實(shí)現(xiàn)預(yù)覽功能,筆者之前想了兩種方案,一種是直接通過頁面組件的方式來實(shí)現(xiàn)預(yù)覽,但是缺點(diǎn)是只有dom和樣式更新能生效,如果編寫js代碼,由于react的內(nèi)部機(jī)制是無法直接執(zhí)行script的。

另一種方案是iframe,這種方案可以很好地隔離react和預(yù)覽代碼,實(shí)現(xiàn)機(jī)制如下:

也就是說我們在代碼編輯器里編輯完代碼之后統(tǒng)一通過請求的方式保存在node端,然后通過iframe請求nodejs渲染的靜態(tài)頁面來實(shí)現(xiàn)預(yù)覽功能。有點(diǎn)類似服務(wù)端渲染的感覺。

那么如何保證實(shí)時預(yù)覽呢?這塊完全可以設(shè)計成用戶手動點(diǎn)擊預(yù)覽,也是筆者最初的設(shè)想,但是為了增強(qiáng)用戶體驗,筆者決定采用實(shí)時預(yù)覽, 也就是用戶代碼的變化可以實(shí)時反應(yīng)在預(yù)覽窗口。方案就是在onChange中更新state來實(shí)現(xiàn)rerender,這一點(diǎn)用react hooks很好實(shí)現(xiàn)。但是實(shí)時更新對性能很不友好, 所以為了提高預(yù)覽性能和頁面體驗,筆者在這里使用防抖來控制請求頻次和時機(jī)。代碼如下:

consthandleChange =(editor, data, value) =>{ fetchPage(value) }constfetchPage =(v) =>{if(timer) clearTimeout(timer); timer = setTimeout(()=>{ fetch(http://localhost:80/dooring/render, {method:POST,body: v}).then(res=>{ html = v setUpdate(prev=>!prev) }); },1000); }

在開發(fā)中還遇到同一個問題就是iframe每刷新一次,代碼編輯器的光標(biāo)都會被重置,這一點(diǎn)對用戶在線coding的體驗非常不好,所以筆者又看了一遍官方文檔,找到了cursor這個有意思的api,中文的意思就是說可以手動設(shè)置光標(biāo)停止的位置,那么我們在每次光標(biāo)變化的時候都強(qiáng)制設(shè)置為當(dāng)前光標(biāo)所在的位置,那么就不會應(yīng)為iframe刷新的影響而被迫觸發(fā)失焦動作了。 代碼實(shí)現(xiàn)如下:

constonCursorChange = (editor, data) => {const{ line, ch } = datasetCursor({line, ch })}//...

網(wǎng)頁題目:前端程序員:如何用javascript開發(fā)一款在線IDE?
分享鏈接:http://muchs.cn/news7/325157.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站改版、域名注冊、靜態(tài)網(wǎng)站、商城網(wǎng)站、網(wǎng)站內(nèi)鏈、標(biāo)簽優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

綿陽服務(wù)器托管