Sunday, December 16, 2012

Yet Another Try at Dart Client Code Organization

‹prev | My Chain | next›

All right, let me give this one more try. After last night's failed experiment with code organization for Dart web applications, Ladislav Thon suggested an alternate approach. And I think it makes a good deal of sense.

His suggestion was to stop trying to put stuff in the public directory. Instead, I ought to make the web subdirectory of my application code the "public" directory from which all HTML, CSS, and Dart is served. I make that happen in my server.dart web server by updating the paths for my public directory handler. Then I move a bunch of code around, ending up with the following directory structure:
➜  dart-comics git:(master) ✗ tree app
app
├── lib
│   ├── Collections.Comics.dart
│   ├── main.dart
│   ├── ModalDialog.dart
│   ├── Models.ComicBook.dart
│   ├── Views.AddComic.dart
│   ├── Views.AddComicForm.dart
│   └── Views.Comics.dart
├── packages
│   ├── hipster_mvc -> /home/chris/.pub-cache/hosted/pub.dartlang.org/hipster_mvc-0.2.0/lib
│   ├── scripts -> /home/chris/repos/dart-comics/app/lib
│   └── unittest -> /home/chris/.pub-cache/hosted/pub.dartlang.org/unittest-0.2.8+2/lib
├── pubspec.lock
├── pubspec.yaml
├── test
│   ├── <test code here>
└── web
    ├── dart.js
    ├── index.html
    ├── packages -> /home/chris/repos/dart-comics/app/packages
    └── stylesheets
        ├── packages -> /home/chris/repos/dart-comics/app/packages
        └── style.css
I update the index.html to point to the new locations of the JavaScript kicker and the main.dart file:
<head>
  <title>Dart Comics</title>
  <link rel="stylesheet" href="/stylesheets/style.css">

  <script src="/dart.js"></script>
  <script src="/packages/scripts/main.dart" type="application/dart"></script>
</head>
But that main.dart won't work there because I am reaching under the Dart Pub covers by sourcing main.dart from the packages path. The primary problem being that all of the associated libraries are not found. So I move it into app/web as well.

That almost works, but I still need to update the import paths in main.dart to pull from the "scripts" package:
import 'package:scripts/Collections.Comics.dart' as Collections;
import 'package:scripts/Views.Comics.dart' as Views;
import 'package:scripts/Views.AddComic.dart' as Views;

import 'dart:html';
import 'dart:json';

import 'package:hipster_mvc/hipster_sync.dart';

main() {
  // ...
}
It is the "scripts" package by virtue of the name listed in the pubspec.yaml in the app directory:
name: scripts
dependencies:
  hipster_mvc: any
  unittest: any
Witht that, I have my application back in business:


I think I can live with that application structure. Then end result is:
app
├── lib
│   ├── Collections.Comics.dart
│   ├── ModalDialog.dart
│   ├── Models.ComicBook.dart
│   ├── Views.AddComic.dart
│   ├── Views.AddComicForm.dart
│   └── Views.Comics.dart
├── packages
│   ├── hipster_mvc -> /home/chris/.pub-cache/hosted/pub.dartlang.org/hipster_mvc-0.2.0/lib
│   ├── scripts -> /home/chris/repos/dart-comics/app/lib
│   └── unittest -> /home/chris/.pub-cache/hosted/pub.dartlang.org/unittest-0.2.8+2/lib
├── pubspec.lock
├── pubspec.yaml
├── test
│   ├── HipsterCollectionTest.dart
│   ├── index.html
│   ├── packages -> /home/chris/repos/dart-comics/app/packages
│   └── Views.AddComicForm_test.dart
└── web
    ├── dart.js
    ├── index.html
    ├── main.dart
    ├── packages -> /home/chris/repos/dart-comics/app/packages
    └── stylesheets
        ├── packages -> /home/chris/repos/dart-comics/app/packages
        └── style.css
The only thing about which I am unsure is including the main.dart file directly in the app/web directory. The old-fashioned way of doing that is putting it in a scripts directory. Maybe I am just stuck in my old ways and this is, in fact fine. Then again, it might be worth exploring a bit more tomorrow.

Update: It turns out that moving dart.js and main.dart into app/web/scripts works just fine. I just have to update the paths in index.html and re-run pub install to get the packages directory set up properly in app/web/scripts:
└── web
    ├── index.html
    ├── packages -> /home/chris/repos/dart-comics/app/packages
    ├── scripts
    │   ├── dart.js
    │   ├── main.dart
    │   └── packages -> /home/chris/repos/dart-comics/app/packages
    └── stylesheets
        ├── packages -> /home/chris/repos/dart-comics/app/packages
        └── style.css
That also explains why stylesheets gets a packages symlink.


Day #601

2 comments:

  1. You can actually put the entrypoint Dart script into two places and both will make sense.

    If you want to include it in the page using <script src=".../main.dart" type="application/dart"></script>, then it makes sense to put it inside the 'web' directory, like you did.

    You can also put it into the 'lib' directory and do something like this:

    <script type="application/dart">
    import 'package:app/main.dart' as app;

    main() => app.main();
    </script>

    Depends on the taste, I'd say that both approaches are correct.

    ReplyDelete
    Replies
    1. Heh. I've been avoiding the inline <script> thing for much the same reason that I disliked having main.dart in the same path as index.html — that's just not how this cranky old man has been doing it. But really, not being able to import directly in a script tag is a limitation of HTML, so this slightly awkward workaround might be OK.

      I'll definitely play with it. Thanks!

      Delete