mgechev / angular-seed

🌱 [Deprecated] Extensible, reliable, modular, PWA ready starter project for Angular (2 and beyond) with statically typed build and AoT compilation
https://mgechev.github.io/angular-seed
MIT License
4.57k stars 1.45k forks source link

Application decoupling #913

Closed mgechev closed 8 years ago

mgechev commented 8 years ago

Purpose

Allow easier development of multi-platform applications with easy code reuse across them.

Make the entire client-side application and its dependencies, decoupled from the build process and encapsulated inside src/client.

Background

At the moment we have our client application in the src/client directory and the build-related tasks in tools. Although we have this separation, all the client-side related dependencies and testing configuration are global (test-main.js, karma.config.js, protractor.config.js).

This makes it unpractical to use the seed for development of multiple Angular applications for different platforms which are sharing common features.

For instance, in case we want to develop backend for the current application, which reuses some of the logic which is already defined by services in the client-side, we need to:

This approach is not modular and has several drawbacks:

.
β”œβ”€β”€ appveyor.yml
β”œβ”€β”€ gulpfile.ts
β”œβ”€β”€ src
β”‚Β Β  └── client
β”‚       β”œβ”€β”€ dist
β”‚       β”œβ”€β”€ coverage
β”‚Β Β      β”œβ”€β”€ app
β”‚Β Β      β”œβ”€β”€ assets
β”‚Β Β      β”œβ”€β”€ css
β”‚Β Β      β”œβ”€β”€ index.html
β”‚       β”œβ”€β”€ test-main.js
β”‚Β Β      β”œβ”€β”€ tsconfig.json
β”‚       β”œβ”€β”€ karma.conf.js
β”‚       β”œβ”€β”€ package.json
β”‚       β”œβ”€β”€ protractor.conf.js
β”‚Β Β      └── typings.d.ts
β”œβ”€β”€ tools
β”œβ”€β”€ tsconfig.json
β”œβ”€β”€ tslint.json
β”œβ”€β”€ typings
β”œβ”€β”€ package.json
└── typings.json

@NathanWalker's advanced seed should benefit a lot from the proposal above.

// cc @ludohenin @d3viant0ne @TheDonDope @nareshbhatia

TheDonDope commented 8 years ago

Hi all!

I really like the proposal, it does make a lot of sense to relocate this client specific to this more appropiate place.

I agree, the advanced seed of @NathanWalker would benefit from this refactor. One point still sticks out for me: shouldn't the client directory get a more specific name? Maybe ng2-clientor something like this? If the approach is to enable multiplatform/multiclient apps, how would one differentiate between the different clients? But really, that is just a minor issue :)

mgechev commented 8 years ago

May be web-client?

NathanWalker commented 8 years ago

Great proposal @mgechev. How about just web?

Then you could have something like following for all sorts of scalability: I feel as the naming should be very platform specific and stay away from things like client or frontend since we truly are in the new brave world of true cross platform development with Angular 2.

.
β”œβ”€β”€ appveyor.yml
β”œβ”€β”€ gulpfile.ts
β”œβ”€β”€ src
β”‚   └── desktop
β”‚   └── reactnative
β”‚   └── nativescript
β”‚   └── server
β”‚   └── web
β”‚       β”œβ”€β”€ dist
β”‚       β”œβ”€β”€ coverage
β”‚       β”œβ”€β”€ app
β”‚       β”œβ”€β”€ assets
β”‚       β”œβ”€β”€ css
β”‚       β”œβ”€β”€ index.html
β”‚       β”œβ”€β”€ test-main.js
β”‚       β”œβ”€β”€ tsconfig.json
β”‚       β”œβ”€β”€ karma.conf.js
β”‚       β”œβ”€β”€ package.json
β”‚       β”œβ”€β”€ protractor.conf.js
β”‚       └── typings.d.ts
β”œβ”€β”€ tools
β”œβ”€β”€ tsconfig.json
β”œβ”€β”€ tslint.json
β”œβ”€β”€ typings
β”œβ”€β”€ package.json
└── typings.json
joshwiens commented 8 years ago

IMO "web" would be the most explicit without getting into something platform specific or non-descript like "public".

Call it web / browser but it's probably best to keep it's naming related to the platform being used for delivery like the rest.

NathanWalker commented 8 years ago

I like browser too @d3viant0ne Either way.

NathanWalker commented 8 years ago

What's nice about this direction is the platform specific naming conventions can be left for the user to decide:

