由于種種原因,我們選擇了Ueditor作為我們的富文本編輯器選型。
Ueditor不支持模塊化,所以無法在代碼中使用import去引入。一開始我們在項目中是將Ueditor的js文件直接通過script標(biāo)簽引入,在React的代碼里直接使用window.UE去使用編輯器。但是這就有一個問題,我們對UE的源碼進(jìn)行了改動,加入了定制化的功能。而直接引入的UE文件在瀏覽器是有緩存的,我們每次改動都要清除緩存才能生效。
我們要解決緩存這個問題,webpack配置就必須滿足以下條件:
- 每次改動代碼后,能自動給UE的文件名加hash
- 能自動插入html模板文件并在主入口文件加載之前加載完成
第一步
為了能讓UE的文件進(jìn)入打包流程,我們將它作為一個新的入口文件
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]
})
按上面的配置構(gòu)建完成之后,會發(fā)現(xiàn)效果并不是我們想要的
<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就會報錯。顯然,我們需要一種方式來讓這個順序符合我們的預(yù)期。
第二步
HtmlWebpackPlugin的chunksSortMode屬性是用來控制插入模板html的script標(biāo)簽的順序的,默認(rèn)是auto,會根據(jù)webpack給每個chunk生成的id去排序,在entry中排的越前的,id就越小,那在html中就排在前面。所以這里我們第一種解決方案是,調(diào)換一下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']
};
但是這個方法有缺陷,當(dāng)項目中有多個模板html需要引用入口的時候,在entry里面去控制這個排序就會遇到?jīng)_突的情況,不夠靈活。
所以我們把順序的控制權(quán)下方到每個HtmlWebpackPlugin中,通過把chunksSortMode設(shè)置為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>
現(xiàn)在看上去順序是ok了,但是運行的時候,我們發(fā)現(xiàn)控制臺報錯
regeneratorRuntime is not defined
第三步
第二步最后出現(xiàn)的錯誤,是我們使用的ES6新API沒有被轉(zhuǎn)換導(dǎo)致的。由于之前我們只是在main的入口加了babel-polyfill,而main又是在UE的后面加載的,所以導(dǎo)致了報錯。所以需要將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']
};
繼續(xù)運行后,第二步的錯誤已經(jīng)解決了。不過,新的錯誤又出現(xiàn)了
TypeError: 'caller', 'callee', and 'arguments'
properties may not be accessed on strict mode functions or the arguments objects for calls to them
第四步
bable會默認(rèn)給編譯的js加上use strict;
嚴(yán)格模式下caller、callee 和arguments 是不能使用的,追溯到UE的源碼中,我們發(fā)現(xiàn)里面大量使用了arguments.callee這種寫法。
直接把源碼都改了不現(xiàn)實,所以只能通過配置讓bable忽略這個文件。在.babel中我們加入如下配置,
"presets": [
"react"
],
"ignore": [
"./src/common/UEditor/ueditor.all.js"
],
到此webpack就能按照我們的預(yù)期構(gòu)建UE模塊了。