eugeneware / debowerify

A browserify transform to enable the easy use of bower components in browserify client javascript projects. This can be used in conjunction with deamdify to require AMD components from bower as well.
493 stars 51 forks source link

Dependencies of installed packages? #45

Open LeonB opened 9 years ago

LeonB commented 9 years ago

Hi,

I've got a question about how debowerify works with dependencies. I'm struggling with that issue and maybe I'm just misunderstanding it.

I have a application.js which contains one thing: require('magnific-popup'). I've installed magnific-popup via bower and it has one dependency: jQuery.

When I browserify the file (browserify -t debowerify app/assets/javascripts/application.js > public/js/application.js) the resulting file doesn't contain the jQuery dependency. Am I doing something wrong or is this how debowerify is supposed to work?

pllee commented 9 years ago

I have the same problem/question. Does this have to be enabled ? Is there a way to ignore dependencies by name? For example a jquery plugin that requires another plugin but ignores jquery if passed in as an argument or whatever.

bobthecow commented 9 years ago

Browserify and Debowerify aren't magic... if a jQuery plugin isn't written to require jQuery properly — and most of them aren't — it won't be bundled automatically. I usually end up with a file in my project that looks something like this:

var $ = require('jquery');

// most jQuery plugins don't work unless jQuery is on the window as well :-/
window.$ = window.jQuery = $;

require('some-jquery-plugin');
require('another-jquery-plugin');
// ...
pllee commented 9 years ago

magic ... It doesn't load the dependencies defined in the plugins bower.json file. What is the point of using a bower component if it doesn't define its dependencies properly. Also no offense to the writer of this but what is the point of Debowerify if it doesn't follow the dependency tree?

sukima commented 9 years ago

@pllee And you hit the bower nail on the head. That has always been the problem with bower and why many browserify fans prefer npm modules over bower components. Until the front end community moves on we will always have to deal with these issues.

I found many times with bower components that I would use debowerify or browserify-shim or some combination together.

pllee commented 9 years ago

@sukima I prefer broswserify but there are cases where the bower way makes sense. Such as excluding a jquery file that the whole page uses but the component also relies on or including a component that only works with bower. My current "problem" now is that I have a "main.js" for each page that just requires whatever components it needs and they all get built into one file with browserify. Unfortunately a jquery plugin that I am extending manages its dependencies with bower (which I think is pretty common) but in order for me to make my component requireable/work I need to require 2 js files and some css. Instead of cherry picking the dependencies I thought a tool could be used to automate the process by using bower's api. I found this tool that I thought would fit my needs but it looks as if it doesn't manage dependencies or give a way to get required css info, also I would prefer to have the ability for non minified source.

sukima commented 9 years ago

@pllee When this happened to me I use bower to install the dependencies and then used browserify-shim instead of debowerify and manually declared the components dependencies.

pllee commented 9 years ago

@sukima Thanks for all the help, that looks like a useful tool. Just to confirm debowerify isn't meant for dependency/css management right ? How tedious it to maintain your suggested way with browserify-shim? One of the great strengths of browserify is that there is no external logic for dependency management and very simple build process.

Would you use a tool that took a bower component and made it into requirable/browerifiable js code ?

bobthecow commented 9 years ago

debowerify is only meant to expose bower packages to browserify. but bower packages are all over the map. if the packages are commonjs-friendly, they'll build properly with browserify+debowerify. if they're not, you'll need to use a shim. if you don't want to use a shim, take it up with the bower package maintainer :)

pllee commented 9 years ago

@bobthecow Thanks for the input, I wasn't clear on the if the packages are commonjs friendly part. That might be helpful to note that in the readme, if it is already there I must have missed it. Since most bower components are not commonjs friendly I might write a tool that can try to package them to be requirable and built with browserifiy.

sukima commented 9 years ago

@pllee Why write a tool that's exactly what browserify-shim is designed to do.

bobthecow commented 9 years ago

Why write a tool that's exactly what browserify-shim is designed to do.

:+1:

pllee commented 9 years ago

@sukima @bobthecow

