# Pure ESM module loading in browser?

**URL:** https://discuss.prosemirror.net/t/pure-esm-module-loading-in-browser/2657
**Category:** Uncategorized
**Created:** [April 5, 2020, 9:45am UTC](https://discuss.prosemirror.net/t/pure-esm-module-loading-in-browser/2657 "2020-04-05T09:45:27Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![andersmad](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/andersmad/32/1670_2.png) [@andersmad](https://discuss.prosemirror.net/u/andersmad)
#### Post date: [April 5, 2020, 9:45am UTC](https://discuss.prosemirror.net/t/pure-esm-module-loading-in-browser/2657/1 "2020-04-05T09:45:27Z")

</div>

Hi, I’m a n00b when it comes to loading js files - so can anyone tell me how I do pure ESM/ES6/ES2020 (?) module loading in latest Chrome browser? I can load e.g. `import { EditorState } from "../node_modules/prosemirror-state/dist/index.es.js"` (using latest TypeScript) but from there it goes `import OrderedMap from 'orderedmap';` - and that cannot be resolved to anything. Same if loading from “src”.

What am I doing wrong? As primarily a backender - module loading in ecmascript seems very “noisy” and have given me a small headache in the last couple of hours 😃 - so sry if this is not related to Prosemirror per say. Are there any boilerplate sample of getting started with Prosemirror out there? Pref. with dynamic loading.

---

<div class="post-metadata">

### Author: ![marijn](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/marijn/32/15_2.png) [@marijn](https://discuss.prosemirror.net/u/marijn)
#### Post date: [April 5, 2020, 12:12pm UTC](https://discuss.prosemirror.net/t/pure-esm-module-loading-in-browser/2657/2 "2020-04-05T12:12:59Z")

</div>

You’re not doing anything wrong. This is a giant gap left in the (initial) implementation of ES modules in browsers. There’s work in progress to make it (a little) easier with [import maps](https://github.com/WICG/import-maps), but that’s only available on Chrome, behind a flag, and still requires you to create such a map.

You _should_ be able to use a server like [esmoduleserve](https://github.com/marijnh/esmoduleserve) to rewrite non-precise imports to precise ones on the fly, and load a ProseMirror-based app that way. I haven’t tried yet with ProseMirror, but that’s how I’m doing development on CodeMirror 6 now, which has a very similar module structure.

---

<div class="post-metadata">

### Author: ![andersmad](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/andersmad/32/1670_2.png) [@andersmad](https://discuss.prosemirror.net/u/andersmad)
#### Post date: [April 5, 2020, 12:19pm UTC](https://discuss.prosemirror.net/t/pure-esm-module-loading-in-browser/2657/3 "2020-04-05T12:19:16Z")

</div>

Thank you! That lifted a dark cloud from my head! Trying to find a missing puzzle piece that never existed… 🤯

---

<div class="post-metadata">

### Author: ![andersmad](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/andersmad/32/1670_2.png) [@andersmad](https://discuss.prosemirror.net/u/andersmad)
#### Post date: [April 5, 2020, 4:13pm UTC](https://discuss.prosemirror.net/t/pure-esm-module-loading-in-browser/2657/4 "2020-04-05T16:13:45Z")

</div>

I got it to work like this - pure ESM using a tiny shimmer - tried to make a `indexOf('prosemirror-')` smartenheiner to avoid the bloated map for when there’s logic - but that’s not in the shim and also - it’s not in the “not-so-standard-yet” ESM:

```auto
<script defer src="/node_modules/es-module-shims/dist/es-module-shims.js"></script>
<script type="importmap-shim">{ "imports": {
	"orderedmap": "/node_modules/orderedmap/index.es.js",
	"rope-sequence": "/node_modules/rope-sequence/dist/index.es.js",
	"crelt": "/node_modules/crelt/index.es.js",
	"w3c-keyname": "/node_modules/w3c-keyname/index.es.js",
	"prosemirror-state": "/node_modules/prosemirror-state/dist/index.es.js",
	"prosemirror-view": "/node_modules/prosemirror-view/dist/index.es.js",
	"prosemirror-model": "/node_modules/prosemirror-model/dist/index.es.js",
	"prosemirror-schema-basic": "/node_modules/prosemirror-schema-basic/dist/index.es.js",
	"prosemirror-schema-list": "/node_modules/prosemirror-schema-list/dist/index.es.js",
	"prosemirror-transform": "/node_modules/prosemirror-transform/dist/index.es.js",
	"prosemirror-history": "/node_modules/prosemirror-history/dist/index.es.js",
	"prosemirror-commands": "/node_modules/prosemirror-commands/dist/index.es.js",
	"prosemirror-dropcursor": "/node_modules/prosemirror-dropcursor/dist/index.es.js",
	"prosemirror-gapcursor": "/node_modules/prosemirror-gapcursor/dist/index.es.js",
	"prosemirror-menu": "/node_modules/prosemirror-menu/dist/index.es.js",
	"prosemirror-inputrules": "/node_modules/prosemirror-inputrules/dist/index.es.js",
	"prosemirror-keymap": "/node_modules/prosemirror-keymap/dist/index.es.js"
}}</script>
<script type="module-shim">
	importShim.fetch = async (url) => await fetch(url.indexOf('.js') < 0 ? url + ".js" : url);
</script>
....
<script type="module-shim">
	import { Fancy } from "./prosemirror/typescript-prosemirror.js"
	const pants = new Fancy();
</script>

```

learned a lot about javascript loaders today - and I don’t like it at all! 😃but there you go if anyone needs to get started with prosemirror using a super simple setup as non-longhaired-and-slow-build-and-bundle-script-and-runners thingies… this `"es-module-shims": "^0.4.6",` goes into package.json

EDIT: You can drop the “importShim.fetch” line if not pointing to /src/ stuff or import like “./stuff” - then we are back to the ESM “std.” i spose…

---

<div class="post-metadata">

### Author: ![andersmad](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/andersmad/32/1670_2.png) [@andersmad](https://discuss.prosemirror.net/u/andersmad)
#### Post date: [April 8, 2020, 8:21am UTC](https://discuss.prosemirror.net/t/pure-esm-module-loading-in-browser/2657/5 "2020-04-08T08:21:48Z")

</div>

FYI on the ESM topic - I suggested this for the shim: [https://github.com/guybedford/es-module-shims/issues/80](https://github.com/guybedford/es-module-shims/issues/80) (Pre-url map lookup handling)

---

<div class="post-metadata">

### Author: ![bruce](https://discuss.prosemirror.net/letter_avatar_proxy/v4/letter/b/ccd318/32.png) [@bruce](https://discuss.prosemirror.net/u/bruce)
#### Post date: [April 8, 2020, 7:18pm UTC](https://discuss.prosemirror.net/t/pure-esm-module-loading-in-browser/2657/6 "2020-04-08T19:18:02Z")

</div>

Thanks for this. I’m very much a noobie to the world of JavaScript and imports, exports, require, npm, etc. I only understand 50% of this conversation. I’d appreciate it if one of you (andersmad or marijn) could spell it out for me at a more basic level.

Basically, all I want is to be able to use ProseMirror in a static html page on my local computer.

I want to be able to load a JavaScript file in that page where I can use all the ProseMirror classes, for instance, call the Schema constructor to build a new schema:

`const mySchema = new Schema( {...} ) `

I don’t know how to do this. I’ve tried various methods.

I puzzled my way through the `require-pm.js` file that Marijn uses on his webpage to enable the `require` syntax. Then I was able to include the following line in my HTML page,

`<script src="https://prosemirror.net/examples/prosemirror.js"></script>`

which would then magically create a `PM` global object containing lots of pre-loaded things, like a `state`, a `view`, a `keymap`. But it didn’t give me the ability to call the `Schema` class constructor directly. So now I am stuck.

---

<div class="post-metadata">

### Author: ![marijn](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/marijn/32/15_2.png) [@marijn](https://discuss.prosemirror.net/u/marijn)
#### Post date: [April 8, 2020, 7:56pm UTC](https://discuss.prosemirror.net/t/pure-esm-module-loading-in-browser/2657/7 "2020-04-08T19:56:15Z")

</div>

> [@bruce](#):
>
> Basically, all I want is to be able to use ProseMirror in a static html page on my local computer.

You will need to run a bundler to do that. I recommend [Rollup](https://rollupjs.org). You’d write your code `import`-ing ProseMirror components, then run rollup on it to produce a single big file that has everything you use in it, and include that with a `<script>` tag.

> [@bruce](#):
>
> ``
> 
> which would then magically create a `PM` global object containing lots of pre-loaded things, like a `state` , a `view` , a `keymap` . But it didn’t give me the ability to call the `Schema` class constructor directly. So now I am stuck.

`Schema` should be under `PM.model.Schema` in that bundle.

---

<div class="post-metadata">

### Author: ![bruce](https://discuss.prosemirror.net/letter_avatar_proxy/v4/letter/b/ccd318/32.png) [@bruce](https://discuss.prosemirror.net/u/bruce)
#### Post date: [April 8, 2020, 8:36pm UTC](https://discuss.prosemirror.net/t/pure-esm-module-loading-in-browser/2657/8 "2020-04-08T20:36:42Z")

</div>

> [@marijn](#):
>
> You will need a bundler to do that. I recommend Rollup.

Thanks for your answer. I’ve looked at Rollup, because you mentioned it before. I am 90% there now. But there is still a conceptual difficulty I have. Namely, I don’t understand the workflow of creating a JavaScript-based webpage that uses modules. It seems to place the chicken before the egg. Namely, you must -first- write all your code blindly, importing the ProseMirror library with import statements. You are not able to run it yet since the browser doesn’t understand what you are talking about! And then, when you’re finished this incredible task of writing a webpage without once being able to “run” your code, you magically “rollup” your code into a “bundle.js” file which you can finally include in the html, and then for the first time you can actually load your webpage! This is very confusing to me. I am missing something important…!

---

<div class="post-metadata">

### Author: ![andersmad](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/andersmad/32/1670_2.png) [@andersmad](https://discuss.prosemirror.net/u/andersmad)
#### Post date: [April 9, 2020, 8:22am UTC](https://discuss.prosemirror.net/t/pure-esm-module-loading-in-browser/2657/9 "2020-04-09T08:22:21Z")

</div>

@bruce: rollup or webpack goes through the jungle of js module loading and makes one big file to be used from the browser… that’s good if you don’t need async module loading, using slow http1 and it can tree shake it so it leaves out unused stuff etc…

however i like the dynamic loading - and I do think i posted all the code needed for that above here… this way you don’t have to build anything (tiny clean fast devel. setup) - the browser will load it as it needs it… its using a “shim” meaning that its features to come to the browser - they are just not there yet, so a clever dude made it happen using that shim that tries to follow the coming standard…

if your not experimenting for next gen stuff as I am - go with the rollup/webpack/pre-build stuff… or grab the big prosemirror.js from the sample/doc site… you make e.g. rollup execute each time a file changes - then if you use typescript (then you don’t code “blindly”) you save, it transpiles and then it packs the files and then you F5 to see what’s what 🙂

---

<div class="post-metadata">

### Author: ![marijn](https://discuss.prosemirror.net/user_avatar/discuss.prosemirror.net/marijn/32/15_2.png) [@marijn](https://discuss.prosemirror.net/u/marijn)
#### Post date: [April 9, 2020, 9:30am UTC](https://discuss.prosemirror.net/t/pure-esm-module-loading-in-browser/2657/10 "2020-04-09T09:30:31Z")

</div>

> [@bruce](#):
>
> Namely, you must -first- write all your code blindly, importing the ProseMirror library with import statements.

There’s nothing stopping you from running rollup during development to test your current work. It even has a `-w` command line option that makes it constantly rebuild your project as you change files.

---

<div class="post-metadata">

### Author: ![bruce](https://discuss.prosemirror.net/letter_avatar_proxy/v4/letter/b/ccd318/32.png) [@bruce](https://discuss.prosemirror.net/u/bruce)
#### Post date: [April 9, 2020, 9:57am UTC](https://discuss.prosemirror.net/t/pure-esm-module-loading-in-browser/2657/11 "2020-04-09T09:57:32Z")

</div>

Ok - thanks a lot to you both for your help.

---

<div class="post-metadata">

### Author: ![pet](https://discuss.prosemirror.net/letter_avatar_proxy/v4/letter/p/82dd89/32.png) [@pet](https://discuss.prosemirror.net/u/pet)
#### Post date: [April 9, 2020, 4:52pm UTC](https://discuss.prosemirror.net/t/pure-esm-module-loading-in-browser/2657/12 "2020-04-09T16:52:57Z")

</div>

I refreshed the [script](https://github.com/dogma-creative/pm-basic-example) I used to setup PM basic example so maybe it will help you to quick test the editor in browser.

---

<div class="post-metadata">

### Author: ![simplygreatwork](https://discuss.prosemirror.net/letter_avatar_proxy/v4/letter/s/e56c9b/32.png) [@simplygreatwork](https://discuss.prosemirror.net/u/simplygreatwork)
#### Post date: [August 13, 2020, 2:07am UTC](https://discuss.prosemirror.net/t/pure-esm-module-loading-in-browser/2657/13 "2020-08-13T02:07:51Z")

</div>

@andersmad It is unbelievably awesome that you posted the import-shim setup. Thank you so much for taking the time to figure this out. I’ll aim to create a new starter project for Prosemirror with this setup plus the content of prosemirror-example-setup builtin and hackable inside the starter app. Bravo!
