How to build and use xterm.js locally?

oclyke picture oclyke · Sep 3, 2019 · Viewed 8.9k times · Source

I want to make some changes to the source code of xterm.js and test them before making a PR. I have been unsuccessful in generating a working 'distribution.'

(Apologies if my terminology is incorrect -- I am pretty new to web development)

Setup

I set up a simple test website with the following index.html

<!doctype html>
  <html>
    <head>
      <script src="%PUBLIC_URL%/xterm.js"></script>
    </head>
    <body>
      <div id="terminal"></div>
      <script>
        console.log(Terminal);
        var term = new Terminal();
        term.open(document.getElementById('terminal'));
        term.write('Hello from \x1B[1;3;31mxterm.js\x1B[0m $ ')
      </script>
    </body>
  </html>

In the location %PUBLIC_URL% I will place a JS source file xterm.js from either:

  • node_modules/xterm/dist/xterm.js - as added through npm
  • xterm.js/lib/xterm.js - as built from the GitHub repository

To build a local copy of xterm.js I took these steps:

git clone https://github.com/xtermjs/xterm.js.git xterm-local
cd xterm-local
npm install
npm run package

(Note: if you are following along at home I could not build xterm.js on Windows or Mac -- I only got through these steps using Ubuntu 18.04)

The commands all run successfully and the last one creates xterm-local/lib which contains xterm.js. I use that file to replace the copy that can be obtained from the NPM installation.

Results

Normal

When using the NPM dist/xterm.js I successfully see my terminal element rendered and the log reads

ƒ Terminal(options) {
        this._core = new Terminal_1.Terminal(options);
        this._addonManager = new AddonManager_1.AddonManager();
    }

Using local build

When using my locally built output from xterm-local/lib/xterm.js there is no terminal element rendered, there is an error: Uncaught TypeError: Terminal is not a constructor and the log reads

{Terminal: ƒ, __esModule: true}
  Terminal: ƒ e(e)
  __esModule: true
  __proto__: Object

Expectations

I would expect that after building my local copy of xterm.js that I could use it interchangeably with the NPM distribution. However I am curious why the command npm run package does not generate the dist folder but a lib folder instead. Are there additional steps that I am missing to make my own useable copy of xterm.js?

Answer

oclyke picture oclyke · Sep 8, 2019

I've reached a semi-acceptable solution so I'd like to share what I can.

This is not the demo you are looking for

Thanks to user Peter I found my way to xterm.js' wiki page about contributing (not to be confused with the CONTRIBUTING.md file in the repo itself). It was hard to find because to an uninitiated individual this line in the repo's CONTRIBUTING.md document:

Get the xterm.js demo running.

seems to refer to the demo that can be found on xtermjs.org with these simple instructions:

First you need to install the module, we ship exclusively through npm so you need that installed and then add xterm.js as a dependency by running:

npm install xterm

To start using xterm.js on your browser, add the xterm.js and xterm.css to the head of your html page. Then create a onto which xterm can attach itself. Finally instantiate the Terminal object and then call the open function with the DOM object of the div.

    <head>
      <link rel="stylesheet" href="node_modules/xterm/dist/xterm.css" />
      <script src="node_modules/xterm/dist/xterm.js"></script>
    </head>
    <body>
      <div id="terminal"></div>
      <script>
        var term = new Terminal();
        term.open(document.getElementById('terminal'));
        term.write('Hello from \x1B[1;3;31mxterm.js\x1B[0m $ ')
      </script>
    </body>   </html> ```

However that is not the case. Instead they are talking about running the demo application that lives in xterm.js/demo

Running the real demo

The xterm.js maintainers are very very very much more experienced than me. They've provided so many ways to build and run the demo that it can be daunting. Eventually the SourceLair option worked out for me despite my aversion to giving them my credit card info.

First make a fork of the xterm.js repo - this is important because you want to be able to change the source code!

Handy as it may be this 'shortcut' https://lair.io/xtermjs/xtermjs kind of doesn't help. What you really want to do is go to SourceLair, create a new project based on your own fork of xterm and choose the preset 'Node' environment. That will allow you to both test the changes you make (by using the web server tool) AND save your changes (because you used your own fork instead of using the upstream repo)

  • Go to SourceLair
  • Start a new project by cloning a repo
  • Provide your repo URL
  • Wait for initialization (git clone, yarn install, webkit compilation etc)
  • Create a new branch for your changes (in the Terminal git checkout -b [name_of_your_new_branch])
  • Make your changes
  • Test them out in the Public URL of the project
  • Commit and push your changes back to your repo

(if you want to skip using the web editors then you could make changes to your repo and pull those changes into Source Lair for testing)

Challenges with other methods

Just FYI.

  • Docker: It was easy to use this pre-configured image but it was not easy to make the changes I needed to from within the container.
  • Foreman (Procfile runners): never heard of 'em... too little time to waste (this is a hobby, mind you!)
  • Linux / MacOSX: On linux I could build but could not test (my only linux is a VPS that I just SSH into) and on Mac I could (presumably) test but not build (because at time of writing the node-gyp dependency failed hard)