DEV Community

Cover image for CKEditor 5, Webpacker, VueJS, and you.
Brandon Cordell
Brandon Cordell

Posted on • Edited on

CKEditor 5, Webpacker, VueJS, and you.

The documentation for using CKEditor 5 with VueJS is pretty good, at least as far as open source technical documentation goes, but it makes the assumption that you're using vue-cli so it falls a bit short if you've set up Webpacker yourself or you're using Rails/Webpacker like I am.

Note: I am building CKEditor from source rather than using the prebuilt package.

The Setup

First we need to add the proper packages to build CKEditor in our project.

yarn add @ckeditor/ckeditor5-vue \
         @ckeditor/ckeditor5-dev-webpack-plugin \ 
         @ckeditor/ckeditor5-dev-utils \
         raw-loader@0.5.1
Enter fullscreen mode Exit fullscreen mode

Next we can prepend a new instance of CKEditorWebpackPlugin to
environment.plugins in config/webpack/environment.js.

// config/webpack/environment.js

const { environment } = require('@rails/webpacker');
// ... existing `require`s
const CKEditorWebpackPlugin = require('@ckeditor/ckeditor5-dev-webpack-plugin');

// ... existing code

environment.plugins.prepend('CKEditorWebpackPlugin', new CKEditorWebpackPlugin({
  addMainLanguageTranslationsToAllAssets: true,
  buildAllTranslationsToSeparateFiles: true,
  language: 'en',
}));

module.exports = environment;
Enter fullscreen mode Exit fullscreen mode

Don't forget to restart your server when your webpack config changes!

If you only use the language property like the documentation shows you'll be met with two errors.

[CKEditorWebpackPlugin] Error: No JS asset has been found during the compilation. You should add translation assets directly to the application from the `translations` directory. If that was intentional use the `buildAllTranslationsToSeparateFiles` option to get rid of the error.
[CKEditorWebpackPlugin] Error: Too many JS assets has been found during the compilation. You should add translation assets directly to the application from the `translations` directory or use the `addMainLanguageTranslationsToAllAssets` option to add translations for the main language to all assets or use the `buildAllTranslationsToSeparateFiles` if you want to add translation files on your own.
Enter fullscreen mode Exit fullscreen mode

Now that the Webpack plugin is set up we need to configure how the CKEditor SVG icons and css are parsed so we'll set up a loader for each. I like to keep my config/webpack/environment.js as clean as possible so we'll be creating small modules to include.

First we'll deal with the SVG icons. We need to use raw-loader to load the SVG icons as text.

Create the following config/webpack/loaders/ckeditor-svg.js

// config/webpack/loaders/ckeditor-svg.js

module.exports = {
  test: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
  use: 'raw-loader',
};
Enter fullscreen mode Exit fullscreen mode

Let's go ahead and create the CKEditor css loader at
config/webpack/loaders/ckeditor-css.js.

// config/webpack/loaders/ckeditor-css.js

const { styles } = require('@ckeditor/ckeditor5-dev-utils');

module.exports = {
  test: /ckeditor5-[^/\\]+[/\\].+\.css$/,
  use: [{
    loader: 'style-loader',
    options: {
      injectType: 'singletonStyleTag',
      attributes: {
        'data-cke': true,
      },
    },
  }, {
    loader: 'postcss-loader',
    options: styles.getPostCssConfig({
      minify: true,
      themeImporter: {
        themePath: require.resolve('@ckeditor/ckeditor5-theme-lark'),
      },
    }),
  }],
};
Enter fullscreen mode Exit fullscreen mode

Now back in config/webpack/environment.js we can require these files and prepend them to environment.loaders.

// config/webpack/environment.js

const { environment } = require('@rails/webpacker');
// ... existing `require`s
const ckeditorSvgLoader = require('./loaders/ckeditor-svg');
const ckeditorCssLoader = require('./loaders/ckeditor-css');

// ... existing code

environment.loaders.prepend('ckeditor-svg', ckeditorSvgLoader);
environment.loaders.prepend('ckeditor-css', ckeditorCssLoader);

module.exports = environment;
Enter fullscreen mode Exit fullscreen mode

If we try to compile our project now it will fail with the following error (or something similar) for every CKEditor css file:

ERROR in ./node_modules/@ckeditor/ckeditor5-ui/theme/components/<component>/<stylesheet>.css (./node_modules/postcss-loader/src??ref--1-1!./node_modules/mini-css-extract-plugin/dist/loader.js!./node_modules/css-loader/dist/cjs.js??ref--5-1!./node_modules/postcss-loader/src??ref--5-2!./node_modules/@ckeditor/ckeditor5-ui/theme/components/<component>/<stylesheet>.css)
Module build failed (from ./node_modules/postcss-loader/src/index.js):
SyntaxError

(1:1) Unknown word

 > 1 | // extracted by mini-css-extract-plugin
Enter fullscreen mode Exit fullscreen mode

To fix this we'll have to exclude CKEditor's assets for our other loaders. Add the following lines to config/webpack/environment.js.

// config/webpack/environment.js

// ... the rest of the code

// The default value for css.exclude is `/\.module\.[a-z]+$/`
environment.loaders.get('css').exclude = [
  /\.module\.[a-z]+$/,
  /ckeditor5-[^/]+\/theme\/[\w-/]+\.css$/,
];
environment.loaders.get('file').exclude = path.resolve(__dirname, '..', '..', 'node_modules', '@ckeditor');
environment.loaders.get('moduleCss').exclude = /ckeditor5-[^/]+\/theme\/[\w-/]+\.css$/;

module.exports = environment;
Enter fullscreen mode Exit fullscreen mode

Using CKEditor

Add the packages you need.

yarn add @ckeditor/ckeditor5-editor-classic \
         @ckeditor/ckeditor5-essentials \
         @ckeditor/ckeditor5-basic-styles \
         @ckeditor/ckeditor5-link \
         @ckeditor/ckeditor5-paragraph \
         @ckeditor/ckeditor5-theme-lark
Enter fullscreen mode Exit fullscreen mode

For the sake of this article I'll activate CKEditor in my pack so it can be used application-wide.

// app/javascript/packs/application.js

import CKEditor from '@ckeditor/ckeditor5-vue';
import Vue from 'vue/dist/vue.esm';

Vue.use(CKEditor);

// ... the rest of the pack
Enter fullscreen mode Exit fullscreen mode

From here we can use the <ckeditor> component anywhere in our Vue app.

<template>
  <div id="app">
    <ckeditor
      v-model="editorData"
      :config="editorConfig"
      :editor="editor"
    />
  </div>
</template>

<script>
import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';

import BoldPlugin from '@ckeditor/ckeditor5-basic-styles/src/bold';
import EssentialsPlugin from '@ckeditor/ckeditor5-essentials/src/essentials';
import ItalicPlugin from '@ckeditor/ckeditor5-basic-styles/src/italic';
import LinkPlugin from '@ckeditor/ckeditor5-link/src/link';
import ParagraphPlugin from '@ckeditor/ckeditor5-paragraph/src/paragraph';

export default {
  data: () => ({
    editor: ClassicEditor,
    editorData: '<p>Content of the editor.</p>',
    editorConfig: {
      plugins: [
        BoldPlugin,
        EssentialsPlugin,
        ItalicPlugin,
        LinkPlugin,
        ParagraphPlugin,
      ],

      toolbar: {
        items: [
          'bold',
          'italic',
          'link',
          'undo',
          'redo',
        ],
      },
    },
  }),
};
</script>
Enter fullscreen mode Exit fullscreen mode

And that's it. Now go create!

Top comments (0)