前言
我查過網上的教程,大部分都是基於vue或者react框架,很少有教程是基於純粹的webpack來的,這篇文章記錄我在webpack上使用monaco-editor的過程,以補充網上在這方面資料的缺失。本文章會根據我的開發隨時進行更新。
使用
monaco的使用介紹,網上有很多,大家可以參考這篇文章進行大概的了解。
自己總結的使用過程
1、安裝。
npm install monaco-editor -save
2、在頁面中使用
在HTML中創建一個容器,然后使用下面的代碼進行初始化就可以得到一個在線編輯器了,但是現在這個編輯器也只是編輯器,什么輔助功能都沒有,比如代碼提示、右鍵菜單等等。
language:"javascript"
})
效果圖:
3、開啟輔助功能
如何開啟輔助功能,一種是我們根據自己的需要把輔助的文件引入到頁面中,方法參考【使用】章節里提供的地址,另外一種就是用webpack來實現。
安裝monaco-editor-webpack-plugin這個模塊。
npm install monaco-editor-webpack-plugin
在webpack.config.js中進行配置,MonacoWebpackPlugin可以接受language和features來配置輔助功能,具體配置參數可以查看npm官網即可。
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
plugins: [
new MonacoWebpackPlugin()
]
}
效果圖如下:
不過這里有幾點注意的,這是博主在使用過程中發現的一些情況:
1)、如果你得webpack項目使用了HtmlWebpackPlugin來實現多頁面配置,那么通過monaco-editor-webpack-plugin生成的一些文件的引用路徑將會受到HtmlWebpackPlugin這個配置的影響。例如我使用如下代碼動態配置HTML模板的信息,其中filename不僅可以從命名文件還可以設置其路徑,假設我將filename改為`pages/${name}.html`,將HTML文件放在pages這個路徑下,那么monaco-editor-webpack-plugin生成的所有文件在引用的時候都會加上pages這個路徑,原因未知,博主排查了好久都不清楚為啥,所以只能放在根目錄下。如果有知道的歡迎指出。
var getHtmlConfig = function(name,chunks){
filename:`${name}.html`,
inject:true, // 將js資源插入到body元素底部
hash:false,
chunks:[name, 'runtime','libs', 'commons']
}
}
2)、monaco-editor-webpack-plugin參數中filename僅更改worker文件的名字,而無法更改其他生成的JS文件名稱。
3)、
MonacoWebpackPlugin的language參數的配置會影響右鍵菜單。經測試:如果language中如果沒有引入typescript,右鍵菜單和控制面板部分功能將消失。
4、如何設置菜單中文顯示效果
這個功能折騰了樓主好久時間。網上也沒有系統的相關資料。不過能在一些文章中零星的看到有人使用下面的代碼進行配置。
'*': 'zh-cn'
}
}
});
可是當你把這段代碼復制到自己的代碼中又發現完全無法執行。那怎么辦?
這里需要涉及到另外兩個模塊。monaco-editor-esm-webpack-plugin和monaco-editor-nls。其中monaco-editor-esm-webpack-plugin和上面的monaco-editor-webpack-plugin這個不一樣,前者需要依賴后者,也就是說你要使用前者,就必須先安裝后者。先安裝兩個模塊。
npm install --save monaco-editor-nls
改寫webpack.config.js,需要注意的是rules里也需要添加MonacoWebpackPlugin.loader
// 去除monaco-editor-webpack-plugin,改為monaco-editor-esm-webpack-plugin
module.exports = {
module: {
rules: [
{
test: /\.js/,
enforce: 'pre',
include: /node_modules[\\\/]monaco-editor[\\\/]esm/,
use: MonacoWebpackPlugin.loader
},
]
}
plugins: [
new MonacoWebpackPlugin()
]
}
然后在頁面的JS中添加如下代碼,這些代碼必須添加在引入'monaco-editor/esm/vs/editor/editor.api.js';之前
import { setLocaleData } from 'monaco-editor-nls';
接着重新編輯文件,你會發現編譯控制台提示報錯,在monaco-editor/esm/vs/editor/contrib下缺少goToDefinition文件夾。其實還缺少了一個referenceSearch。如何解決?首先說明一下,這兩個文件夾其實並沒有缺少,只是在monaco-editor@0.19.0版本以上,微軟把這些文件統一放到了gotoSymbol這個文件夾,你可以把monaco-editor安裝為0.18.1這個版本就可以使用,不過還是得進行一些插件源代碼修改。如果我一定要安裝@0.20.0怎么辦,那只需要修改\node_modules\monaco-editor-esm-webpack-plugin\node_modules\monaco-editor-webpack-plugin\features.js這個文件即可。
// 刪除一下代碼
worker: undefined,
},
goToDefinitionMouse: {
entry: 'vs/editor/contrib/goToDefinition/goToDefinitionMouse',
worker: undefined,
},
referenceSearch: {
entry: [
'vs/editor/contrib/referenceSearch/referenceSearch',
'vs/editor/standalone/browser/referenceSearch/standaloneReferenceSearch',
],
worker: undefined,
}
// 新增以下代碼
gotoSymbol:{
entry: 'vs/editor/contrib/gotoSymbol/goToCommands',
worker: undefined
}
按照上述操作修改后就可以正常編譯了。可是編譯后,你打開項目你會發現菜單什么還是英文的。這又是啥子情況,明明都按照要求更改了。這個問題我也不清楚是為啥,不過按照下面的改法就行。在一開始我們引入editor.api.js的時候是使用import進行引入的,只要把它改為require引入就行。
const monaco = require('monaco-editor/esm/vs/editor/editor.api');
value: `console.log(123)`,
contextmenu: true,
language: 'javascript',
theme: 'vs-dark'
})
到此菜單漢化就完成了,重新打包運行后效果如下:
5、編輯器功能(更新:2020年8月24日)
1)、動態賦值
language: 'javascript',
theme: 'vs-dark'
})
monacoInstance.setValue(res);
2)、動態修改語言
monaco.editor.setModelLanguage(monacoInstance.getModel(), 'html');
3)、獲取光標位置
monacoInstance.getPosition();
// column 列數
4)、設置光標位置。
// 兩個參數最好都寫,不然控制台會報錯
column: 1
})
5)、聚焦編輯器
monacoInstance.focus();
6)、編輯器滾動到頂部
monacoInstance.setScrollPosition({
});
7)、獲取當前編輯器內容行數
monacoInstance.getModel().getLineCount()
8)、獲取某一行的列數
monacoInstance.getModel().getLineLength(2)
9)、在特定行插入數據
function insertValueByCurrentPosition(value) {
[
{
range: new monaco.Range(p.lineNumber,
p.column,
p.lineNumber,
p.column),
text: value
}
]
);
}
6、monaco-editor使用到的JS文件如何壓縮(2020年4月28日11:49:58)
我們在webpack中使用到壓縮JS模塊一般都是使用uglifyjs-webpack-plugin。如果我們在項目中使用了monaco-editor的話,在使用uglifyjs-webpack-plugin壓縮editor需要的JS的時候,你會發現控制台輸出錯誤信息,會出現兩種錯誤提示,一種是關於worker.js相關的錯誤,一個是Unexpected token: name «__insane_func», expected: punc «;»。上面兩個錯誤本質上都是因為monaco-editor中使用了最新的ESM語法,uglifyjs-webpack-plugin無法正常解析導致的。處理辦法有兩種:
1)、繼續使用uglifyjs-webpack-plugin。在exclude參數中添加worker.js,然后在chunkFilter中去除提示Unexpected token: name «__insane_func», expected: punc «;»錯誤的文件。不對這些文件進行壓縮就可以正常編譯。
module.exports = {
new UglifyJSPlugin({ //目的是為了編譯環境清除控制台以及關閉注釋
exclude: /\.min\.js|\.worker\.js|\/libs-bundle$/,
cache: true,
parallel: true, // 開啟並行壓縮,充分利用cpu
extractComments: false, // 移除注釋
chunkFilter: (chunk) => { // 需要加上這個,不然monaco-editor采用新的es語法,uglify無法解析
if (chunk.name == 'libs') {
return false;
}
return true
},
uglifyOptions: {
output: {
comments: false // 保留所有的注釋
},
compress: {
drop_debugger: true,
drop_console: true // 刪除所有的 `console` 語句,可以兼容ie瀏覽器
}
}
}),
]
}
}
2)、不是用uglifyjs-webpack-plugin,將該模塊替換為terser-webpack-plugin。這兩個插件參數和使用方法基本是一致,可以理解為后者是前者的升級版。參考資料:【傳送門1、傳送門2、傳送門3】。下面給出我的配置代碼。
module.exports = {
minimizer: [
new TerserPlugin({ //目的是為了編譯環境清除控制台以及關閉注釋
exclude: /\.min\.js$/,
cache: true,
parallel: true, // 開啟並行壓縮,充分利用cpu
extractComments: false, // 移除注釋
terserOptions: {
output: {
comments: false // 保留所有的注釋
},
compress: {
drop_debugger: true,
drop_console: true // 刪除所有的 `console` 語句,可以兼容ie瀏覽器
}
}
}),
]
}
}
后記:2020年4月23日15:22:48 在使用這個編輯器過程中,博主前前后后折騰了好久,特別是那個莫名添加路徑和漢化這兩點上,花費了很多的時間。百度過谷歌過都沒有找到解決方案。不過幸好,最終還是做到自己想要的效果了。在此感謝上述涉及的插件模塊的開發者。