TipTap with ESM module

@patrick and @JonL do I understand correctly that using an ESM module is currently possible?

Or is this an AC2 benefit that I should wait for?

I need to integrate TipTap, and my client would prefer it be built in an extension as it opens up the possibility of sharing with the community if the work effort is not significantly greater.

I am using them without problems in AC1. I haven’t had time to touch AC2 at all but I don’t see why there would be problems there.

The only thing I find a bit hit&miss is finding the appropriate source if using a CDN. I use jsdelivr which provides their own ESM builds or you can also use the library one if thy provide it. Then you need to use the right import(default, named).

You will maybe find problems with the dynamic import() due to AC’s nature. But there are workarounds.

Thanks Jon.

Could you share an example of this?

I’m assuming I need to convert to require given this statement by @patrick

I’m starting with this vendor provided example:

import { Editor } from '@tiptap/core'
import StarterKit from '@tiptap/starter-kit'

new Editor({
  element: document.querySelector('.element'),
  extensions: [
  content: '<p>Hello World!</p>',

And would like to get that working in an AC extension.

CommonJS uses require and it’s meant for the backend.

In browsers you can use import.

You still need to add the script tag in the html with the source and type=module.

Or you can just use import() in your JS and skip the script tag but this sometimes has issues with AC depending on the library and what you are trying to do.

1 Like

Thanks Jon…closer.

<script type="module">
    import { Editor } from "https://esm.sh/@tiptap/core";
    import StarterKit from "https://esm.sh/@tiptap/starter-kit";

I can initialize successfully using from a cdn that was created. Doesn’t feel like a production source though. But at least I can keep moving forward.

Any idea how I can use a local source?

I’ve tried pointing to all of these, plus various src points, but can’t find anything that will work.

I’m obviously just grabbing at straws now…is there some pattern that I just don’t understand?

Sorry Ken,

I’ve been checking tiptap and they really want you to use ES modules in a best practice way.

If you are installing via npm and want to use them locally you would need to use a bundler like webpack/rollup/parcel/etc.

Using the files directly will only cause you pain and suffering. That’s because npm packages often use names as identifiers instead of file paths (like ‘@tiptap/core’). This would be resolved correctly by a bundler when building the project.

However if you really need to use ESM and don’t want to use a bundler you would have to use relative paths and point to the actual local file → index.js

import { Editor } from './@tiptap/core/dist/index.js'
import StarterKit from './@tiptap/starter-kit/dist/index.js'

But as I said this is a path of sorrow. You will most likely have to go through all the referenced files and change paths to relative routes.

So you have 4 options:

  1. Use a remote CDN version that already has been bundled for you. e.g. jsdelivr
  2. Use locally via npm and introduce a build step to bundle the files
  3. Use locally via npm and change all the named packages to relative paths → Pain and sorrow.
  4. Build from source for your needs.

For 4) here you have a GH repo that has all the files you need to build a browser version:

It basically imports core and starter-kit and attaches them to the window object. He then bundles them with Esbuild and he gets a single file ready to be used in a script tag.

Maybe @patrick has some ideas on how you could use Tiptap library locally without a bundler.

You can vote this one to have all this supported:

I think the solution from @JonL is the best (option 4). You keep it separate from the web project, use npm packages and a bundler to build the final script for usage in the web project.

Normally I would say to use the UMD module and just load it via a script tag, but it doesn’t seem tiptap delivers a script that includes all dependencies.

About the files in the dist folder:
index.cjs is the CommonJS version, you load it using require.
index.js is the ES module, you can load it using import or a script tag with type module.
index.umd.js is the Universal module, it can be loaded in multiple environments, you can also load this using a script tag.

Thanks guys for confirming that the typical routes I take were not going to work. I appreciate all the pointers! I’ll see what I can do with them.

Hey @mebeingken, I’m looking into TipTap. Did you have luck setting it up?

Nope, it never came together for me.

Their docs mention this as starter code. It uses https://esm.sh/ to import. I’m not sure if that helps, but I’m trying to see if it’s possible to intergrate with Wappler.

  <div class="element"></div>
  <script type="module">
    import { Editor } from 'https://esm.sh/@tiptap/core'
    import StarterKit from 'https://esm.sh/@tiptap/starter-kit'
    const editor = new Editor({
      element: document.querySelector('.element'),
      extensions: [
      content: '<p>Hello World!</p>',

Ya, loading from a cdn works, but it was posted as a dev only option. I never found a solution that I felt was production ready…but everybody has a different view on what that means.

Would just changing from import to require help?

const { Editor } = require('@tiptap/core');
const StarterKit = require('@tiptap/starter-kit');

new Editor({
  element: document.querySelector('.element'),
  extensions: [
  content: '<p>Hello World!</p>',

Maybe you will have better luck than I. :slight_smile: