带有React的CKEditor5:添加自定义插件失败(复制模块)



我正试图在react应用程序中为CKEditor5构建一个自定义插件。我主要遵循了这两个教程:

  • https://ckeditor.com/docs/ckeditor5/latest/installation/getting-started/frameworks/react.html
  • https://ckeditor.com/docs/ckeditor5/latest/framework/guides/plugins/creating-simple-plugin-timestamp.html

以下是我的代码到目前为止的样子:

import React from 'react';
import logo from './logo.svg';
import './App.css';
import { CKEditor } from '@ckeditor/ckeditor5-react';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
class Timestamp extends Plugin {
init() {
console.log( 'Timestamp was initialized.' );
}
}
function App() {
return (
<div className="App">
<h2>Using CKEditor 5 build in React</h2>
<CKEditor
editor={ ClassicEditor }
config={ {
plugins: [ Timestamp ],
toolbar: [ 'bold', 'italic' ]
} }
data="<p>Hello from CKEditor 5!</p>"
onReady={ (editor: any) => {
// You can store the "editor" and use when it is needed.
console.log( 'Editor is ready to use!', editor );
} }
onChange={ ( event: any, editor: { getData: () => any; } ) => {
const data = editor.getData();
console.log( { event, editor, data } );
} }
onBlur={ ( event: any, editor: any ) => {
console.log( 'Blur.', editor );
} }
onFocus={ ( event: any, editor: any ) => {
console.log( 'Focus.', editor );
} }
/>
</div>
);
}
export default App;

我一直得到一个白色的屏幕和控制台中的这个错误,尽管:

Uncaught CKEditorError: ckeditor-duplicated-modules
Read more: https://ckeditor.com/docs/ckeditor5/latest/support/error-codes.html#error-ckeditor-duplicated-modules
at ./node_modules/@ckeditor/ckeditor5-utils/src/version.js (version.js:144:1)
at options.factory (react refresh:6:1)
at __webpack_require__ (bootstrap:24:1)
at fn (hot module replacement:62:1)
at ./node_modules/@ckeditor/ckeditor5-utils/src/emittermixin.js (ckeditorerror.js:195:1)
at options.factory (react refresh:6:1)
at __webpack_require__ (bootstrap:24:1)
at fn (hot module replacement:62:1)
at ./node_modules/@ckeditor/ckeditor5-utils/src/observablemixin.js (mix.js:48:1)
at options.factory (react refresh:6:1)

