Building Prosemirror

I am adding Prosemirror 1.0.0 to a project and including it in the project’s build steps. It is unclear to me how best to build Prosemirror such that I end up with ES5 js file(s) at the end to later be concatenated and minified with the rest of the project’s javascript.

While I think I can make something that can build Prosemirror I want to make sure I do it right. I want it to be easy to update Prosemirror in the future and not have to update the Prosemirror build steps more than necessary going forward.

As best as I can tell rollup is used to compile the javascript from the /src to the /dist directory of each module. Should I rollup each module in my project build system? After which point can the module files be included in any order? I noticed the output of those files have a ‘use strict’ statement at the top. Since I plan on concatenating the files together I’d have to wrap the files in an iife first.

Is this a good approach? Also once I do have the javascript figured out I still have the CSS to build.

As I do not know rollup('s syntax) at all, I’m using webpack to build and test ProseMirror. My webpack.config.js looks like

module.exports = {
  entry: "./index.js",
  output: {
    filename: "./dist/bundle.js"
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader'
      }
    ]
  }
}

My package.json is configured that npm start runs webpack-dev-server, that automatically refreshes the browser window after recompiling the sources:

"scripts": {
  "start": "webpack-dev-server --open",
  …

If anyone knows a better approach, please tell us.

We don’t use webpack so that config is rather foreign to me. I’ll take a look at webpack to better understand it.

Switching to Webpack, however, is not an option for us.

This is what Webpack or maybe Rollup should do for you.

Why is using Webpack not an option?

We use grunt for our build process and I did not think webpack could be used with it. But it looks like a grunt webpack plugin does exist so maybe webpack is an option.

You can use a standalone Browserify/babelify build to output an ES5 bundle quite easily:

package.json

{
  "scripts": {
    "build": "./node_modules/.bin/browserify index.js --outfile prosemirror.js -t [ babelify --presets [ es2015 ] ]"
  },
  "dependencies": {
    "prosemirror-collab": "^1.0.0",
    "prosemirror-commands": "^1.0.0",
    "prosemirror-dropcursor": "^1.0.0",
    "prosemirror-example-setup": "^1.0.0",
    "prosemirror-gapcursor": "^1.0.0",
    "prosemirror-history": "^1.0.0",
    "prosemirror-inputrules": "^1.0.0",
    "prosemirror-keymap": "^1.0.0",
    "prosemirror-markdown": "^1.0.0",
    "prosemirror-menu": "^1.0.0",
    "prosemirror-model": "^1.0.0",
    "prosemirror-schema-basic": "^1.0.0",
    "prosemirror-schema-list": "^1.0.0",
    "prosemirror-state": "^1.0.0",
    "prosemirror-tables": "^0.3.0",
    "prosemirror-transform": "^1.0.0",
    "prosemirror-view": "^1.0.0"
  },
  "devDependencies": {
    "babel-preset-es2015": "^6.24.1",
    "babelify": "^7.3.0",
    "browserify": "^14.4.0",
    "uglify-js": "^3.1.2"
  }
}

index.js

const collab = require("prosemirror-collab");
const commands = require("prosemirror-commands");
const dropcursor = require("prosemirror-dropcursor");
const gapcursor = require("prosemirror-gapcursor");
const history = require("prosemirror-history");
const inputrules = require("prosemirror-inputrules");
const keymap = require("prosemirror-keymap");
const markdown = require("prosemirror-markdown");
const model = require("prosemirror-model");
const schemaBasic = require("prosemirror-schema-basic");
const schemaList = require("prosemirror-schema-list");
const state = require("prosemirror-state");
const tables = require("prosemirror-tables");
const transform = require("prosemirror-transform");
const view = require("prosemirror-view");

window.ProseMirror = {
    collab,
    commands,
    dropcursor,
    gapcursor,
    history,
    inputrules,
    keymap,
    markdown,
    model,
    schemaBasic,
    schemaList,
    state,
    tables,
    transform,
    view
}

I ended up using grunt-rollup in our Grunt build. The main reason I went with rollup is that Prosemirror uses it internally for building. I modeled my rollup config off of Prosemirror’s website/bin/build-library.js.

Gruntfile.js

var rollupPluginNodeResolve = require('rollup-plugin-node-resolve');
var rollupPluginCommonjs = require('rollup-plugin-commonjs');
var rollupPluginBuble = require('rollup-plugin-buble');

...

rollup: {
    options: {
        format: 'iife',
        sourceMap: true,
        plugins: function () {
            return [
                rollupPluginNodeResolve({
                    main: true,
                    preferBuiltins: false
                }),
                rollupPluginCommonjs(),
                rollupPluginBuble()
            ];
        }
    },
    pm: {
        files: {
            'vendors/prosemirror.js': ['prosemirror.bundle.js']
        }
    }
}

prosemirror.bundle.js

// Used as input to Rollup to generate the prosemirror js file

import * as model from 'prosemirror-model';
import * as transform from 'prosemirror-transform';
import * as state from 'prosemirror-state';
import * as view from 'prosemirror-view';
import * as keymap from 'prosemirror-keymap';
import * as inputrules from 'prosemirror-inputrules';
import * as history from 'prosemirror-history';
import * as commands from 'prosemirror-commands';
import * as schemaBasic from 'prosemirror-schema-basic';
import * as schemaList from 'prosemirror-schema-list';
import * as dropcursor from 'prosemirror-dropcursor';
import * as gapcursor from 'prosemirror-gapcursor';
import * as menu from 'prosemirror-menu';
import * as tables from 'prosemirror-tables';
import * as exampleSetup from 'prosemirror-example-setup';
import * as OrderedMap from 'orderedmap';

window.pm = {
  model, transform, state, view, keymap, inputrules, history, commands,
  schemaBasic, schemaList, dropcursor, menu, tables, exampleSetup, gapcursor,
  OrderedMap
};

Thanks everyone for the help and suggestions. It looks like we have quite a few examples of how to build Prosemirror using different build systems now.

1 Like