Compile a Dart library to commonjs

414 views
Skip to first unread message

chris wales

unread,
Aug 31, 2020, 5:31:38 PM8/31/20
to Dart Misc
Hello,

I have a library that I wrote for use in some Flutter apps. It just exposes some classes that do some math. Is there a way to compile this library for use in a nodejs app? I first tried dart2js but that didn't work at all as there was no `main` method. dartdevc compiled it but its output was in AMD. The FAQ for dartdevc says:  

"Dartdevc can also generate ES6 (Harmony) and CommonJS (Node) modules, but these options aren’t currently supported by the build_web_compilers package used with the build_runner and webdev tools." 

I can't find an reference of the API or examples of what options I need to pass to dartdevc to get it output commonjs though. Does anyone know where I can find that?

Thanks!


Jake Macdonald

unread,
Sep 1, 2020, 2:38:59 PM9/1/20
to Dart Misc, qwa...@gmail.com
You can try out the `build_node_compilers` package - I don't know how up to date it is but it is a fork of build_web_compilers for node essentially.

Siggi Cherem

unread,
Sep 1, 2020, 4:28:12 PM9/1/20
to General Dart Discussion, qwa...@gmail.com
TL;DR: Generally speaking, though, we don't recommend using dartdevc to export functionality written in Dart to use it from JavaScript. The best we have at this time is to use JS-interop to export your APIs instead.

Our focus with dartdevc is to create a good experience for fast iteration during development. Its output is unstable and not meant to be used as an input to a larger JavaScript application. This is for many reasons. In part, because we are not optimizing the output for deployment. In some cases the code produced by dartdevc can be many times slower than the code produced by dart2js (our production compiler). Another reason is that we may break you accidentally, since this is not a supported pattern. For example, we currently have logic to emit multiple formats (es6, amd, etc), but we have plans to consolidate into a single module format. Given some constraints we have with support for hot-reload in flutter, this format is unlikely going to be node's.

Our recommended approach for interoperability with JavaScript is to use the `package:js` APIs. Those APIs were designed with the idea of importing JavaScript, rather than exporting Dart, but it is still possible to use it to export code. To do so, you will need to define a `main` method that declares how you want to export code from your library. For instance, you can declare some global names where your library will be expose members like this:

@JS()
library foo;

import 'package:my_math/my_math.dart' as mymath;
import 'package:js/js.dart';

@JS('mathMin')  // will be available on self.mathMin in JavaScript.
external set mathMinFunction(Function v);

main() {
   mathMinFunction = allowInterop(mymath.min);
}

With this approach, it will be possible to compile and optimize the code with our production compiler (dart2js). You'll also be in control of how Dart code is exposed, so you will be guarded from breaking changes in how our compilers represent code internally.

Hope this helps!
Cheers,
Siggi

--
For more ways to connect visit https://dart.dev/community
---
You received this message because you are subscribed to the Google Groups "Dart Misc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+uns...@dartlang.org.
To view this discussion on the web visit https://groups.google.com/a/dartlang.org/d/msgid/misc/ed73da7d-b158-4012-989c-9fdf44058047n%40dartlang.org.

Anatoly Pulyaevskiy

unread,
Sep 1, 2020, 4:43:51 PM9/1/20
to mi...@dartlang.org, qwa...@gmail.com
What Jake said.

There is even an example of how to create a node module which can be later imported into a Node.js project here:


There is also an e2e test which verifies that exports work.

That said I haven't tested this use case that much and only have this basic example. But hopefully it'll be a good starting point for you.

Best,
Anatoly

chris wales

unread,
Sep 9, 2020, 9:03:03 AM9/9/20
to Dart Misc, Sigmund Cherem, chris wales
Hi Siggi,

Thank you for the explanation of that warning. I saw it in the docs somewhere but now have a better understanding of what could happen. I did actually get the dartdevc compilation working with a simple class. The options "--help" and "-h" are overshadowed by the "-o" output dir check so it was tripped me up. I typoed "-help" by accident and saw the options. Going to play around with package:js and see how it goes. 

Chris

chris wales

unread,
Sep 9, 2020, 9:15:34 AM9/9/20
to Dart Misc, anatoly.p...@gmail.com, chris wales
Hi Anatoly,

Thanks! This is very cool. I was playing around with it and it seemed to have trouble with classes. I am not sure if I was doing something wrong though. I exported a function that took some arguments and returned a new instance of a class with those arguments but inspecting the compiled javascript it wasn't passing the arguments to the class constructor. And none of the methods seemed to be defined on the object. Do you know by chance if that should work? 

Chris

Anatoly Pulyaevskiy

unread,
Sep 10, 2020, 12:33:33 PM9/10/20
to chris wales, Dart Misc
Hi Chris,

Do you have an example Dart code which you’d like to compile to Node? 

JS interop is not very straightforward to use but I can try and help if I had an example.

Best,
Anatoly 

Anatoly Pulyaevskiy

unread,
Sep 16, 2020, 9:02:05 PM9/16/20
to chris wales, Dart Misc
Great! Glad to see you got it working.

On Wed, Sep 16, 2020 at 12:27 PM chris wales <qwa...@gmail.com> wrote:
Hi Anatoly,

I made a little repo of a basic example but while I was doing that started playing around some more and found something that I can definitely roll with.

Before I was trying to return an instance of the class:

class TwoNums {
  final int a;
  final int b;
  TwoNums(this.a, this.b);

  int add() {
    return a + b;
  }
}

TwoNums _factory(int a, int b) {
  return TwoNums(a, b);
}

void main() {
  setExport('factory', allowInterop(_factory));
}

But then changed it just to return the result of the work the class does which is really all I care about anyways and it totally works!

int _add(int a, int b) {
  return TwoNums(a, b).add();
}

void main() {
  setExport('add', allowInterop(_add));
}

Thank you for the help!

chris wales

unread,
Sep 17, 2020, 5:14:59 AM9/17/20
to Dart Misc, anatoly.p...@gmail.com, Dart Misc, chris wales
Hi Anatoly,

I made a little repo of a basic example but while I was doing that started playing around some more and found something that I can definitely roll with.

Before I was trying to return an instance of the class:

class TwoNums {
  final int a;
  final int b;
  TwoNums(this.a, this.b);

  int add() {
    return a + b;
  }
}

TwoNums _factory(int a, int b) {
  return TwoNums(a, b);
}

void main() {
  setExport('factory', allowInterop(_factory));
}

But then changed it just to return the result of the work the class does which is really all I care about anyways and it totally works!

int _add(int a, int b) {
  return TwoNums(a, b).add();
}

void main() {
  setExport('add', allowInterop(_add));
}

Thank you for the help!




On Thursday, September 10, 2020 at 12:33:33 PM UTC-4 anatoly.p...@gmail.com wrote:
Reply all
Reply to author
Forward
0 new messages