关于错误代码(重复的模块(的文档没有告诉任何关于自定义插件的信息(只有导入的插件(。据我所见(https://ckeditor.com/docs/ckeditor5/latest/framework/guides/tutorials/using-react-in-a-widget.html)这应该是可行的。

有人知道我做错了什么吗?

好的,我应该更仔细地阅读文档。。本质上,如果你在create-react应用程序生成的repo中工作,你必须更新你的webpack配置。这里有一个全面的指南:https://ckeditor.com/docs/ckeditor5/latest/installation/getting-started/frameworks/react.html#using-创建-实际-app3

以下是我的rules块在./config/webpack.config.js文件中的样子:

rules: [
// Handle node_modules packages that contain sourcemaps
shouldUseSourceMap && {
enforce: 'pre',
exclude: /@babel(?:/|\{1,2})runtime/,
test: /.(js|mjs|jsx|ts|tsx|css)$/,
loader: require.resolve('source-map-loader'),
},
{
// "oneOf" will traverse all following loaders until one will
// match the requirements. When no loader matches it will fall
// back to the "file" loader at the end of the loader list.
oneOf: [
// TODO: Merge this config once `image/avif` is in the mime-db
// https://github.com/jshttp/mime-db
{
test: [/.avif$/],
type: 'asset',
mimetype: 'image/avif',
parser: {
dataUrlCondition: {
maxSize: imageInlineSizeLimit,
},
},
},
// "url" loader works like "file" loader except that it embeds assets
// smaller than specified limit in bytes as data URLs to avoid requests.
// A missing `test` is equivalent to a match.
{
test: [/.bmp$/, /.gif$/, /.jpe?g$/, /.png$/],
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: imageInlineSizeLimit,
},
},
},
{
test: /.svg$/,
// Exclude `js` files to keep the "css" loader working as it injects
// its runtime that would otherwise be processed through the "file" loader.
// Also exclude `html` and `json` extensions so they get processed
// by webpack's internal loaders.
exclude: [
/.(js|mjs|jsx|ts|tsx)$/,
/.html$/,
/.json$/,
/ckeditor5-[^/\]+[/\]theme[/\]icons[/\][^/\]+.svg$/,
/ckeditor5-[^/\]+[/\]theme[/\].+.css$/
],
use: [
{
loader: require.resolve('@svgr/webpack'),
options: {
prettier: false,
svgo: false,
svgoConfig: {
plugins: [{ removeViewBox: false }],
},
titleProp: true,
ref: true,
},
},
{
loader: require.resolve('file-loader'),
options: {
name: 'static/media/[name].[hash].[ext]',
},
},
],
issuer: {
and: [/.(ts|tsx|js|jsx|md|mdx)$/],
},
},
// Process application JS with Babel.
// The preset includes JSX, Flow, TypeScript, and some ESnext features.
{
test: /.(js|mjs|jsx|ts|tsx)$/,
include: paths.appSrc,
loader: require.resolve('babel-loader'),
options: {
customize: require.resolve(
'babel-preset-react-app/webpack-overrides'
),
presets: [
[
require.resolve('babel-preset-react-app'),
{
runtime: hasJsxRuntime ? 'automatic' : 'classic',
},
],
],

plugins: [
isEnvDevelopment &&
shouldUseReactRefresh &&
require.resolve('react-refresh/babel'),
].filter(Boolean),
// This is a feature of `babel-loader` for webpack (not Babel itself).
// It enables caching results in ./node_modules/.cache/babel-loader/
// directory for faster rebuilds.
cacheDirectory: true,
// See #6846 for context on why cacheCompression is disabled
cacheCompression: false,
compact: isEnvProduction,
},
},
// Process any JS outside of the app with Babel.
// Unlike the application JS, we only compile the standard ES features.
{
test: /.(js|mjs)$/,
exclude: /@babel(?:/|\{1,2})runtime/,
loader: require.resolve('babel-loader'),
options: {
babelrc: false,
configFile: false,
compact: false,
presets: [
[
require.resolve('babel-preset-react-app/dependencies'),
{ helpers: true },
],
],
cacheDirectory: true,
// See #6846 for context on why cacheCompression is disabled
cacheCompression: false,

// Babel sourcemaps are needed for debugging into node_modules
// code.  Without the options below, debuggers like VSCode
// show incorrect code and set breakpoints on the wrong lines.
sourceMaps: shouldUseSourceMap,
inputSourceMap: shouldUseSourceMap,
},
},
// "postcss" loader applies autoprefixer to our CSS.
// "css" loader resolves paths in CSS and adds assets as dependencies.
// "style" loader turns CSS into JS modules that inject <style> tags.
// In production, we use MiniCSSExtractPlugin to extract that CSS
// to a file, but in development "style" loader enables hot editing
// of CSS.
// By default we support CSS Modules with the extension .module.css
{
test: cssRegex,
exclude: [
cssModuleRegex,
/ckeditor5-[^/\]+[/\]theme[/\].+.css$/,
],
use: getStyleLoaders({
importLoaders: 1,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
modules: {
mode: 'icss',
},
}),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
// using the extension .module.css
{
test: cssModuleRegex,
exclude: [
/ckeditor5-[^/\]+[/\]theme[/\].+.css$/,
],
use: getStyleLoaders({
importLoaders: 1,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
modules: {
mode: 'local',
getLocalIdent: getCSSModuleLocalIdent,
},
}),
},
// Opt-in support for SASS (using .scss or .sass extensions).
// By default we support SASS Modules with the
// extensions .module.scss or .module.sass
{
test: sassRegex,
exclude: sassModuleRegex,
use: getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
modules: {
mode: 'icss',
},
},
'sass-loader'
),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
// Adds support for CSS Modules, but using SASS
// using the extension .module.scss or .module.sass
{
test: sassModuleRegex,
use: getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
modules: {
mode: 'local',
getLocalIdent: getCSSModuleLocalIdent,
},
},
'sass-loader'
),
},
// Custom loaders for CKEditor5
{
test: /ckeditor5-[^/\]+[/\]theme[/\]icons[/\][^/\]+.svg$/,
use: [ 'raw-loader' ]
},
{
test: /ckeditor5-[^/\]+[/\]theme[/\].+.css$/,
use: [
{
loader: 'style-loader',
options: {
injectType: 'singletonStyleTag',
attributes: {
'data-cke': true
}
}
},
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: styles.getPostCssConfig( {
themeImporter: {
themePath: require.resolve( '@ckeditor/ckeditor5-theme-lark' )
},
minify: true
} )
}
}
]
},
// "file" loader makes sure those assets get served by WebpackDevServer.
// When you `import` an asset, you get its (virtual) filename.
// In production, they would get copied to the `build` folder.
// This loader doesn't use a "test" so it will catch all modules
// that fall through the other loaders.
{
// Exclude `js` files to keep "css" loader working as it injects
// its runtime that would otherwise be processed through "file" loader.
// Also exclude `html` and `json` extensions so they get processed
// by webpacks internal loaders.
exclude: [/^$/, /.(js|mjs|jsx|ts|tsx)$/, /.html$/, /.json$/],
type: 'asset/resource',
},
// ** STOP ** Are you adding a new loader?
// Make sure to add the new loader(s) before the "file" loader.
],
}
].filter(Boolean),

最新更新