I figured I would be sick of writing browserifiy-shim config files that just mimic that the dependencies defined by bower file. It seems like the great tool but doesn't really automate the process. I still don't know if it is worth the effort for my use case because there are tools out there and it really isn't a big problem for me. Having info about css meta would be nice to I was thinking about doing something like :

bowerifiy jquery.businessHours -jquery > businessHours.js

That file would include it's deps without jquery so basically be:

require(./'bower_components/jt.timepicker')
require('./bower_components/jquery.businessHours')
module.exports = {
    css: .. css info;
}

I would be able to use that file in my code that will be browserifed

var businessHours = require('./businessHours')
loadCss(businessHours.css);

https://github.com/gEndelf/jquery.businessHours

sukima commented 9 years ago

In my cases where I also wanted CSS and stuff I used the CSS processor lib to pull it in. Like Less or Sass include statements and left the JS separate. Sounds like you have more unique requirements.

Maybe your setup could glean some light on how to import CSS from JS and a way to parse the bower.json file better. If so please contribute back; sounds like it would be a valuable feature for debowerify.

maxnordlund commented 9 years ago

This seams a lot like cssify, perhaps this could be solved using a combination of debowerify and cssify? Just throwing ideas out there.

pllee commented 9 years ago

@maxnordlund @sukima cssify looks nice but I am weary about including css strings in js. I am not really sure how relative images would work and the processing of js strings to css is much more overhead than natively parsed and cached css. But my weariness is irrelevant.

Besides that all I what was looking to do would be to add some "meta" to the bundle which adds css info that could be used by external tools such as cssify or loaded with a css loader etc. It would just basically parse the bower.json's main for css files and add them to the meta. It might look something like:

{
 filePaths: ['./bower_components/dep1/file.css', './bower_components/dep2/file.css'],
 relativeUrls: ['bower_components/dep2/file.css', 'bower_components/dep2/file.css']
}
eggyal commented 9 years ago

I've just started using browserify and must admit to being rather surprised (and confused) by this discussion. I had assumed (just as @LeonB and @pllee appear to have done) that, upon encountering a commonjs-unfriendly component, debowerify would automatically require the dependencies listed in its .bower.json—it appears, from what @bobthecow @sukima and @maxnordlund are saying, that it does not?

If I've understood correctly, then browserify-shim will not do this automatically either?

Presumably these tools do not adopt such an approach because it wouldn't work? Would someone be able to elaborate on that for me? I'm rather puzzled at present.

FWIW: I'm reluctant to switch to npm for front-end package management because of its nested approach to dependency management, which (again, if I've understood correctly) could result in libraries being included multiple times... at least with bower I can manage version conflicts in such a way as to end up including only a single copy of each. I don't want to be serving up three versions of jQuery with every page!

fza commented 9 years ago

This is a bit offtopic, I'm sorry. ;)

@eggyal

I'm reluctant to switch to npm for front-end package management because of its nested approach to dependency management, which (again, if I've understood correctly) could result in libraries being included multiple times...

That's only true when the same package is referenced multiple times with a non-combinable version constraint. For example, when a package is referenced by 1.1.x and another time by ~1.1.0 (patch level constraint in this example), a fresh npm install will place only one copy of that package at the top level of the node_modules directory (or as top most as necessary, I'm not sure about the exact placement behavior). At least the package will only be present once. Thus, browserify will only find this one copy and will therefore not include the package twice in the bundle.

But you are right in terms that e.g. the combination of 1.2.x and ~1.1.0 should cause the "same" package being included twice, but in different versions. That's on purpose as e.g. the API could have changed. That's what all this semantic versioning is all about and it's actually a good thing—in a perfect world at least, where all packages have well defined (dependency) versions. (see also semver)

You can test it with a package.json like this:

{
  "name": "test",
  "version": "0.1.0",
  "dependencies": {
    "httppp": "~0.2.1", // references readable-stream 1.0.2
    "readable-stream": "~1.0.0" // yields only one ~1.0.0 in the node_modules directory
                                // try with "1.1.0" and you get two copies
  }
}