Node.js 中的进阶编辑器捆绑
本文介绍了如何在 Node.js 中创建 CKEditor 5 编辑器捆绑包。它是从 CKEditor 5 包(从 CKEditor 5 Builder 下载)创建编辑器捆绑包的分步指南,但可以轻松地适应各种设置。CKEditor 云服务需要编辑器捆绑包来启用 文档存储、导入和导出 以及 连接优化 功能。
# 捆绑包要求
CKEditor 云服务可以使用的那一款编辑器捆绑包必须满足某些要求
- 它需要被构建成单个
.js
文件。 - 插件应添加到
builtinPlugins
属性中,以包含在编辑器捆绑包中。您不能使用config.plugins
选项将插件添加到编辑器。 - webpack 配置中的
output.library
属性应设置为CKEditorCS
值。 - 编辑器捆绑包中使用的插件不能执行外部 HTTP 请求。
- 编辑器实例需要是编辑器捆绑包中的默认导出。
官方支持的 CKEditor 5 插件在 CKEditor 云服务将它们用于编辑器捆绑包时,已经满足了不执行外部请求的要求。如果您的自定义插件发送任何外部请求,那么您有两个选择
- 如果此插件不修改编辑器的模型或编辑器的输出,则您可以在编辑器捆绑包上传期间从编辑器配置中将其删除。
- 如果此插件修改了编辑器的模型,则可以将其重构为 2 个插件。其中一个将负责编辑部分,而另一个将发出 HTTP 请求。这样,您就可以在不影响输出数据的情况下,在编辑器捆绑包上传期间删除其中一个插件。
有关从编辑器配置中删除插件的更多信息,请参阅 上传编辑器捆绑包 部分。
# 创建捆绑包
以下示例作为如何准备编辑器捆绑包配置的模板。假设您拥有基本的 CKEditor 5 文件 - package.json
、main.js
、index.html
和 style.css
文件,这些文件是使用 CKEditor 5 Builder 和“自托管(npm)”集成方法的结果。
# 依赖项
此示例使用以下依赖项
ckeditor5
ckeditor5-premium-features
webpack
webpack-cli
mini-css-extract-plugin
如果您按照 Builder 设置进行操作,则 ckeditor5*
包应该已经存在。对于其余的运行
npm install -D webpack webpack-cli mini-css-extract-plugin
之后,您的 package.json
依赖项部分应该如下所示
{
"dependencies": {
"ckeditor5": "^42.0.0",
"ckeditor5-premium-features": "^42.0.0"
},
"devDependencies": {
"mini-css-extract-plugin": "^2.9.0",
"webpack": "^5.92.1",
"webpack-cli": "^5.1.4"
}
}
# 编辑器设置
强烈建议在创建捆绑包和将 CKEditor 5 与前端层集成时使用相同的编辑器设置。这样,更容易将前端和后端之间的所有内容保持同步和一致。这需要对上述设置进行一些调整,方法是更改编辑器各个部分的定义和使用方式。
两种设置的共同部分是编辑器类、插件列表和编辑器配置。我们将 main.js
文件拆分为 3 个文件
- 将定义共享部分的
main.js
文件。 main-fe.js
文件,它将负责前端应用程序中的编辑器设置。main-be.js
文件,将从中生成编辑器捆绑包。它将是捆绑器入口文件。
第一步是调整 main.js
文件。
// main.js
import {
ClassicEditor,
Essentials,
Paragraph,
Bold,
Italic
} from 'ckeditor5';
import {
RealTimeCollaborativeEditing
} from 'ckeditor5-premium-features';
// 1. Remove style imports. Those will be used in main-fe.js.
// import 'ckeditor5/ckeditor5.css';
// import 'ckeditor5-premium-features/ckeditor5-premium-features.css';
// import './style.css';
// 2. Create a list of plugins which will be exported.
const pluginList = [
Essentials,
Paragraph,
Bold,
Italic,
RealTimeCollaborativeEditing
];
// 3. Adjust 'editorConfig' to utilize 'pluginList'.
const editorConfig = {
plugins: pluginList,
...
}
// 4. Export shared parts, instead of initializing editor.
// ClassicEditor.create(document.querySelector('#editor'), editorConfig);
export {
ClassicEditor,
pluginList,
editorConfig
}
接下来,我们将创建将在前端使用的 main-fe.js
。
// main-fe.js
import { ClassicEditor, editorConfig } from './main.js';
// 1. Move style imports from main.js here.
import 'ckeditor5/ckeditor5.css';
import 'ckeditor5-premium-features/ckeditor5-premium-features.css';
import './style.css';
// 2. Initialize editor.
ClassicEditor.create(document.querySelector('#editor'), editorConfig);
之后,应该创建用于捆绑的 main-be.js
文件。
// main-be.js
import { ClassicEditor, pluginList } from './main.js';
class CKEditorCS extends ClassicEditor {}
// 1. Assign plugins to be used in bundle.
CKEditorCS.builtinPlugins = pluginList;
// 2. Export editor class.
export default CKEditorCS;
# 前端构建
进行上述更改后,您的应用程序可以像以前一样构建和捆绑。唯一需要调整的地方是更改导入的文件。
<!doctype html>
<html lang="en">
<head>...</head>
<body>
...
<!-- <script type="module" src="./main.js"></script> -->
<script type="module" src="./main-fe.js"></script>
</body>
</html>
# 捆绑器配置
接下来,您需要准备 webpack 配置以生成有效的捆绑包。
const MiniCssExtractPlugin = require( 'mini-css-extract-plugin' );
module.exports = {
entry: './main-be.js', // Your editor build configuration.
output: {
filename: 'editor.bundle.js', // Content of this file is required to upload to CKEditor Cloud Services.
library: 'CKEditorCS', // It is required to expose you editor class under the "CKEditorCS" name!
libraryTarget: 'umd',
libraryExport: 'default',
clean: true
},
plugins: [
new MiniCssExtractPlugin()
],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader']
}
]
},
performance: { hints: false }
};
# 生成捆绑包
然后,在 CKEditor 5 包文件夹中运行以下命令
npx webpack --mode production
此命令将生成 ./dist/editor.bundle.js
文件。此捆绑包文件应随后 上传到 CKEditor 云服务服务器。
# 使用 TypeScript 构建编辑器捆绑包
上面介绍的示例在编辑器源文件中使用了 JavaScript。使用 TypeScript 构建编辑器捆绑包也是可能的。要开始使用 TypeScript,请执行以下步骤
- 将 TypeScript 集成到 webpack 中。有关更多详细信息,请参阅 本指南。
- 将编辑器源文件的扩展名更改为
.ts
。调整webpack.config.js
中的入口路径。 - 请参阅 使用 TypeScript 指南,并在需要时调整导入和配置设置。
# 从传统配置创建捆绑包
以下示例作为如何准备编辑器构建和捆绑器配置的模板。假设您拥有一个包含 ckeditor.js
、package.json
和 webpack.config.js
文件的现有 CKEditor 5 包。
# 依赖项
此示例使用以下依赖项
@ckeditor/ckeditor5-editor-classic
@ckeditor/ckeditor5-basic-styles
@ckeditor/ckeditor5-essentials
@ckeditor/ckeditor5-paragraph
@ckeditor/ckeditor5-real-time-collaboration
@ckeditor/ckeditor5-dev-utils
@ckeditor/ckeditor5-theme-lark
webpack
webpack-cli
postcss-loader
raw-loader
style-loader
package.json
文件依赖项部分应该类似于以下部分。
包列表及其版本可能会有所不同,具体取决于编辑器预设/构建以及创建它的时间。
{
"dependencies": {
"@ckeditor/ckeditor5-basic-styles": "41.4.2",
"@ckeditor/ckeditor5-editor-classic": "41.4.2",
"@ckeditor/ckeditor5-essentials": "41.4.2",
"@ckeditor/ckeditor5-paragraph": "41.4.2",
"@ckeditor/ckeditor5-real-time-collaboration": "41.4.2"
},
"devDependencies": {
"@ckeditor/ckeditor5-dev-utils": "^32.1.2",
"@ckeditor/ckeditor5-theme-lark": "41.4.2",
"postcss-loader": "^4.3.0",
"raw-loader": "^4.0.2",
"style-loader": "^2.0.0",
"webpack": "^5.91.0",
"webpack-cli": "^4.10.0"
}
}
# 编辑器构建配置
此文件展示了一个编辑器构建配置示例。捆绑器将其用作入口文件。此 ckeditorcs.js
文件应基于您的 ckeditor.js
文件创建。
请记住将以下配置适应您的需求,因为示例保持在最低限度。请参阅 CKEditor 5 构建的 高级设置 文档,以根据您的要求调整捆绑包创建过程。
// ckeditorcs.js
// The editor base creator to use.
import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';
// All plugins that you would like to use in your editor.
import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials';
import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
import RealTimeCollaborativeEditing from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativeediting';
class CKEditorCS extends ClassicEditor {}
// Load all plugins you would like to use in your editor this way.
// This is the only way to load plugins into the editor which will then be used in CKEditor Cloud Services.
CKEditorCS.builtinPlugins = [
Essentials,
Paragraph,
Bold,
Italic,
RealTimeCollaborativeEditing
];
// Export your editor.
export default CKEditorCS;
# 捆绑器配置
此文件展示了一个捆绑器配置示例。这里使用 webpack 作为捆绑器。
// webpack.config.js
const { styles } = require( '@ckeditor/ckeditor5-dev-utils' );
module.exports = {
entry: './ckeditorcs.js', // Your editor build configuration.
output: {
filename: 'editor.bundle.js', // Content of this file is required to upload to CKEditor Cloud Services.
library: 'CKEditorCS', // It is required to expose you editor class under the "CKEditorCS" name!
libraryTarget: 'umd',
libraryExport: 'default'
},
module: {
rules: [
{
test: /\.svg$/,
use: [ 'raw-loader' ]
},
{
test: /\.css$/,
use: [
{
loader: 'style-loader',
options: {
injectType: 'singletonStyleTag'
}
},
{
loader: 'postcss-loader',
options: styles.getPostCssConfig( {
themeImporter: {
themePath: require.resolve( '@ckeditor/ckeditor5-theme-lark' )
},
minify: true
} )
}
]
}
]
},
performance: { hints: false }
};
这里最重要的部分是 output.library
字段。没有它,捆绑包将无法与 CKEditor 云服务服务器一起使用。
module.exports = {
// ...
output: {
library: 'CKEditorCS', // It is required to expose you editor class under the "CKEditorCS" name!
// ...
},
// ...
};
# 生成捆绑包
在 CKEditor 5 包文件夹中运行以下命令
npm install
npx webpack --mode production
此命令将生成 ./dist/editor.bundle.js
文件。此捆绑包文件应随后 上传到 CKEditor 云服务服务器。
您的 webpack output.*
配置可能略有不同。对于 CKEditor 5,将构建工件存储在 ./build/
文件夹中也很常见。在这种情况下,捆绑包将是 ./build/editor.bundle.js
文件。
# 带有 Watchdog、上下文或“超级构建”的编辑器捆绑包
云服务期望捆绑文件中 Editor
类作为默认导出。如果您使用的是带有 Watchdog 和 上下文 的编辑器捆绑包,或者您将多个编辑器构建为 “超级构建”,则需要采取额外的步骤才能上传这些编辑器。
您可以从多个源文件构建多个编辑器捆绑包,用于不同的目的。然后,可以使用单个 webpack 构建来捆绑所有这些捆绑包。借助这种方法,您将拥有一个与云服务兼容的编辑器捆绑包,并且您仍然可以使用另一个编辑器捆绑包并利用“超级构建”、watchdog 或上下文。
# 使用 Watchdog 创建传统编辑器捆绑包
假设您拥有一个 ckeditor.js
源文件,它导出带有 watchdog 的编辑器
import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor.js';
import EditorWatchdog from '@ckeditor/ckeditor5-watchdog/src/editorwatchdog';
// Other plugins imports.
class Editor extends ClassicEditor {}
Editor.builtinPlugins = [
// Imported plugins.
];
const watchdog = new EditorWatchdog( Editor );
export default watchdog;
您现在可以创建 ckeditorcs.js
源文件,其内容与上面的文件相同。唯一的区别是此文件中的 export
。您应该导出 Editor
实例,而不是导出 watchdog:export default Editor;
。
有了这两个源文件,您可以调整 webpack 配置,以在单个构建步骤中捆绑这两个编辑器
'use strict';
const path = require( 'path' );
const webpack = require( 'webpack' );
const { bundler, styles } = require( '@ckeditor/ckeditor5-dev-utils' );
const { CKEditorTranslationsPlugin } = require( '@ckeditor/ckeditor5-dev-translations' );
const TerserWebpackPlugin = require( 'terser-webpack-plugin' );
const config = {
devtool: 'source-map',
performance: { hints: false },
optimization: {
minimizer: [
new TerserWebpackPlugin( {
sourceMap: true,
terserOptions: {
output: {
comments: /^!/
}
},
extractComments: false
} )
]
},
plugins: [
new CKEditorTranslationsPlugin( {
language: 'en',
additionalLanguages: 'all'
} ),
new webpack.BannerPlugin( {
banner: bundler.getLicenseBanner(),
raw: true
} )
],
module: {
rules: [
{
test: /\.svg$/,
use: [ 'raw-loader' ]
},
{
test: /\.css$/,
use: [
{
loader: 'style-loader',
options: {
injectType: 'singletonStyleTag',
attributes: {
'data-cke': true
}
}
},
{
loader: 'css-loader'
},
{
loader: 'postcss-loader',
options: {
postcssOptions: styles.getPostCssConfig( {
themeImporter: {
themePath: require.resolve( '@ckeditor/ckeditor5-theme-lark' )
},
minify: true
} )
}
}
]
}
]
}
};
module.exports = [
// The first bundle will have the editor with watchdog and can be used in your application.
{
...config,
entry: path.resolve( __dirname, 'src', 'ckeditor.js' ),
output: {
library: 'Watchdog',
path: path.resolve( __dirname, 'build' ),
filename: 'ckeditor.js',
libraryTarget: 'umd',
libraryExport: 'default'
}
},
// The second bundle will be ready to be uploaded to the Cloud Services server.
{
...config,
entry: path.resolve( __dirname, 'src', 'ckeditorcs.js' ),
output: {
library: 'CKEditorCS',
path: path.resolve( __dirname, 'build' ),
filename: 'ckeditorcs.js',
libraryTarget: 'umd',
libraryExport: 'default'
}
}
];
类似地,如果您使用上下文或“超级构建”,您可以构建多个捆绑包。在使用上下文捆绑包的情况下,请确保云服务的捆绑包包含上下文编辑器具有的所有插件。对于超级构建,您可以简单地创建源文件的副本,并导出您要上传到云服务的单个编辑器实例。
# 使用 TypeScript 构建编辑器捆绑包
上面介绍的示例在编辑器源文件中使用了 JavaScript。使用 TypeScript 构建编辑器捆绑包也是可能的。要开始使用 TypeScript,请执行以下步骤
- 将 TypeScript 集成到 webpack 中。有关更多详细信息,请参阅 本指南。
- 将编辑器源文件的扩展名更改为
.ts
。调整webpack.config.js
中的入口路径。 - 请参阅 使用 TypeScript 指南,并在需要时调整导入和配置设置。