Saturday, December 15, 2012

Experimenting with Dart Application Locations

‹prev | My Chain | next›

From the very beginning, I have built my Dart web applications the same way that I build my JavaScript applications—with client-side code directly in my web server's public directory. Last night, I finally tried to test my application and found that maybe, just maybe there is a better way of doing this.

The solution that I came up with last night was to put my Dart application code in the appcode directory directly under the root level of my website. I then manually symlink the appcode/web subdirectory into my site's public directory:
➜  dart-comics git:(master) ✗ tree
.
├── appcode
│   ├── packages
│   │   ├── hipster_mvc -> /home/chris/.pub-cache/hosted/pub.dartlang.org/hipster_mvc-0.2.0/lib
│   │   └── unittest -> /home/chris/.pub-cache/hosted/pub.dartlang.org/unittest-0.2.8+2/lib
│   ├── pubspec.lock
│   ├── pubspec.yaml
│   ├── test
│   │   ├── index.html
│   │   ├── packages -> /home/chris/repos/dart-comics/appcode/packages
│   │   └── Views.AddComicForm_test.dart
│   └── web
│       ├── Collections.Comics.dart
│       ├── main.dart
│       ├── ModalDialog.dart
│       ├── Models.ComicBook.dart
│       ├── packages -> /home/chris/repos/dart-comics/appcode/packages
│       ├── Views.AddComic.dart
│       ├── Views.AddComicForm.dart
│       └── Views.Comics.dart
├── public
│   ├── images
│   ├── index.html
│   ├── scripts
│   │   ├── dart_comics -> ../../appcode/web
│   │   ├── dart.js
│   └── stylesheets
│       └── style.css
...
The nice thing about this approach is that I can still run my appcode tests locally, none of the tests or other associated code is available in the public subdirectory, and Dart Pub works fine with the appcode—including when appcode/web is symlinked into public.

This got me to thinking—perhaps I can move appcode out into its own repository and then use pub install to add it to the website. There is one way to find out.

So I create that repository in $HOME/repos/dart-comics-app. The only change that I make is to the name in the pubspec.yaml to reflect its application status:
name: dart_comics_app
dependencies:
  hipster_mvc: any
  unittest: any
Back in the website public/scripts directory, I create a pubspec.yaml that will pull this application into the site:
name: scripts
dependencies:
  dart_comics_app:
    git: /home/chris/repos/dart-comics-app
In public/scripts, I run pub install:
➜  scripts git:(master) ✗ pub install
Resolving dependencies... 
Warning: Package "dart_comics_app" does not have a "lib" directory so you will not be able to import any libraries from it.
Dependencies installed! 
That does not seem promising. And indeed, that did not install dart_comics_app in the packages directory or anywhere else:
➜  scripts git:(master) ✗ tree  
.
├── dart.js
├── packages
│   ├── hipster_mvc -> /home/chris/.pub-cache/hosted/pub.dartlang.org/hipster_mvc-0.2.0/lib
│   └── unittest -> /home/chris/.pub-cache/hosted/pub.dartlang.org/unittest-0.2.8+2/lib
├── pubspec.lock
└── pubspec.yaml
Bummer. It seems like that won't work.

The dart_comics_app is included in the generated pubspec.lock:
{"packages":
{"dart_comics_app":{
  "version":"0.0.0",
  "source":"git",
  "description":{
    "url":"/home/chris/repos/dart-comics-app",
    "ref":null,
    "resolved-ref":"35f4fe3cb59da75457671347b7cc43b8dd718ed7"
  }
},
"hipster_mvc":{"version":"0.2.0","source":"hosted","description":"hipster_mvc"},
"unittest":{"version":"0.2.8+2","source":"hosted","description":"unittest"}
}}
And it did get installed into my pub cache:
➜  scripts git:(master) ✗ ls -l ~/.pub-cache/git/dart_comics_app-35f4fe3cb59da75457671347b7cc43b8dd718ed7 
total 16
-rw-r--r-- 1 chris chris  170 Dec 15 20:31 pubspec.lock
-rw-r--r-- 1 chris chris   71 Dec 15 20:31 pubspec.yaml
drwxr-xr-x 2 chris chris 4096 Dec 15 20:31 test
drwxr-xr-x 2 chris chris 4096 Dec 15 20:31 web
But that did not result in actually seeing that in my website. I could manually symlink the web subdirectory from my pub cache, but I do not see any advantage in doing that over simply keeping the code in an appcode directory in the website proper.

Ah well, at the risk of invoking sour grapes, I am not sure that a separate code repository would have bought me much anyway. There is definitely something to be said for keeping it in the codebase along with the rest of the site.


Day #600

2 comments:

  1. I believe that the intent is a little bit different. The 'web' directory should be the document root of the web site, while the application code should lie in the 'lib' directory, as with ordinary libraries or standalone applications. Like this:

    .
    ├── app
    │ ├── lib
    │ │ ├── Collections.Comics.dart
    │ │ ├── main.dart
    │ │ ├── ModalDialog.dart
    │ │ ├── Models.ComicBook.dart
    │ │ ├── packages -> /home/chris/repos/dart-comics/app/packages
    │ │ ├── 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
    │ │ └── unittest -> /home/chris/.pub-cache/hosted/pub.dartlang.org/unittest-0.2.8+2/lib
    │ ├── pubspec.lock
    │ ├── pubspec.yaml
    │ ├── test
    │ │ ├── index.html
    │ │ ├── packages -> /home/chris/repos/dart-comics/app/packages
    │ │ └── Views.AddComicForm_test.dart
    │ └── web
    │ ├── images
    │ ├── index.html
    │ ├── ModalDialog.dart
    │ ├── packages -> /home/chris/repos/dart-comics/app/packages
    │ ├── scripts
    │ └── stylesheets

    Note that there is a 'packages' symlink in the 'web' directory.

    Actually, when you do 'pub install', Pub will create add a symlink to the root-level 'packages' directory inside all these subdirectories: 'bin', 'example', 'test', 'tool' and 'web'.

    And now, you probably understand that from the 'web' directory, you will refer to your application code using 'package:app/...'.

    But this is likely to change, application deployment isn't a finished story yet.

    ReplyDelete
    Replies
    1. Oops, the content of the 'web' directory is shown badly. But I guess you understand the point :-)

      Delete