由于种种原因, 我们选择了 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 模块了.
来源: https://juejin.im/post/5b88e7606fb9a01a0058c0bf