InfomediaLtd / angular2-redux-example

Example project for using pure Redux with Angular 2 and TypeScript
MIT License
71 stars 14 forks source link

can you include your favorite debugging workflow #3

Closed born2net closed 8 years ago

born2net commented 8 years ago

It would be awesome if you include your favorite workflow as far as debugging, do you use live sever or express? which arguments do you use... with gulp? or do you use ts watch or others?

tx as always

seen

rubyboy commented 8 years ago

I usually use live-server with both my IDE (currently using Atom) and Chrome open on the same screen, side-by-side. I'm running a terminal session inside the IDE. The Chrome Developer Tools is pretty awesome with debugging and with the help of Source Maps you can break in the TypeScript code. The Redux dev tools helps as well. The only thing I'm missing is hot reloading without losing state (and just the file that changed), but I haven't got that set up just yet.

With JSPM (which I absolutely love!) you don't really need a watcher because it uses the TypeScript loader on the fly, so you get the best of all worlds, with just a simple live-server and no need to recompile before serving again. I do use Gulp for running the build (testing, linting, and bundling the final distribution). I also use Gulp to run a little script that takes care of typings for me (using the "typings" project). You can find the Gulp scripts under "tasks" folder. For tests I do a similar thing by running the "npm test" on a terminal on the side of my IDE and writing/fixing tests while it's reloading it.

Here's an example of how it looks like when testing the app in a browser: debugging

born2net commented 8 years ago

as always right on the money... I am intrigued.. I use gulp for for my live-reload, which I am not a fan of, since sometimes you always get extra reloads... I just moved to JSPM from Webpack (becuase of your project) and I am very impressed with it... can you share more info on JSPM, does it have a watch? or you just run it by hand to recompile each time?

here is my gulp

gulp.task('x_server_systemjs', ['x_ts-compile', 'x_watch2'], function () {
    process.stdout.write('Starting browserSync and superstatic...\n');
    browserSync({
        port: 8003,
        open: false,
        files: ['index.html', '**/*.js'],
        injectChanges: true,
        logFileChanges: true,
        logLevel: 'info',
        logSnippet: true,
        logPrefix: 'log:',
        notify: true,
        reloadDebounce: 4000,
        server: {
            baseDir: './',
            directory: true,
            middleware: superstatic({debug: false})
        }
    });
    opn('http://localhost:8003/src/public/index_sys.html')
});

but sounds I could do better with JSPM? tx again

Sean

born2net commented 8 years ago

I watch your awesome gif again, but didnt see how you executed JSPM to watch... By the way, I am using Webstorm...

rubyboy commented 8 years ago

JSPM works in a different way. It uses SystemJS when loading its files, thus being able to convert them on the fly. It support loading various module formats (ES6, AMD, CJS, you name it!), then running it through plug-ing (what you would call "loader" in the Webpack world) and only then loading it in the browser. So, that means there is no "js" file being generated on the server. It's all happening on the client.

Notice the network tab when the app loads: image It only loads the "ts" files. Then, it generates the "js" ones and you can find both in the "sources" tab: image

So, no watcher aside from "live-server" that watchers the vanilla files and kicks of a browser reload when files change. The transpilation is happening in the browser. Now, this is only relevant for development environment. In prod, you would definitely want to run the transpiled code. Look at the "dist" gulp task, or just run it on the example project ("npm run dist"). Comment out the "lint" bit if it's complaining about code formatting :) . Then, run "live-server" and go to http://localhost:8080/dist . This will be the end user experience on prod - loading just "js" as a single minified file.

A lot of it was inspired by Glen Maddern's awesome awesome presentation Javascript in 2015 . The creator of JSPM is Guy Bedford and he is amazing! You can watch an old talk he gave here: Package Management for ES6 Modules

born2net commented 8 years ago

I understand, will have to play with it ASAP... tx again...

rubyboy commented 8 years ago

No worries. Feel free to ask any JSPM related questions. I've used it extensively when getting the architecture ready for our company's modern projects and know it quite well by now. BTW, another huge benefit that you get with JSPM is the whole dependency management. It knows what depends on what and makes versioning management really easy. You can see here - https://github.com/InfomediaLtd/angular2-tutorial - some more examples of using JSPM with some different dependencies than this one.

born2net commented 8 years ago

ya read about it... love it!

rubyboy commented 8 years ago

You're missing the application config and loading any dependencies. Check out this minimal config for Angular 2: https://github.com/InfomediaLtd/angular2-tutorial/tree/master/1-getting-started

Basically, do a "jspm init" in a folder and you should be golden from there.

Here's a guide I've written, part of the tutorial series that the angular2-tutorial code accompanies, that will help you get started: 01 Getting Started with Angular 2.pdf

