Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Questions #1

Closed
Shepless opened this issue Mar 9, 2015 · 21 comments
Closed

Questions #1

Shepless opened this issue Mar 9, 2015 · 21 comments
Labels

Comments

@Shepless
Copy link

Shepless commented Mar 9, 2015

@lookfirst First off, thanks for taking the time and effort to produce such a comprehensive example! I am looking at using JSPM and SystemJS to build a library of separate and re-usable modules. These SystemJS modules will export angular services/controllers/directives along with templates and CSS or LESS.

My main concerns are how I would expose the JS, LESS or CSS (or which I would expose?) and pre-compiled HTML templates for a consuming project in one go and also how the consuming project would be able to handle loading these in a development/production environment.

As an example lets say I have ModuleA and ModuleB as separate SystemJS modules and each contain an angular directive, a corresponding HTML template and LESS styling. If I am building MyProject that has dependencies on these two modules how would it build all of the styling and pre-compile the templates in a dev and production environment? Ideally I would like people to be able to build the dependencies in isolation (e.g. "vendors.min.js" and "vendors.min.css") and build their own "my-project.min.js" files that depend on it. I've seen examples of people using the SystemJS builder in a gulp build system but not to load in ModuleA and ModuleB LESS files to compile and concat. They only seem to build individual files that are isolated to their SystemJS modules.

I hope that makes sense and that you might have suggestions as you are clearly far more versed in JSPM and SystemJS than I. I am still in the early learning phase of these two technologies.

Any help/advice is greatly appreciated.

@lookfirst
Copy link
Owner

Thanks @Shepless for the compliments. 😄

I think what I hear you saying is that you'd like to provide 3rd party modules (aka: components) for people to use in their own projects.

