You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js集成CKEditor自定义图片缩放功能编译失败的解决方案求助

解决Next.js中CKEditor编译失败及图片自定义缩放问题

一、编译失败原因及修复

你当前代码直接将ImageResizeButtons、ImageResizeEditing、ImageResizeHandles等源码级插件添加到extraPlugins中,但@ckeditor/ckeditor5-build-classic是预编译好的编辑器包,不支持直接引入未包含在预构建内的源码插件,这会触发模块解析错误,导致编译失败。

修复步骤:

  1. 移除错误的插件导入
    删除以下导入语句:

    import {Image, ImageResizeButtons, ImageResizeEditing, ImageResizeHandles} from '@ckeditor/ckeditor5-image'
    

    同时从config.extraPlugins数组中移除这些插件。

  2. 改用Next.js动态导入避免SSR问题
    CKEditor依赖浏览器API,Next.js的SSR环境下直接加载会报错,替换原有的动态导入逻辑为Next.js官方的dynamic函数并禁用SSR:

    import dynamic from 'next/dynamic';
    const CKEditor = dynamic(() => import('@ckeditor/ckeditor5-react').then(mod => mod.CKEditor), {
      ssr: false,
      loading: () => <p>加载编辑器中...</p>
    });
    const ClassicEditor = dynamic(() => import('@ckeditor/ckeditor5-build-classic'), {
      ssr: false
    });
    

    同时移除原有的editorRef及相关useEffect代码,直接使用上述导入的组件。

二、实现自定义图片缩放功能

预构建的Classic Editor默认不包含图片缩放插件,有两种可行方案实现需求:

方案1:自定义构建CKEditor(推荐)

按照官方指南构建包含ImageResize插件的自定义编辑器包:

  1. 克隆CKEditor5构建仓库,安装图片缩放相关依赖:
    npm install @ckeditor/ckeditor5-image --save-dev
    
  2. 在构建配置文件src/ckeditor.js中添加:
    import ImageResize from '@ckeditor/ckeditor5-image/src/imageresize';
    
    将ImageResize加入builtinPlugins数组,重新构建编辑器后,替换项目中的@ckeditor/ckeditor5-build-classic依赖。
  3. 组件中配置图片缩放:
    config={{
      removePlugins: ['MediaEmbed'],
      image: {
        resizeOptions: [
          {
            name: 'resizeImage:original',
            value: null,
            label: '原始大小'
          },
          {
            name: 'resizeImage:50',
            value: '50',
            label: '50%'
          },
          {
            name: 'resizeImage:75',
            value: '75',
            label: '75%'
          },
          {
            name: 'resizeImage:custom',
            value: 'custom',
            label: '自定义'
          }
        ],
        toolbar: [
          'imageStyle:full',
          'imageStyle:side',
          'imageTextAlternative',
          '|',
          'resizeImage'
        ]
      }
    }}
    

方案2:预构建编辑器的临时替代方案

若不想自定义构建,可通过ImageStyle插件配合自定义CSS实现近似效果:

config={{
  removePlugins: ['MediaEmbed'],
  image: {
    styles: [
      'full',
      'side',
      'alignLeft',
      'alignRight'
    ],
    toolbar: [
      'imageStyle:full',
      'imageStyle:side',
      'imageStyle:alignLeft',
      'imageStyle:alignRight',
      'imageTextAlternative'
    ]
  }
}}

添加自定义CSS控制样式宽度:

.ck-content .image-style-alignLeft {
  max-width: 50%;
  float: left;
  margin-right: 1em;
}
.ck-content .image-style-alignRight {
  max-width: 50%;
  float: right;
  margin-left: 1em;
}

三、完整修复后的组件代码示例

import { config } from '@/configs';
import { postFile } from '@/utils/fetch';
import { Editor } from '@ckeditor/ckeditor5-core';
import { regexDescription } from '@/utils/regex-message';
import { FileLoader, UploadAdapter } from '@ckeditor/ckeditor5-upload/src/filerepository';
import { useState } from 'react';
import dynamic from 'next/dynamic';

// 动态导入CKEditor,禁用SSR
const CKEditor = dynamic(() => import('@ckeditor/ckeditor5-react').then(mod => mod.CKEditor), {
  ssr: false,
  loading: () => <p>加载编辑器中...</p>
});
const ClassicEditor = dynamic(() => import('@ckeditor/ckeditor5-build-classic'), {
  ssr: false
});

const CKEditorComp = ({ name, formDesc, setFormDesc, register, error }: any) => {
  const [errorMsg, setErrorMsg] = useState('')
  const [isValid, setIsValid] = useState<boolean>(false)

  function uploadAdapter(loader: FileLoader): UploadAdapter {
    return {
      upload: () => {
        return new Promise(async (resolve, reject) => {
          try {
            const file: any = await loader.file;
            const { data } = await postFile(`?folder_path=images/blog&save_to=AWS&max_size=${config.MAX_FILE}`, { images: file });

            resolve({
              default: `${data.files[0].path}`,
            });
          } catch (error) {
            console.log(error)
            reject('图片上传失败');
          }
        });
      },
      abort: () => {},
    };
  }

  function uploadPlugin(editor: Editor) {
    /* @ts-ignore */
    editor.plugins.get('FileRepository').createUploadAdapter = (loader: any) => {
      return uploadAdapter(loader);
    };
  }

  const handleChange = (value: any) => {
    const check = regexDescription.regex.test(value)
    if(check){
      setIsValid(true)
      setErrorMsg('请勿使用HTML标签或类似内容')
    }else{
      setIsValid(false)
      setErrorMsg('')
      setFormDesc(value)
    }
  };

  return (
    <div>
      <CKEditor
        config={{
          extraPlugins: [uploadPlugin],
          removePlugins: ['MediaEmbed'],
          // 若使用自定义构建的编辑器,保留以下image配置;否则替换为方案2的配置
          image: {
            resizeOptions: [
              {
                name: 'resizeImage:original',
                value: null,
                label: '原始大小'
              },
              {
                name: 'resizeImage:50',
                value: '50',
                label: '50%'
              },
              {
                name: 'resizeImage:75',
                value: '75',
                label: '75%'
              },
              {
                name: 'resizeImage:custom',
                value: 'custom',
                label: '自定义'
              }
            ],
            toolbar: [
              'imageStyle:full',
              'imageStyle:side',
              'imageTextAlternative',
              '|',
              'resizeImage'
            ]
          }
        }}
        editor={ClassicEditor}
        data={formDesc}
        onChange={(event: any, editor: any) => handleChange(editor.getData())}
      />
      {isValid && errorMsg && (<p className="text-sm text-red-500">{errorMsg}</p>)}
    </div>
  )
};

export default CKEditorComp;

注意事项

  • 自定义构建CKEditor时,需确保所有依赖版本与项目中CKEditor React组件版本一致,避免版本冲突。
  • Next.js中使用CKEditor必须禁用SSR,否则会出现浏览器API未定义的错误。
  • 图片上传的postFile函数需确保能正确处理文件上传并返回有效图片URL,否则图片插入会失败。

内容的提问来源于stack exchange,提问作者Hovi Sohibul Wafa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 00:23:09