See bottom of the page for latest updates
This vanilla TypeScript project shows how (remote) tiptap modules can be acquired through dynamic imports.
These dynamically loaded tiptap modules, themselves are depending on other modules (most noteably @tiptap/core
).
To satisfy these (secondary) dependencies, used by dynamically imported modules, this project uses importmaps.
This project effectively has two parts:
- a main project, consisting of an
index.html
and asrc/main.ts
file. - a tiptap extension project, consisting of
packages/extension-introduction/src/introduction.ts, index.ts
.
The main project's index.html
declares the es-module-shims.js
module.
This module enables importmaps
in all browsers that support ES6 modules
.
Note: that the shim-mode
is used so that this indeed works across browsers.
The main project uses three (standard) tiptap extensions (document, paragraph, text) which are not dynamically imported.
Additionally it uses the extension-introduction
tiptap extension which is loaded through dynamic import
.
These 4 extensions, together define the tiptap Editor
which is started in main.ts
.
This is a very simple tiptap extension that defines a Introduction
node as part of the schema.
The extensions uses @tiptap/core
, and/but the ES6 module that is created from it, declares this as something external
.
This means that at runtime (in the application), this @tiptap/core
depencency needs to be resolved somehow.
The main project uses importmaps for this.
The extension project leverages rollup.js to build the ES6 module.
This module is then subsequently copied to the remote-extensions
location/directory in the project.
This will be the directory, serviced through LiveServer
from which dynamic imports are resolved.
-
Go to the folder `packages/extension-introduction and run
pnpm run clean
=> cleans out any old stuffpnpm run build
=> constructs theextension-introduction-esm.js
module (from TypeScript sources)pnpm run copy
=> this copies the aboveES6 module
to theremote-extensions
location
-
To to the
root
folder and runpnpm run clean
=> cleans out any old stuffpnpm run build
=> creates the distribution build (from TypeScript sources)pnpm run live
=> startsLiveServer
and opensindex.html
from root in the browser
After this you should see a tiptap Editor
window.
You can also check the browser DevTools network tap, to see what all is loaded.
** Update December 10th, 2021 **
While revisiting this setup, looked again at the reason why initially we used shim mode.
In an other projects, I was only able to get stuff working with that mode (in dev).
The problem with that though is that the entry point index.html
no longer is processed by vitejs
.
The reason for this is that the module declaration for shim mode looks something like this:
<script type="module-shim" src="/dist/main.js"></script>
After having another go at using polyfill mode, I noticed that in this particular project,
that doesn't use vitejs
, stuff still works.
Notes
- In Google Chrome, no additional console error will appear
- In FF, an additional console error will appear (which can be ignored, according to the manual)
The message that is seen is:Uncaught TypeError: Error resolving module specifier “@tiptap/core”. Relative module specifiers must start with “./”, “../” or “/”.
See es-module-shims for additional information.
For this the index.html
looks something like this:
<html>
<head>
<script type="importmap">
// Your import map statements here
</script>
...
<head>
<body>
...
<script type="module" src="/src/main.ts"></script>
...
</body>
</html>
Will do another attempt in a project that does use vitejs
.
** Update December 10th, 2021 **
Checking the above in the project that does use vitejs
shows that this does not work in FF, Chrome dev mode nor FF production mode.
Only Chrome production mode works in that setup.
** Update December 10th, 2021 ** The problem with CDN import maps of tiptap apparently aren't support in production. See detail of this skypack issue
A way to mitigate the above issue, is to use local sources instead of CDN.
For this purpose all necessary dependencies are installed locally as dev dependencies.
Subsequently through pnpm run copy
the required ES6 module files are copied to /dist/js
.
And the index.html
importmap is changed accordingly.
Now running pnpm run live
still works, resolving dependencies locally instead of through CDN.
** Update December 10th, 2021 **
A result of this vanilla setup, where no bundler (like vitejs
) is used, is that it becomes more challenging to work with some frameworks.
For instance Vue3 uses SIFC (SIngle File Component) mechanism.
Basically this a single file where template
, script
and styles
are collecated in a single .vue
file.
It is possible to use Vue without this SIFC approach, whilst still working with the latest version capabilities (e.g. Composition API).
The fact of the matter is, is that working with these files is indeed a bit more challenging.
In this update, I've added a Vue component in vue
, which uses a CDN reference in the importmap.
Note that there is a tool called htm
that might make working with these components (especially templates) somewhat easier.
** Update December 24th, 2021 **
As the trail to use vitejs combined with importmaps and dynamic imports seem to get colder, looked into htm
.
In this update I actually use htm
to create the Vue App
component.
For additional information check the npm page.
** Update December 31th, 2021 **
Moved along with the approach that no longer uses vitejs.
Have a look at this issue for some vitejs background about this.
Additionally this was raised against es-module-shim
.
In this update, the direct tiptap plugins document
, paragraph
and text
, initially loaded via importmaps are removed.
Instead these plugins are now wrapped in tangelo
equivalents (see packages folder).
Effectively what this means, is that through some rollup
configuration (i.e. nodeResolve) we reuse tiptap code.
Additionally the file scenario-1.json
is introduced.
This is an example for how the editor can be made fully data-driven.
That file holds meta-data that specifies the extensions/plugins that are required.
Additionally it also holds the actual content of what the editor needs to present.
Note by no longer loading tiptap specific extensions from the importmap, and instead wrapping them in Tangelo counterparts, we implicitly mitigate the (perceived?) issue that exists in loading tiptap extensions from CDN. This means that the importmap as specified in index.html might actually work with a fully CDN based declaration.