What I would do is package them up so that they look like an npm module, which is to say that everything that is needed is contained in a single folder and then publish that somehow (I say somehow in that I don't know if you want these modules to be public or not).

I have a slight example of what I think you're talking about in the todo example. Specifically, I'm depending on the third party TodoMVC css files. SystemJS just allows those to be imported as modules. In this case, it is just CSS, but it could be anything else you'd like, including angular modules or Less/Sass.

There is also a really neat 'hack' in systemjs-seed in that there is a routing.js module which combines SystemJS with ui-router futurestates and ocLazyLoad. This enables the app to dynamically load things at runtime based on route.

Let me know if you'd like more examples or clarification.

@Shepless
Copy link
Author

Shepless commented Mar 9, 2015

@lookfirst No problem, I really appreciate you getting back so quickly!

You're exactly right about the approach. I would probably be looking to publish them to github so people can install via jspm install github:foo.

The todo example is close to what I am looking for, but I'm not sure if its exactly the same - Rather than have the CSS in a separate module I would want to publish all assets together, for example ModuleA:

build-output
+-- directives
| +-- directive-a.js
| +-- directive-b.js
+-- less
| +-- directive-a.less
| +-- directive-b.less
+-- templates
| +-- directive-a.js
| +-- directive-b.js

So if I were a consumer of this as dependency it would be nice if I could do something like (for the LESS compilation):

gulp.task('build', function () {
   return gulp.src('./jspm_packages/modules/**/*.less')
   // ...
});

Not sure if that is possible or even the best approach? Would you always recommend pre-compiling the LESS to CSS for the build output of a module? On top of this I'm not sure how the pre-compilation of templates fits into the picture in terms of imports, since in dev mode they would probably stay as .html files but in production they would be .js files and I would imagine SystemJS would no longer find the module.

Apologies for the all the questions!

@lookfirst
Copy link
Owner

No worries, questions are good. 👍

  1. You can use my seed project as your basis for each of your components, so no need to even write gulpfiles (or if you do, make sure to take advantage of gulp-helpers to DRY your gulpfile. The idea would be that you'd take the output located in the dist folder as the 'main' section in the package.json for your module.
  2. There is no reason to separate stuff out into folders like that. Especially if you are building a component. I'd structure things so that everything is component based like this:
build-output
+-- component
|+-- directive-a.js
|+-- directive-b.js
|+-- a.html
|+-- b.html
|+-- a.css
|+-- b.css

So, for example, let's say that directive-a.js depends on a template and some css. You'd structure it just like I've done with the todo example where I've declared the template and css dependencies directly in the todo.js file.

When you import this module into another project, all that project has to do is depend on the import path, which is all setup automatically in the system.config.js.

I'm currently working on a yeoman generator that outputs the same gulpfile as this project already has. That way, you can create re-usable module projects more easily. If this still isn't clear, I'll build an example of what I'm talking about soon.

@lookfirst
Copy link
Owner

Play with this seed project a bit and try to get a feeling for how all the bits fit together. I think it will help lift the fog of how everything fits together a bit. It took me a while myself, but hopefully this project makes it more clear.

@Shepless
Copy link
Author

Shepless commented Mar 9, 2015

Excellent, I play around some more. The example would be fantastic if you get the opportunity. When I've (hopefully!) made some progress I'll let you know so you can pick it apart haha! Thanks again for all your help - I really appreciate it!

@Shepless
Copy link
Author

Shepless commented Mar 9, 2015

I've been looking through the project and I have noticed that you aren't using the SystemJS Builder module to build your scripts. I would have thought that this would be needed?

@lookfirst
Copy link
Owner

It is used, but only for 'production' mode and it is used through this project: https://github.com/Swimlane/systemjs-route-bundler

@Shepless
Copy link
Author

Shepless commented Mar 9, 2015

Ah ha! Thanks again 😄

@lookfirst
Copy link
Owner

Ok, yeoman generator is done for now. Can you give me an example self-contained component that you'd like to build? I'll fit it into my stuff and show you what can be done.

@Shepless
Copy link
Author

Shepless commented Mar 9, 2015

@lookfirst that was fast! I have a WIP test module that I'm working on here

I know you said that the nested directory structure wasn't required, but if I'm being honest I like the structure so I kept it 😄

This is by no means the finished article but gives you a good idea of what I'm trying to achieve. I think it's almost there, the only stumbling block is if I use the jspm cli to bundle-sfx it fails, still looking into why. Let me know what you think.

@lookfirst
Copy link
Owner

Ok, I've 'rewritten' your code to fit under my semi-opinionated way of doing things.

https://github.com/lookfirst/module-a

What I did was:

  1. git clone your module-a && cd module-a
  2. yo systemjs (see https://github.com/lookfirst/generator-systemjs) and overwrote most of your stuff
  3. Hacked and slashed and moved stuff around a bit, but not too much
  4. gulp run
  5. http://localhost:9000

Things to note:

  1. I didn't have to edit the gulpfile or any other config stuff at all. It just works.
  2. You'll note that I added a module.js, you won't need that if you are building a component that isn't used elsewhere. It is really just so that it shows up in the browser for now. It is basically the code someone else would add to their project in order to use yours.
  3. I didn't bother with tests, but those would be super easy to add. Let me know if you need me to write one out.
  4. Take advantage of ngAnnotate, it is your friend over $inject.
  5. Take advantage of my version of gulp-ng-html2js which exports the module so you can just say 'directiveOneTpl.name' in the module declarations.
  6. browserSync is enabled, so if you're developing this, it auto reloads in the browser. weee!

@Shepless
Copy link
Author

Apologies for the delay - I've just got in from work so will take a look at this tonight. Thanks for all the effort.

@Shepless
Copy link
Author

Immediate thoughts are:

  • Not too sure about the absolute paths to modules, could they potentially clash with other modules? Or does SystemJS/JSPM handle this out of the box? Also will absolute paths be needed in order for unit tests to work correctly?
  • Also not sure about the module per entity, I get that each file is essentially a module in ES6 terms but in Angular it feels a bit overkill. Thats why in my original module I tried to keep everything in two modules - module-a and module-a-templates (I'm even going to try and lose the templates module too)
  • I really like the gulp tasks repo - very, very useful! I'm guessing you've used this in a few projects? Have you found that it potentially limits and you've had to work around it or has it been plain sailing?
  • I also really like the future states and lazy loading (as a module consumer)

I'll keep playing around, but thanks again!

@lookfirst
Copy link
Owner

  • They aren't really absolute paths, they are relative to the system.config.js baseURL. You can still use ../ paths too, but I took that out cause Intellij isn't real smart about it yet and marks them as red.
  • Shrug. Not sure what the issue here is. Modules are great. In order to use the future states and lazy loading, things have to be modules, I was getting errors otherwise.
  • This is the first time I've used it. I built it while building this project and now I've copied it into three other projects. But, I've been doing build systems for a very long time now (20 years) and I've got a lot of experience with what works and what doesn't. It has been plain sailing.

@Shepless
Copy link
Author

Awesome stuff. The second point is a personal preference but it also has practical thought behind it, which is that angular modules aren't the best and can be easily overwritten by other modules so minimising them reduces the chances of clashes.

@lookfirst
Copy link
Owner

always namespace your modules. you can use module.id for that.

so, it becomes:

angular.module(module.id, [])

which resolves at runtime to the name of the file.

app/module/directives/directive-one

@brianfeister
Copy link

Great work @lookfirst !

I'll piggyback on here for now, where are your watcher tasks located now? In my fork of the original project, I broke out separate subroutines and watchers for LESS vs other assets in watch / compile because the LESS file changes were triggering full-page refresh, which for me defeats the purpose of browserSync.

Also, when I cloned this project just now and added a test.less file in /src/app/todo, the build is not picking it up. This is the one potential problem of burying all of the internals of the gulp in a separate module. I think that's the only change you introduced which I feel uneasy about. It's like middleware that depends on 10 other middleware at the same time, which makes me worry it will get out of date.

@lookfirst
Copy link
Owner

When I have 20 projects, I'd much rather have a single place for all those tasks rather than having to fix 20 projects when one of those tasks goes wrong.

In fact, this is a perfect example, you found a bug! Now I update my gulp-helpers and every project down the chain gets the fix without having to modify their gulpfile at all. npm update your project and problem is solved. If you can think of a better solution, I'm all ears. 😸

With regards to dependencies getting out of date, I'm ok with that cause I'm just more concerned with repeatable builds. You'll know right away from your CI system if something breaks. If you want to contribute, I'll give you commit access and I have years worth of responding to PR's in a timely fashion across many projects. You can also always fork the project and use the fork instead. I ❤️ github.

This is the less task:

https://github.com/lookfirst/gulp-helpers/blob/master/src/tasks/less.js

Interesting, it was actually a bug that I picked up from the parent project:

https://github.com/Swimlane/angular-systemjs-seed/blob/master/gulpfile.js#L107

changed() extension looks at the dest extension, not the src extension.

https://github.com/sindresorhus/gulp-changed#extension

I just pushed v1.2.3 to npm. Enjoy. 😄

lookfirst added a commit to lookfirst/angular-systemjs-seed that referenced this issue Mar 11, 2015
So, the interesting thing is that this started from this discussion: lookfirst/systemjs-seed#1 (comment)

I suggest that you adopt [gulp-helpers](https://github.com/lookfirst/gulp-helpers). It was based off this gulpfile and would really help clean up a lot of your code.
@Shepless
Copy link
Author

I tend to agree with @lookfirst on this one. On the subject of dependencies - surely this approach is better as it allows you to manage to them in one place? Meaning that you can't get any kind of version mis-matches between projects (especially important if they interact in some way), it gives you far more control over management I think. I will definitely be using either the repo already available or look into building my own.

@lookfirst
Copy link
Owner

If you build your own, let me know! I know that gulp-helpers is just one way of doing it. I'm always interested in seeing other ideas. 😄

@lookfirst
Copy link
Owner

I'm going to close this as I think the discussion has ended. =) If you have further questions, feel free to open new issues!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants