xterm.js icon indicating copy to clipboard operation
xterm.js copied to clipboard

ES6 module no export Terminal

Open elgs opened this issue 5 years ago • 28 comments

When I follow the doc to import Terminal as an ES6 module.

The recommended way to load xterm.js is via the ES6 module syntax:

import { Terminal } from 'xterm';

I got the following error. I opened the xterm.js and found it's an minified js file and it indeed didn't export Terminal.

The requested module '../../../node_modules/xterm/lib/xterm.js' does not provide an export named 'Terminal'

I'm not using any building tools. I just used plain ES6 import syntax.

elgs avatar Apr 27 '20 06:04 elgs

I don't know the details here on what TS does but TS works for me. I guess this is requesting a native ESM target which has come up before https://github.com/xtermjs/xterm.js/issues/2486

Tyriar avatar Apr 27 '20 13:04 Tyriar

What I am wondering is I've seen a few other libraries claiming they are supporting ES6, but they are in the same situation like this, like this one https://github.com/highlightjs/highlight.js/issues/2473. They use Rollup to build the library. I'm not familiar with Rollup.

My understanding of ES6 module is the library has some code syntax like:

export something = someFunction;

And the client is like:

import { something } from 'node_modules/someLib/someLib.js';

something();

I wonder if I misunderstood what ES6 is.

elgs avatar Apr 29 '20 00:04 elgs

This is a big deal, because with the REAL ES6 support, the client can get rid of the dependency of build tools, though the build tools are awesome, but at least it's not necessary.

elgs avatar Apr 29 '20 00:04 elgs

Yeah it would be nice to be on the latest and greatest but then you lose support for other better supported ways of importing. Eventually we'll move there but shipping a library that supports many different import types is tricky.

Tyriar avatar Apr 29 '20 01:04 Tyriar

I understand that. That's why if you look at the lodash package, they released a separate package called lodash-es. That is the REAL ES6 support. But unfortunately the export syntax is illegal in the nodejs like module system.

You mentioned:

but then you lose support for other better supported ways of importing

Actually, no, you don't lose anything in browser. All modern build tools support the REAL ES6 syntax. What you lose is the support to build for nodejs users. But for packages like xterm, and highlightjs, why does it matter at all. Who use them in Nodejs.

elgs avatar Apr 29 '20 03:04 elgs

lodash releases two separate packages for a wise reason, one for Nodejs and the other for browsers. Because the nature of lodash is that it is used in both Nodejs and browsers. In the old days, Javascript didn't have any module system in the browser, everything is bound to window, so that's why many build tools did many tricky things to translate the Nodejs module system to the browser window. That's understandable before REAL ES6 is usable in the browsers. Now ES6 is natively supported by browsers, packages like xterm and highlightjs should have no reason go around to the Nodejs module system.

elgs avatar Apr 29 '20 03:04 elgs

Is there any chance of moving to native modules in a major release? Every current major browser, and the past 3 major (soon to be 4 next moth) of Node, supports modules natively.

@Tyriar

then you lose support for other better supported ways of importing. Eventually we'll move there but shipping a library that supports many different import types is tricky.

I don't think there are better ways of importing than native modules. Every other way requires tools or userland loaders, and can be targeted with native modules and a tool anyway.

At this point I really don't think it'd even be worth it to publish two packages. Applications that support older browsers can really easily consume JS module dependencies and compile them to a different format. It's the default behavior for Rollup and Webpack.

One problem with not publishing standard JS modules is that you library is shut off from those that are using native modules. I'm trying to use a terminal widget for a project, but all my libraries are modules only, and there's no good way to import UMD from native modules.

justinfagnani avatar Sep 05 '20 00:09 justinfagnani

As I learned more about the whole thing. Now I know this is kind of like a fake ES6 support. Webpack did the trick to allow ES6 like syntax to import Nodejs modules.

elgs avatar Mar 08 '21 18:03 elgs

@elgs

I made an es6 export version with a fork here:

https://github.com/TomzBench/xterm.js

It is a fork with a set of different tsconfig files + rollup to export an es module. Hopefully this works for you.

you can test it by importing @altronix/xterm

TomzBench avatar Mar 09 '21 22:03 TomzBench

@TomzBench cool, thanks!

Can you please show an example assuming I don't have node or npm installed, which file should I import in the browser in order to use it?

elgs avatar Mar 09 '21 23:03 elgs

I import like this

import {Terminal} from "@altronix/xterm"

TomzBench avatar Mar 09 '21 23:03 TomzBench

Can you please tell me the absolute path of @altronix/xterm?

elgs avatar Mar 09 '21 23:03 elgs

npm install @altronix/xterm

Then it will be inside your node modules. Are you trying to import from cdn? Or a script tag?

TomzBench avatar Mar 09 '21 23:03 TomzBench