.
β”œβ”€β”€ appveyor.yml
β”œβ”€β”€ gulpfile.ts
β”œβ”€β”€ src
β”‚   └── desktop  <-- could be electron or something else.
β”‚   └── mobile <-- could be nativescript, reactnative, or something else.
β”‚   └── server
β”‚   └── web
β”‚       β”œβ”€β”€ dist
β”‚       β”œβ”€β”€ coverage
β”‚       β”œβ”€β”€ app
β”‚       β”œβ”€β”€ assets
β”‚       β”œβ”€β”€ css
β”‚       β”œβ”€β”€ index.html
β”‚       β”œβ”€β”€ test-main.js
β”‚       β”œβ”€β”€ tsconfig.json
β”‚       β”œβ”€β”€ karma.conf.js
β”‚       β”œβ”€β”€ package.json
β”‚       β”œβ”€β”€ protractor.conf.js
β”‚       └── typings.d.ts
β”œβ”€β”€ tools
β”œβ”€β”€ tsconfig.json
β”œβ”€β”€ tslint.json
β”œβ”€β”€ typings
β”œβ”€β”€ package.json
└── typings.json
TheDonDope commented 8 years ago

web sounds good to me too!

mgechev commented 8 years ago

Ok, let's call it web.

arm5472 commented 8 years ago

Great idea @mgechev. This decoupling makes perfect sense. I also like web.

joshwiens commented 8 years ago

Not that I want to debate it endlessly but if we are naming things based on the medium used as a content delivery method, browser is technically more accurate.

ludohenin commented 8 years ago

I vote for browser as well and second @d3viant0ne

ludohenin commented 8 years ago

... but the proposal rocks.

NathanWalker commented 8 years ago

It's a good debate and naming is always hard.

browser cons:

Platform examples: web, mobile, desktop, server, tv, xbox

Angular and React are vehicles to develop for all platforms above. NativeScript and ReactNative are vehicles to develop for the mobile platform. Electron and NW.js are vehicles to develop for the desktop platform. Express, PHP, and Ruby on Rails are vehicles to develop for the server platform.

Then there are the crossover vehicles like Ionic and Cordova which can be used to develop for web and mobile platforms. This is where browser is ruled out as a platform since to say that Ionic is a vehicle for the browser is true but not definitive because browser is not a platform, but to say Ionic is a vehicle for the web platform is accurate since it can be used to develop for the browser and for a hybrid app because it definitively is a vehicle for the web platform.

Just my 2 cents.

joshwiens commented 8 years ago

Platform examples: web, mobile, desktop, server, tv, xbox

It really comes down to how what and how you think about delivery mediums. To me web is a generic term that encompasses the interconnects between delivery mediums of which something like the Chrome web browser is one.

In the end naming this is funky now because the lines between delivery mediums has been blurred significantly, which is only going to get worse.

We could ask 100 people and it would probably be split down the middle for web / browser. In the end I think either choice conveys the intent well enough to get the purpose across.

Either way, imo this refactoring idea is probably the most beneficial out of any that have landed. You can call it purple fluffy bunnies so long as the change lands in #master :)

ludohenin commented 8 years ago

Just to bring extra water to the mill πŸ˜„(I want to see browser win) (source wikipedia)

web

The World Wide Web (WWW) is an information space where documents and other web resources are identified by URLs, interlinked by hypertext links, and can be accessed via the Internet.

browser

A web browser (commonly referred to as a browser) is a software application for retrieving, presenting, and traversing information resources on the World Wide Web.

That's pretty straight forward, isn't it ? The entire world is probably wrong calling apps web applications which are in fact browser applications. Shit, we have to tell the entire world now :)

joshwiens commented 8 years ago

I'll create the issue to inform the planet and just go ahead and assign that one to you @ludohenin . If you could get on that right after the whole offline compile feature, that would be great...thanks.

Shyam-Chen commented 8 years ago

Why not web? If integration Material and Firebase be weird.

TheDonDope commented 8 years ago

Just as @d3viant0ne said:

We could ask 100 people and it would probably be split down the middle for web / browser.

To add onto that, i'd like to quote Phil Karlton:

There are only two hard things in Computer Science: cache invalidation and naming things.

The corresponding PR isn't finished, so there could still be changes, and though i personally tend towards web too, but i went ahead with browser because i flipped a coin with web being heads and browser being tails, and tails showed.

two_face_6711

spicemix commented 8 years ago

How about a src/shared directory for platform-independent/isomorphic core code that can be unit tested/profiled on its own?

NathanWalker commented 8 years ago

@spicemix I really like the thought of that πŸ‘ There will certainly be some universal/isomorphic code with this kind of setup.

NathanWalker commented 8 years ago