born2net commented 8 years ago

SWEET... will read it all.. ya I did add

System.config({
    baseURL: "/",
    defaultJSExtensions: true,
    transpiler: "typescript",
    typescriptOptions: {
        "module": "commonjs",
        "emitDecoratorMetadata": true
    },
    packages: {
        "app": {
            "main": "main",
            "defaultExtension": "ts"
        },
        "studioEnterprise": {
            "main": "src/App.ts",
            "defaultExtension": "ts"
        }
    },

playing with it some more..

born2net commented 8 years ago

got it!!!! TX again!!!! working... now I can't sleep, too excited... nerd I know

rubyboy commented 8 years ago

There's just two small things to fix and then you're good to go.

In your index.html change the import to be "src":

    System.import('src')

In your config.js update the package config:

  packages: {
    "src": {
      "main": "App",
born2net commented 8 years ago

exactly...

packages: {
    "src": {
      "main": "App",

u guru ;)

born2net commented 8 years ago

if u ever come down to Los Angeles, dinner is on me!!!

rubyboy commented 8 years ago

My pleasure. If you ever come to Israel, likewise :)

born2net commented 8 years ago

how did you know it was "src:" as many different examples online had app and other variations.. does that need to match the directory ...

are you serious? I am Israeli, Ma kore.. I come to Israel every couple of years...

born2net commented 8 years ago

so next summer I will be in Israel, will get together, I stay at Ramat aviv... ok Holech lishon... Toda al hakol... appreciate it! FYI I own digitalsignage.com, so maybe we can talk about some work options.. if you have time, we can talk soon on the phone... Yalla bye!

rubyboy commented 8 years ago

Small world. I'm currently in Ness Ziona. Lived in Sydney for 7 years and moved back to Israel with the family a few months ago. BTW, I assume you can find my Twitter handle (same as username here) so it may be easier to chat over there. Or email (rubyboy@gmail.com) :)

Laila Tov!

born2net commented 8 years ago

will do :)

born2net commented 8 years ago

Boker tov, I was wondering why you like the gulp minifier better over the built in minifier in JSPM

jspm bundle moduleA + module/b [outfile] [--minify]

tx

Sean

born2net commented 8 years ago

nvm, when I minified with the built in one, nothing loaded :) tx

rubyboy commented 8 years ago

If I remember correctly the reason I did that was a bug in Angular 2 (at least until beta-2) where it wasn't loading properly if you also minified variable/function/argument names. Notice that the Gulp task has "mangle:false" for the uglify task. I had to do that, even though it means less minified code, to get it working. It was working prior to the beta's (alpha 4x), so I assume it's just a matter of waiting for an angular-2 version with this fixed.

born2net commented 8 years ago

got it, ya I remember seeing a bug on that, cool tx.

born2net commented 8 years ago

for me in order for eveyrthing to work, I have to include: <script src="https://code.angularjs.org/2.0.0-beta.1/angular2-polyfills.js"></script> but in your code it works with it.. any idea why? just wondering...

born2net commented 8 years ago

hopefully they release new ts paths feature https://github.com/Microsoft/TypeScript/issues/5039

rubyboy commented 8 years ago

The two main things that you need from the polyfills are reflect-metadata and zone.js . You did import reflect-metadata in your app.ts, but you need to also install and import zone.js.

Install it with (I used a specific version so it's compatible with the one that the specific Angular2 version is using):

jspm install zone.js@0.5.10

Then, in your app.ts add:

import "zone.js/dist/zone.min.js";

Now, you can get rid of the script line in index.html (which I don't like because it has a specific version in it and needs maintaining) and Angular2 can properly detect that the service call has completed and trigger its component refresh :)

Yeah, I'm waiting for that TS feature as well. I'm still not sure if it makes it into 1.8 or 2.0. I've written a whole workaround guide for our developers to provide typings intellisense until the TS project fixes it. You can have a look: Dependency Typings.pdf

born2net commented 8 years ago

this is great, do you have links to all your pdfs? love the ones you shared so far

rubyboy commented 8 years ago

Send me your email and I'll send them through. I need to figure out a way to convert them from Confluence to public friendly format. The images may be a problem - some are screen grabs from a presentation I liked, so it's good for sharing internally but not for using publicly.

born2net commented 8 years ago

I like how you passed the function to the child component, smart...

born2net commented 8 years ago
...            <tr *ngFor="#item of list">           
       <td *ngIf="!content" (click)="select.emit(item)">{{item}}</td>           
       <td *ngIf="content" (click)="select.emit(item)">{{content(item)}}</td> ..
born2net commented 8 years ago

good reading so far, in ch-3


  "jspm": {
    "dependencies": {
      "angular2": "npm:angular2@^2.0.0-beta.2",
      "angular2-simple-list": "github:InfomediaLtd/angular2-simple-list@master",

why does jspm need to update the package.json, isnt' config.js enough for it? when you run jspm install, wouldn't it only look only at config.js? so what's the reason for updating package.json... reason I'd like to understand, if I add new packages in the future, I need to maintain updates to both config,js and package.json? (might be good to update in book as well)

born2net commented 8 years ago

Another question I had is that on the last chapter you mentioned create a d.ts file for custom libraries, and I'm wondering why do you need to do that if you're working in a pure typescript environment, and intelisence should work off the orignal source files no?

great read so far...

born2net commented 8 years ago

FYI: " mhegazy commented 5 hours ago @born2net (that's me) this change does not support JSPM directly, you can add a path mapping for every package you use.

see #6012 for JSPM support. "

from here: https://github.com/Microsoft/TypeScript/issues/5039

may interest you...

born2net commented 8 years ago

so done with pdf, really nice work.. its not easy reading for someone new.. I have spent 1+ months playing with Redux, rxjs, (jspm lately) ng2, es6 and the rest of their friends so understood it all, great job. However I would expect readers to follow your links in the docs in order to grasp all the new tech...

another question I have and still not 100% sure is why and the benefits of Typings vs DT... I guess specifically: "and external modules have clearly defined boundaries (no parts are ambient)" ... does that mean we import the types instead of using the ///reference tag? I guess what I was missing in the doc is how do we use the new "Typings" syntax...

good stuff that doc.

rubyboy commented 8 years ago

Thanks for the feedback. Much appreciated!

Re: why JSPM specified dependencies in two places. It's probably a question to JSPM's creator :) , but as for my understanding I think that the source of truth for JSPM is package.json. config.js is used by SystemJS and JSPM is the one responsible for bridging between package.json and config.js. JSPM installs dependencies off of what package.json specifies. Then, the specific version that is installed gets written to config.js. Notice that package.json can say angular2@^2-beta.2 and that means that only versions above beta.2 will be installed (not less). Then, during JSPM installation (or JSPM update) it will choose the right version and put that on config.js. It can change as you install other dependencies and update versions, but the source rules are in package.json. config.js has lots of other bits of information (transitive dependencies, etc.) and is the one used by SystemJS when loading the files at runtime. I think you should refrain from updating the dependencies in config.js yourself. This should always be done with the JSPM CLI (install, uninstall, update, etc.). I do, however, find myself updating package.json versions when needed, to maintain consistency between library versions (zone.js matching angular's dependency, etc.).

Re: d.ts. I agree that theoretically it should find the "ts" files and use them, and I'd love for that to work out of the box. But, because "jspm_packages" is excluded from tsc, the files in there are not used by TSC, thus it doesn't recognise them. So, the way I've worked around that was by using "typings" to collect the d.ts for libraries that have them and add the ones that are missing. I tried various options, where I did include jspm_packages, but always had trouble with another library getting compiled accidentally. The other approach would be to specify what I want to include in TSC (instead of "exclude"), but that required specifying versions and I didn't want to have to update tsconfig with every new library or version that I change. If you find a better workflow I will be more than happy to adopt it :)

Re: Typings vs. DT. I think Typings is the newer project, created to replace DT. I liked the typings.json approach where it it used for installing the types (similar to how JSPM works with its dependencies), so I just went with it. Recently the creator of typings spoke in the AngularAir podcast and explained about it: http://audio.angularair.com/e/typescript-deep-dive-with-alex-eagle-and-blake-embrey

Thanks for the awesome feedback and your questions. It's great to have someone ask and challenge my thoughts. The set of tutorials was mainly built for a few days of training, where I go through it with a class. Less for someone to go through it themselves, so your comments do make sense. It's a lot to take in and very difficult to grok it all in one read. BTW, I've also planned some mini-project at the end, basically replicating the angular2-redux-example :) - Angular 2 Training Project.pdf

born2net commented 8 years ago

GOT IT! Toda al hakol... till the next Q ;)

born2net commented 8 years ago

by the way, I tried to use typings, and I included in my module for example: ///<reference path="../typings/main.d.ts"/>

but got a TS error of:

Error:(18, 5) TS2309: An export assignment cannot be used in a module with other exported elements.

basically it didnt like the export = trunk in the typing file:

// Compiled using typings@0.6.6
// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/75249b97104d00c1ca2451ac29369009a5f2b101/redux-thunk/redux-thunk.d.ts
// Type definitions for redux-thunk
// Project: https://github.com/gaearon/redux-thunk
// Definitions by: Qubo <https://github.com/tkqubo>
// Definitions: https://github.com/borisyankov/DefinitelyTyped

declare module ReduxThunk {
    export interface Thunk extends Redux.Middleware {}
    export interface ThunkInterface {
      <T>(dispatch: Redux.Dispatch, getState?: () => T): any;
    }
}

declare module "redux-thunk" {
    var thunk: ReduxThunk.Thunk;
    export = thunk;
}
rubyboy commented 8 years ago

Does it happen to you also in the angular2-tutorial project inside the 7-redux step?

I did notice something funky with the export of this module. I think you had trouble with importing it and had to change the way it was imported. Later on I had the same issue in the angular2-redux project...

rubyboy commented 8 years ago

In that project (7-redux) run "npm run typings" to get the typings to be created.

born2net commented 8 years ago

it was in my own project, it's ok I will play with it some more... tx

born2net commented 8 years ago

any tips on this issue I have: https://github.com/jspm/jspm-cli/issues/1504

rubyboy commented 8 years ago

Not sure what you're trying to do there. Are you trying to bundle just part of your application? Is that for a purpose for building several bundles to be loaded lazily or for creating libraries?

Does regular self executing bundle work for you?

jspm bundle-sfx src/app out.js --skip-source-maps

(and then just import "out.js" in a top folder index.html)

Also - side note - wouldn't you want to bundle the "ts" itself and not the "js"? Not that this wouldn't change the result, but I was wondering why you would want to go down to the "js" in bundling. JSPM should produce the js from the source ts anyway...

born2net commented 8 years ago

yes I was trying to lazy load Modules... but so far no luck if I do a multi bundle config with jspm. It works fine if I don't bundle, but of course it just loads from dir directly as in:

static LoadComponentAsync(name:string, path:string) {

        return System.import(path).then(c => c[name]);
        ...

I will play with it some more tx...

born2net commented 8 years ago

Hi again, How did you get TS compiler to not complain about:

import style from "./user-view.css!text"
@Component({
selector: 'user',
styles: [style],

as I get: Error:(14, 19) TS2307: Cannot find module './user-view.css!text'. Error:(20, 5) TS2345: Argument of type '{ selector: string; directives: (typeof ModalDialog | Type[])[]; templateUrl: string; style: any[...' is not assignable to parameter of type '{ selector?: string; inputs?: string[]; outputs?: string[]; properties?: string[]; events?: strin...'. Object literal may only specify known properties, and 'style' does not exist in type '{ selector?: string; inputs?: string[]; outputs?: string[]; properties?: string[]; events?: strin...'.

regards, Sean

rubyboy commented 8 years ago

I didn't. I use JSPM's TypeScript plugin, which goes around this problem by adding its own module resolution: https://github.com/Microsoft/TypeScript/issues/4595

Why do you need it to not complain? Are you using TSC outside of JSPM for some reason? There's a good discussion about this problem here: https://github.com/Microsoft/TypeScript/issues/2709 The feature to support this in TSC is here (expected in 2.0, I think): https://github.com/Microsoft/TypeScript/issues/6615

born2net commented 8 years ago

ya I am using webstorm, no worries tx

rubyboy commented 8 years ago

Oh, right. Yeah, I've got a little dotted red line in Atom as well :)

BTW, I'm a huge fan of IntelliJ, but I've abandoned it a couple of months ago in favour of Atom (for web development only) because I got annoyed by its constant reindexing and slowdown when running "npm install"/"jspm install". Did you work around this somehow or do you just accept it? I still believe it's the best IDE around for productivity, but I just couldn't bear with the lags and constant freezing...

born2net commented 8 years ago

ha yes, just right click on the folde, select from the context menu "mark directory as" and set as excluded. Do that for node_modules, jspm and dist and it will never reindex all this stuff. also be sure to .gitignore in the root of the project as:

src/**/*.map
src/**/*.js
src/*.js
src/*.map
/src/*.js
/src/*.map

and everything will work great!!! I love the latest Webstorm early release, has all the Angular2 goodnes

rubyboy commented 8 years ago

Nice! I'll give that a try. Might just reignite my love for IntelliJ again :)

born2net commented 8 years ago

cool, not sure if intellij has the latest ng2 intellisence... maybe try webstorm beta, its free while beta

rubyboy commented 8 years ago

Do you have the TypeScript compiler enabled or do you just use the JavaScript language settings on 6/7 and let it resolve that automatically without TS compilation? image

I think the two are the same, aren't they? They following similar EAP releases. Do you have an example of ng2 intellisense feature of Webstorm that I can try it on my IntelliJ?

BTW, I quite liked Atom's experience - it's fast and the UI is nice and clean...