I am actually thinking about getting rid of the dependencies of node and rollup at all. I suddenly realized the source of this project is written in Typescript so it should be natively/immediately ready for Deno. And if we have for example an Angular project, we should be able to import the source code from this project without going through the rollup at all.

elgs avatar Mar 09 '21 23:03 elgs

xtermjs typescript sources uses "paths" and referenced projects and outputs es5. So to have it build es6 output you can look at my fork and copy the tsconfig.es6.json files if you want to build it that way. You can copy the es6 xterm.js file and paste it where ever you need it if you don't want to use node.

TomzBench avatar Mar 10 '21 00:03 TomzBench

I was getting this error with vite when using npm link & excluding xterm from vite's optimizeDeps config.

@TomzBench's fork fixes this.

staff0rd avatar Oct 18 '21 10:10 staff0rd

@Tyriar any news to real ES6 support?

jogibear9988 avatar Nov 19 '21 15:11 jogibear9988

Updates would be posted here

Tyriar avatar Nov 19 '21 15:11 Tyriar

@elgs

I made an es6 export version with a fork here:

https://github.com/TomzBench/xterm.js

It is a fork with a set of different tsconfig files + rollup to export an es module. Hopefully this works for you.

you can test it by importing @altronix/xterm

Good job! , Thankyou!

walterjj avatar Oct 31 '22 19:10 walterjj

Is there any official progress or recommended solution on this issue? This is still mentioned as the recommended way of importing the module on the website but it doesn't work. The fork is also behind and isn't really a sustainable solution to the issue.

Aurillium avatar Jan 20 '23 07:01 Aurillium

@Aurillium A proper move to full ESM support is quite involved, this mainly results from the fact, that TS has its own understanding of module resolution, and how far it allows to use ESM resolution beside the old nodejs resolution.

@Tyriar Could we do a lightweight transition during bundling, like creating an explicit ESM target for xterm.js and the addons? I currently do this in node-sixel with different tsconfig + webpack build targets, where the result is a proper ESM bundle. Downside - it is not properly reflected by node package exports, as this is more involved with the right entries in package.json, thus it will not work with pure nodejs ESM resolution yet. Still the browser would happily digest that as ESM. I dont see yet a full move to ESM for xterm.js, as we would have to sort out, which parts should go into native ESM resolution, and which would always need some sort of prebundling. Furthermore cutting off the current nodejs module resolution will create many frictions on most embedding projects...

This is still mentioned as the recommended way of importing the module on the website but it doesn't work.

Currently the docs snippets are written for TS, not JS. Plus the idea, that your TS project is set up with nodejs module resolution. It just happens, that TS uses a similar syntax to JS-ESM, but in fact translates things to require(xy) calls underneath. Imho thats just a misunderstanding from the docs - note that the import syntax in the snippets does not contain '.js' endings on modules. TS uses that syntax way longer than ESM is out in the wild.

The fork is also behind and isn't really a sustainable solution to the issue.

Yes, for long term thats not a viable solution, as forks always tend to show that issue.

jerch avatar Jan 20 '23 14:01 jerch

I gave a quick try to resync with the master branch but i get some compile errors now. so i probably won't be able to fix them unless i need to use this package with vite again.

TomzBench avatar Jan 20 '23 17:01 TomzBench

I just tried to use xtermjs for the first time in a deno project, and immediately bumped into the The requested module 'npm:[email protected]' does not provide an export named 'Terminal' issue..

johtso avatar Feb 02 '23 02:02 johtso

We're going to be forced to do this soon as VS Code is in the process of moving from AMD to ES6. I expect some progress on this in the next 2-6 months

Tyriar avatar Feb 02 '23 15:02 Tyriar

I managed to get things working by using the old version that @TomzBench kindly forked .. any tips on how I can import an addon? They have the same issue.

Edit: Ah, just found @altronix/xterm-addon-fit

johtso avatar Feb 02 '23 15:02 johtso

Loading as import "xterm" and then simply using const terminal = new Terminal() works.

Soesah avatar Sep 04 '23 13:09 Soesah

The module doesn't seem to be ES6 compatible. I sent a temporary quick fix while waiting for the native export

import {Terminal, SearchAddon, WebLinksAddon, FitAddon} from "@thimpat/xterm";

thimpat avatar Oct 01 '23 19:10 thimpat

I tried @altronix/xterm, but it's version 4.x and a little old, I forked and changed minimal code to output esm/module builds.

You can use it as import { Terminal } from "@liudonghua123/xterm";

OR

    <script type="importmap">
      {
        "imports": {
          "xterm": "https://unpkg.com/@liudonghua123/[email protected]/lib/xterm.js"
        }
      }
    </script>

And some code also need to update, see also https://github.com/xtermjs/xterm.js/issues/4256#issuecomment-1510977408.

liudonghua123 avatar Apr 01 '24 07:04 liudonghua123