@TheDonDope I'll be using web in advanced seed so whatever you guys wanna use here, makes no difference to me :)

joshwiens commented 8 years ago

@TheDonDope - Are you still stuck on the what package goes where step to all of this?

If so, i'll PR the changes into your current working branch on your fork so we can bring this one home.

wolfganga commented 8 years ago

Since this topic is still under discussion, i want to propose to think about a workspace like structure to allow multiple projects to share one installation.

With the current proposal, the decoupling of a custom project and the default seed project looks like:

β”œβ”€β”€ appveyor.yml
β”œβ”€β”€ gulpfile.ts
β”œβ”€β”€ src
β”‚   └── client  <-- project base of the default seed project
β”‚       β”œβ”€β”€ dist
β”‚       β”œβ”€β”€ coverage
β”‚       β”œβ”€β”€ app
β”‚       β”œβ”€β”€ assets
β”‚       β”œβ”€β”€ css
β”‚       β”œβ”€β”€ index.html
β”‚       β”œβ”€β”€ test-main.js
β”‚       β”œβ”€β”€ tsconfig.json
β”‚       β”œβ”€β”€ karma.conf.js
β”‚       β”œβ”€β”€ package.json
β”‚       β”œβ”€β”€ protractor.conf.js
β”‚       └── typings.d.ts
β”‚   └── myproject  <-- project base of "myproject"
β”‚       β”œβ”€β”€ dist
β”‚       β”œβ”€β”€ coverage
β”‚       β”œβ”€β”€ app
β”‚       β”œβ”€β”€ assets
β”‚       β”œβ”€β”€ css
β”‚       β”œβ”€β”€ index.html
β”‚       β”œβ”€β”€ test-main.js
β”‚       β”œβ”€β”€ tsconfig.json
β”‚       β”œβ”€β”€ karma.conf.js
β”‚       β”œβ”€β”€ package.json
β”‚       β”œβ”€β”€ protractor.conf.js
β”‚       └── typings.d.ts
β”œβ”€β”€ tools
β”œβ”€β”€ tsconfig.json
β”œβ”€β”€ tslint.json
β”œβ”€β”€ typings
β”œβ”€β”€ package.json
└── typings.json

To use it: npm start -- --client myproject This makes updating the seed itself much easier while working on the custom project.

Now looking to the advanced seed project, with the change proposed / agreed to by NathanWalker, the purpose of that client directory is somehow different. It is no longer a project container on its own but a target within the same project. Think of src/ as the project base dir, where in the previous example client/ was the project base dir.

β”œβ”€β”€ appveyor.yml
β”œβ”€β”€ gulpfile.ts
β”œβ”€β”€ src <--  project base
β”‚   └── desktop  <-- project target within the same project - could be electron or something else.
β”‚   └── mobile <-- project target within the same project - could be nativescript, reactnative, or something else.
β”‚   └── server
β”‚   └── web
β”‚       β”œβ”€β”€ dist
β”‚       β”œβ”€β”€ coverage
β”‚       β”œβ”€β”€ app
β”‚       β”œβ”€β”€ assets
β”‚       β”œβ”€β”€ css
β”‚       β”œβ”€β”€ index.html
β”‚       β”œβ”€β”€ test-main.js
β”‚       β”œβ”€β”€ tsconfig.json
β”‚       β”œβ”€β”€ karma.conf.js
β”‚       β”œβ”€β”€ package.json
β”‚       β”œβ”€β”€ protractor.conf.js
β”‚       └── typings.d.ts
β”œβ”€β”€ tools
β”œβ”€β”€ tsconfig.json
β”œβ”€β”€ tslint.json
β”œβ”€β”€ typings
β”œβ”€β”€ package.json
└── typings.json

An integration of myproject would be difficult, it would be on the same level as the project targets for desktop, mobile etc.

So why not allowing both, an individuall project with its specific targets within one common workspace:

β”œβ”€β”€ appveyor.yml
β”œβ”€β”€ gulpfile.ts
β”œβ”€β”€ workspace <-- new 
β”‚   └── seed  <-- basedir of the seed project istelf - set as default (former client/ directory)
β”‚       └── desktop  <-- target within this project - could be electron or something else.
β”‚       └── mobile <-- target within this project - could be nativescript, reactnative, or something else.
β”‚       └── server
β”‚       └── web
β”‚           β”œβ”€β”€ dist
β”‚           β”œβ”€β”€ coverage
β”‚           β”œβ”€β”€ app
β”‚           β”œβ”€β”€ assets
β”‚           β”œβ”€β”€ css
β”‚           β”œβ”€β”€ index.html
β”‚           β”œβ”€β”€ test-main.js
β”‚           β”œβ”€β”€ tsconfig.json
β”‚           β”œβ”€β”€ karma.conf.js
β”‚           β”œβ”€β”€ package.json
β”‚           β”œβ”€β”€ protractor.conf.js
β”‚           └── typings.d.ts
β”‚   └── myproject <-- basedir of my project - refers to the project config like in tools/config/project.config.ts
β”‚       └── desktop  
β”‚       └── mobile 
β”‚       └── server
β”‚       └── web
β”‚           β”œβ”€β”€ dist
β”‚           β”œβ”€β”€ coverage
β”‚           β”œβ”€β”€ app
β”‚           β”œβ”€β”€ assets
β”‚           β”œβ”€β”€ css
β”‚           β”œβ”€β”€ index.html
β”‚           β”œβ”€β”€ test-main.js
β”‚           β”œβ”€β”€ tsconfig.json
β”‚           β”œβ”€β”€ karma.conf.js
β”‚           β”œβ”€β”€ package.json
β”‚           β”œβ”€β”€ protractor.conf.js
β”‚           └── typings.d.ts
β”œβ”€β”€ tools
β”œβ”€β”€ tsconfig.json
β”œβ”€β”€ tslint.json
β”œβ”€β”€ typings
β”œβ”€β”€ package.json
└── typings.json

Maybe this can be even extended to allow more than one custom project. (Granted, this would need more thoughts on how to setup the individuall project settings and the build process.)

DmitryEfimenko commented 8 years ago

What's the status of this? Is someone working on a PR? I'm about to start a new ng2 project and this is exactly what I was looking for... an ng2 seed project with structure that keeps server in mind. Another thing to think of... if there will be a server, the live reload would have to be configured to use it.

TheDonDope commented 8 years ago

Hi @DmitryEfimenko: About your:

with structure that keeps server in mind."

-> have a look here https://github.com/vyakymenko/angular2-seed-express (by @vyakymenko)

About the status of the issue: The issue is currently stale. There have been multiple PRs / different branches across other forks to work on it, but at some point got blocked. See #926 for further details.

DmitryEfimenko commented 8 years ago

that's a shame. Thanks for pointing out to the express seed. Though there is still a lot of work need to be done there to properly support server.

vyakymenko commented 8 years ago

@DmitryEfimenko , in progress :))

DmitryEfimenko commented 8 years ago

how do we get this issue going? I saw @TheDonDope 's branch. It does not look like it's too much work and I do believe that proper project structure is one of the most important things.

@TheDonDope, were you close to being done with it? If so I could quickly repeat changes made by you and submit a PR against latest code

TheDonDope commented 8 years ago

@DmitryEfimenko It is not as simple as one may think. First of all i urge you to take a few minutes and have a look at #959, especially the comment section starting at https://github.com/mgechev/angular2-seed/pull/959#issuecomment-226690850

The initial work that was done was only the tip of the iceberg, if you read through the comments you will see that there is a lot to be done ahead, and there already was a lot of time invested into this. So there will be no "quick finish" for this.

Basically, one should take a look at the current status and come up with a detailed concept of things to be done still. Because the complexity is high enough, that one cannot simply start working on without beforehand analysis.

Sorry, i don't want to be a downer here, just trying to manage expectations!

Alas, if you still are on fire and want to work on this, after reading all the beforehand stuff, i wholeheartedly welcome you to open a new issue to get things started again, maybe starting to work on the analysis part.

Cheerio

Dope

e-oz commented 8 years ago

in case we want to develop backend for the current application, which reuses some of the logic which is already defined by services in the client-side, we need to:

Move this code to reusable library and forget about multiple apps inside one repo, it's insanity.

e-oz commented 8 years ago

Not sure why 'client' folder exist, if it's the only folder in src. Just extra naming.

mgechev commented 8 years ago

Yeah, at this point I agree that it might be a better idea to drop the client directory.

DmitryEfimenko commented 8 years ago

Disagree completely. There are almost no projects out there that do not have server. As @TheDonDope pointed out, angular2-seed-express is a great example of creating a project that has both server and client sides. I understand that this particular seed currently has only angular in the source code, but it might be beneficial to actually create a simple node server as a starting point. It would be easy enough to enchant/ delete or replace it with something else.

e-oz commented 8 years ago

It's weird to think all projects use nodejs as a server.

e-oz commented 8 years ago

And server is a completely different app with completely different dependencies. It's really weird way to reuse code by pushing everything into one huge mess - usually for code reuse people do exactly opposite - split code to reusable parts and move them out as libraries/modules/etc.

