由於種種原因,我們選擇了Ueditor作為我們的富文字編輯器選型。
Ueditor不支援模組化,所以無法在程式碼中使用import去引入。一開始我們在專案中是將Ueditor的js檔案直接通過script標籤引入,在React的程式碼裡直接使用window.UE去使用編輯器。但是這就有一個問題,我們對UE的原始碼進行了改動,加入了定製化的功能。而直接引入的UE檔案在瀏覽器是有快取的,我們每次改動都要清除快取才能生效。
我們要解決快取這個問題,webpack配置就必須滿足以下條件:
- 每次改動程式碼後,能自動給UE的檔名加hash
- 能自動插入html模板檔案並在主入口檔案載入之前載入完成
第一步
為了能讓UE的檔案進入打包流程,我們將它作為一個新的入口檔案
const entry = {
main: [`babel-polyfill`, `./src/main.js`],
ueditor_config: [`./src/common/UEditor/ueditor.config.js`],
ueditor_all: [`./src/common/UEditor/ueditor.all.js`]
};
new HtmlWebpackPlugin({
template: `./src/app/${key}/templates/${filename}`,
filename: `../view/${targetHtml}`,
hash: true,
chunks: [ueditor_all, ueditor_config, main]
})
複製程式碼
按上面的配置構建完成之後,會發現效果並不是我們想要的
<script type="text/javascript" src="/public/main.xxxx.js"></script>
<script type="text/javascript" src="/public/ueditor.config.xxxx.js"></script>
<script type="text/javascript" src="/public/ueditor.all.xxxx.js"></script>
複製程式碼
main.js在UE的前面,這樣main中使用window.UE就會報錯。顯然,我們需要一種方式來讓這個順序符合我們的預期。
第二步
HtmlWebpackPlugin的chunksSortMode屬性是用來控制插入模板html的script標籤的順序的,預設是auto,會根據webpack給每個chunk生成的id去排序,在entry中排的越前的,id就越小,那在html中就排在前面。所以這裡我們第一種解決方案是,調換一下entry順序
const entry = {
ueditor_config: [`./src/common/UEditor/ueditor.config.js`],
ueditor_all: [`./src/common/UEditor/ueditor.all.js`]
main: [`babel-polyfill`, `./src/main.js`]
};
複製程式碼
但是這個方法有缺陷,當專案中有多個模板html需要引用入口的時候,在entry裡面去控制這個排序就會遇到衝突的情況,不夠靈活。
所以我們把順序的控制權下方到每個HtmlWebpackPlugin中,通過把chunksSortMode設定為manual,按chunks的順序去排序,例如
new HtmlWebpackPlugin({
...
chunks: [ueditor_config, ueditor_all, main]
})
複製程式碼
這樣,生成的html中srcipt就會是下面的順序
<script type="text/javascript" src="/public/ueditor.config.xxxx.js"></script>
<script type="text/javascript" src="/public/ueditor.all.xxxx.js"></script>
<script type="text/javascript" src="/public/main.xxxx.js"></script>
複製程式碼
現在看上去順序是ok了,但是執行的時候,我們發現控制檯報錯
regeneratorRuntime is not defined
第三步
第二步最後出現的錯誤,是我們使用的ES6新API沒有被轉換導致的。由於之前我們只是在main的入口加了babel-polyfill,而main又是在UE的後面載入的,所以導致了報錯。所以需要將babel-polyfill放到入口第一個檔案
const entry = {
ueditor_config: [`babel-polyfill`, `./src/common/UEditor/ueditor.config.js`],
ueditor_all: [`./src/common/UEditor/ueditor.all.js`]
main: [`./src/main.js`]
};
複製程式碼
繼續執行後,第二步的錯誤已經解決了。不過,新的錯誤又出現了
TypeError: `caller`, `callee`, and `arguments`
properties may not be accessed on strict mode functions or the arguments objects for calls to them
複製程式碼
第四步
bable會預設給編譯的js加上use strict;
嚴格模式下caller、callee 和arguments 是不能使用的,追溯到UE的原始碼中,我們發現裡面大量使用了arguments.callee這種寫法。
直接把原始碼都改了不現實,所以只能通過配置讓bable忽略這個檔案。在.babel中我們加入如下配置,
"presets": [
"react"
],
"ignore": [
"./src/common/UEditor/ueditor.all.js"
],
複製程式碼
到此webpack就能按照我們的預期構建UE模組了。