vyakymenko commented 8 years ago

@e-oz , okay, in the production build client-side app will be built to dist/prod folder, so what is the problem with client folder? What if you will use Python, Java, .NET, that will look for client folder changes, docker for deploy with precompile and you want to operate with dual ts compilation for many apps or parts.CLI(any that you like) for watcher testings for specific folders.Daemon that will watch to some directories that you want aka PM2, and you can easily use ESBas pattern for extra-large applications, you can without any problems add another folder for another app, with one compiler and precompiler(AOT) ?

e-oz commented 8 years ago

@vyakymenko , maybe because 'dist' should be cleaned before build. Or maybe because you can configure target (output) dir for build in gulpfile, without adding any additional folders to source.

vyakymenko commented 8 years ago

@e-oz , it's always cleaned:

gulpfile.ts

// --------------
// Build prod.
gulp.task('build.prod', (done: any) =>
  runSequence('clean.prod', // <----- @e-oz, clean folder
              'tslint',
              'css-lint',
              'build.assets.prod',
              'build.html_css',
              'copy.client.js.prod',
              'copy.server.js.prod',
              'build.js.prod',
              'build.bundles',
              'build.bundles.app',
              'build.index.prod',
              'build.server.prod',
              'copy.server.assets',
              done));

seed.config.ts and project.config.ts

/**
   * The directory where the client files are located.
   * The default directory is `client`.
   * @type {string}
   */
  APP_CLIENT = argv['client'] || 'whiskas';

// @e-oz, or add you own
e-oz commented 8 years ago

@vyakymenko that's what I'm talking about. If dist will contain other folders, from other projects, they will be removed also.

vyakymenko commented 8 years ago

@e-oz , if you will configure your own task with another folder structure in project.config.ts or seed.config.ts everything will be okay. Look for example with angular2-seed-express or adnvanced-angular2-seed. You can configure you folders copy, and cleaning. It depends on your specific technical issue, project structure/architecture.

And keep in mind, that all new/newbie developers will search that client source much longer. Remember about one of 7 important development paradigm KISS.

e-oz commented 8 years ago

@vyakymenko in tools/config/seed.config.ts you can change DIST_DIR = 'dist'; or PROD_DEST to any exotic path for any exotic watcher. I think it's better than force everybody else to have client folder just because of exotic watchers.

And keep in mind, that all new/newbie developers will search that client source much longer.

Not sure what you are talking about. New developers are writing client-side app, so everything in src is client by default. Making them think "there should be something else besides client" will not make their life easier.

vyakymenko commented 8 years ago

@e-oz , If you try to learn gulp, you need to learn Node.js a little bit? Dual-app, client for users and admin for admins, with different bootstraps but one angular2-seed builder?

New developers are writing client-side app, so everything in src is client by default

And injections, shims etc ?

P.S. Don't want to start a holy war.

e-oz commented 8 years ago

Not sure want you want to prove. You want to add knowledge of nodejs (and ability to write dual-app code) as a requirement to use this seed? It's against that KISS principle. If not say more.

I think I not only argumented my opinion but also found simple workaround for you, so I don't think I can add something to this talk.

tarlepp commented 8 years ago

@DmitryEfimenko you really want to add server side? If yes seed should have every server side options to satisfy everyone (C#, Python, Java, PHP, node, etc.). I don't really see point to take that path.

vyakymenko commented 8 years ago

@e-oz , I want to say, that we have client folder with one Angular2 application. And if you will want, you can feel free just to add another application to the src folder and start to work with another application based on this seed. Because my logic is that this is a seed, when we use water seed grows to tree with one or more applications. Does that make sense?

e-oz commented 8 years ago

@vyakymenko yes, but different apps have different dependencies, and you have one package.json. Every version change will be nightmare. Having different apps in one repo is a very bad idea.

tarlepp commented 8 years ago

And what if water app support is gone but tree still grows? Are you really going to make water app all those necessary changes? Just asking who is going to pay that "extra" work?

vyakymenko commented 8 years ago

@tarlepp , tree will die without water it's an axiom, doesn't matter what tree. Good example for "extra" work, any retailer-manufacture app that can use dual-apps.

vyakymenko commented 8 years ago

@e-oz , I agree with you. But for sometimes, it's a must.

P.S. I never use dual-apps, but I think that it can be.

tarlepp commented 8 years ago

@vyakymenko "extra" work is eg. when seed updates to newer angular which will broke something. And this goes when there is water, tree1 and tree2 and eg. tree1 project dies on your hand.