Skip to content
This repository has been archived by the owner on Jul 26, 2022. It is now read-only.

How to make elements reusable through Bower #11

Closed
zenorocha opened this issue Mar 20, 2014 · 29 comments
Closed

How to make elements reusable through Bower #11

zenorocha opened this issue Mar 20, 2014 · 29 comments

Comments

@zenorocha
Copy link
Member

When we stopped to use the CDN and started to use Bower we had this default bower_components folder commited (which is now called lib).

We made this decision because we want people to be able to demonstrate their elements right from the gh-pages and debug them easily.

However this causes reusability problems. They cannot be shared with Bower and used by other apps.

@robdodson
Copy link
Contributor

This is something we've been discussing a lot internally and I still don't think there is a great solution.

If an element is going to be registered and shared with bower, then it must assume all dependencies will be siblings. So what my-element is doing here is actually incorrect. The correct path to polymer.html would be:

<link rel="import" href="../polymer/polymer.html">

Because if I run bower install my-element I'm going to get:

lib/
  polymer/
    polymer.html
  my-element/
    my-element.html

This means an element boilerplate needs to have two branches:
In the master branch, the element is written to always depend on its siblings. example from mark-down's master branch

In the gh-pages branch, you can have a bower_components folder (or libs folder) and import your element from that into an index.html to test. That's what I do in mark-down's gh-pages branch.

This is an annoying way to work but it's the only way that your element will be installable by bower. Take a look at the Polymer elements, they all follow this same technique.

There is another wrinkle to think about...

If someone does hardcode a path into their import:

<link rel="import" href="../other-stuff/polymer/polymer.html">

Then you'll have to create a folder in your project called other-stuff and put an html import in there which just contains another import to where you've actually stored polymer.html. Sorry if that was confusing to read (it's confusing to think about!) but the long and short of it is that you can't ever put a dirname into your element's imports. They will all have to be ../polymer/polymer.html in order to satisfy bower. I think that means, if you use git to install an element instead of bower, you'll have to put it in your bower components folder, and that feels weird. We're trying to see if we can evolve bower to make this not so weird.

@zenorocha
Copy link
Member Author

Today @robdodson and I tried to put together some solution to fix this.

You can check the full prototypes here:

The basic idea is:

  1. Set .bowerrc to:

    {
        "directory": "./"
    }
  2. Git ignore polymer and platform on master branch, but commit them on gh-pages branch

  3. Move the demo from root to src/

That way you can still develop on master branch and also have a live demo on gh-pages: http://zenorocha.github.io/x-test/src/demo.html

The only thing we need to automate in order to make it easier for people to publish live demos is the .gitignore removal on gh-pages branch: https://github.com/zenorocha/x-test/commit/d56c93b2e7b385c743233b57a9b9841564418bd8. Suggestions?

@addyosmani
Copy link
Member

cc @wibblymat for his take on this approach, but it looks legit.

@robdodson
Copy link
Contributor

@wibblymat pointed out that once you install the element it no longer works because it's in package_name/src but it's looking for ../polymer.

Sounds like we might need a build task instead...

@sindresorhus
Copy link

You also shouldn't change the name of the folder as it should be clear it's the folder Bower uses to store components.

@zenorocha
Copy link
Member Author

No idea how to solve this one 😔

I wanted to avoid build steps, but I don't think it's possible...

@zenorocha zenorocha added bug and removed enhancement labels Mar 27, 2014
@robdodson
Copy link
Contributor

Because everyone must assume their element will be installed by bower, we have to use the "canonical path" (../package_name/package.html) for dependencies. This means you're either developing your element inside of your bower_components dir or you need a build step that strips out any paths to bower_components and turns them into canonical paths.

Another alternative is for bower to be cool with git repos and other things being dumped into the bower_components dir. At that point you wouldn't want to call it bower_components anymore, you'd want something more generic, like the original components (yes I know why we changed it) or, as Zeno is doing, lib. I realize this makes people freak out and I understand the importance of indicating that the stuff in the folder is managed by bower. It's a total can of worms but it's something we might consider. The alternative is to tie bower usage for Web Components to a build system like grunt, gulp, etc.

or, we move the build step to bower itself. Maybe have a comment string that bower can look for in our main html import file and it can swap the paths

<!-- on-bower-install -->
<!-- ../package_name/package.html -->
<link rel="import" href="bower_components/package_name/package.html>

(I realize this is stinky, just throwing out ideas)

@zenorocha
Copy link
Member Author

I feel sad about having all those dependencies.

Instead of focusing on the element authoring itself, a beginner first needs to install NodeJS, install Grunt and Bower globally, then install local dependencies to fetch Polymer/Platform, then run some Grunt command to handle those paths.

For us who run those commands everyday it's not a problem. And I'm not saying that those tools are bad either. They are incredibly useful and important to distribute your element for example. But they are blockers for lots of developers who just wants to open their editors, edit two HTML files, and see the magic happen.

Unfortunately using a CDN isn't an option for bunch of reasons:

  • The CDN does not host polymer.html which removes the ability for elements to import it.
  • There are many elements which are not hosted on the CDN so it might be tricky to include all of * them in your project.
  • You will not be able to Vulcanize your code.

That's why we end up having no alternative but use Bower + Grunt/Gulp. So let me focus in a solution.

I don't think Bower will make such changes [soon], and every single day there are people using this boilerplate to create stuff. They are building their projects on top of something that is not distributable at this current state.

I'm not familiar with this grunt-targethtml but it seems like it can be a solution.

@zenorocha
Copy link
Member Author

Just changed the issue title since this discussion is more about how to make elements reusable through bower then how to name bower's custom install folder.

@zenorocha zenorocha changed the title Use a custom install location for Bower How to reuse elements through Bower Mar 27, 2014
@sjmiles
Copy link

sjmiles commented Mar 27, 2014

Polymer engineering perspective:

  • We define a component as a shareable thing. This may (or may not) contain one or more elements. Canonical path and the concept of a components folder are both enablers for sharing.
  • The notion that the flat dependency list has anything to do with Bower is a misunderstanding. Flat dependency list exists to enable the canonical path, which is a Good Thing, not some constraint.
  • The notion that your components folder must only contain components from a specific source, e.g. Bower, is a non-starter. In my recent discussion with Mat Scales, my understanding was that he is completely on board with this notion. We say that your components folder should be able to contain components from any source (zip files, GIT checkouts, Bower, other).

Rob you said

This means an element boilerplate needs to have two branches:

But I can't understand what you refer to and I can't figure it out from the repos you pointed to. Can you be more explicit? No polymer material or elements ever need to twiddle paths, this is the point, it all Just Works (tm).

@zenorocha zenorocha changed the title How to reuse elements through Bower How to make elements reusable through Bower Mar 27, 2014
@zenorocha
Copy link
Member Author

What we want to achieve @sjmiles is having a single gh-pages branch that can serve element(s) through Bower and also contain a HTML file that imports those element(s) for demo purposes.

@sjmiles
Copy link

sjmiles commented Mar 27, 2014

I suggest you do not try to achieve that, and accept that the shape of a shareable package is not the same as the shape of a deployment.

What we did is automate constructing a [gh-pages] branch from the [master] branch of my component. A simple shell script does the following:

  1. creates a gh-pages branch of the component repository
  2. clears it out
  3. does a bower install into the naked folder to download the component and it's dependencies
  4. push

Which results in a fully functional deployment of my components in 30 seconds or less. :)

Note that Step 3 is exactly the easiest way a user can do this too.

There are virtues to no trying to make one repository serve all masters. Here is just one: a clean component repo can be installed by downloading or cloning via GIT without relying on Bower ignore.

@robdodson
Copy link
Contributor

@sjmiles I'm curious, how do you develop using this workflow. Do you work in master, make changes, run the script, and preview the gh-pages branch?

@zenorocha
Copy link
Member Author

Exactly, by using this workflow you would need to create a git tag for every single change you make.

@sjmiles
Copy link

sjmiles commented Mar 27, 2014

Locally my component sits in a component folder with all it's other dependencies just sitting there. So my demo files, tests, whatever are totally runnable in place. I can run/edit/test in a tight loop. My working folder is a GIT checkout (this is one reason it's best to be able to have hetergeneous components folder) that I can commit to, pull or push from whenever I want. This GIT image maintains a production footprint (as close as possible to only the stuff a user needs to use your component at runtime).

The only time you have to update the gh-pages branch is when you want to deploy a live version of your component demo page. I usually do this via bower update. You could run the script again, but this assumes your gh-pages has only the content in your original component.

Again, in my view, any live page about your component is fundamentally different from your shareable component. It's not hard to imagine a gh-pages deployment for a large component that contains a significant amount of other material, including tutorials, sample applications, and so on.

@robdodson
Copy link
Contributor

Locally my component sits in a component folder with all it's other dependencies just sitting there.

Does that look like this:

~/sjmiles/components/
  x-foo/
  x-bar/  <-- the element you're working on
  x-baz/

Or is it more like this:

~/sjmiles/projects/
  some-project/
    components/
      x-foo/
      x-bar/  <-- the element you're working on
      x-baz/

Or something else entirely? 😄

@sjmiles
Copy link

sjmiles commented Mar 27, 2014

Both cases are [path]/components, and that's all that really matters. The rest is salt to taste.

But since you asked, I have multiple setups.

I have one uber setup with a zillion components in multiple folders that I make look like one folder to the client using apache redirects. Because members of Polymer team often need to push to like ... every repository (somebody counted around 180 at some point) we have more advanced needs here. Most users will not be pushing changes to all the components they use (including numerous polyfills, etc).

But, whenever I feel like it, I can spawn a new project folder as in your second example. It's really easy with Bower to populate the components folder, so I have various sub-projects that use this model. I choose this model when I want a simpler workspace.

Btw, the multiple folders thing is not awesome, and I only do that because last time I checked bower update would clobber some of my git checkouts. Mat told me this should have been fixed, I have an action item to verify.

@robdodson
Copy link
Contributor

so the simple workflow, if you're using bower, is to develop inside of the bower_components dir, which you rename to components using .bowerrc. did I get that right?

@sjmiles
Copy link

sjmiles commented Mar 27, 2014

You gotta disconnect from Bower. Bower is a convenience, but it doesn't drive any of this.

The intent of components is to have high granularity and reuse. This is what drives having a components folder. How anything gets into that folder is an orthogonal question.

I call my components folder components, because of KISS. Then I put stuff in there. Maybe I use zip files exclusively. Maybe I use git checkouts and some zip files. Maybe I use curl. Frequently, I copy of bunch of components in there from some other place on my system, or create a brand new folder and write some fresh code.

Now, I can also use Bower to bring in packages, which will be damn convenient because it will also bring in dependencies.

Bower has to know where to install my components. The default folder is not to my liking, but thankfully, Bower is not cranky like NPM and allows me to control this name. I choose the name components, which I usually do with .bowerrc. You could use the name squid on your system, and everything would remain groovy; your components would still play with my components (none of them reference this name).

The key concept is that the use of Bower is for convenience, it's not driving the bus.

@sjmiles
Copy link

sjmiles commented Mar 27, 2014

I probably should have just said yes, sorry for long-windedness.

I got stuck because of "if you're using bower", and the answer would be yes even if I wasn't.

@robdodson
Copy link
Contributor

I totally get what you're saying about Bower being a convenience, we've just always told people to not put their things in whatever folder bower is installing to and that's why I focus on it. We've specifically said, that folder is sacred, do not touch.

From the bower readme:

All package contents are installed in the bower_components directory by default. You should never directly modify the contents of this directory.

If the boilerplate goes this route, it requires reeducation which will meet with confusion and possibly resistance. Something akin to telling Node developers "You can put your stuff in the node_modules folder now." It's that confusion that I'm concerned about, not whether or not it's conceptually ok to do it. I concede that you can probably put whatever you want in bower_components and (with the possible exception of bower update) it won't break anything. But I think we'll be swimming against the current if we try to sell that idea.

FWIW, I'm not trying to stir things up. Just looking for the simplest solution for new developers

@wibblymat wdyt?

@sjmiles
Copy link

sjmiles commented Mar 27, 2014

I hear you, but in my view, the long term good solution trumps concerns
about current expectations.

Btw, regarding that bit in the readme, this was the very first thing
Polymer team objected to when we started using Bower. We were clear that we
require homogeneous component folder.

we'll be swimming against the current if we try to sell that idea.

Sell to whom? As I've said, my understanding from our last Bower-asks
meeting was that there is now general agreement on this question.

Is there any real virtue to having a restricted folder? As far as I can
tell, we are just making things a lot easier on component developers.

On Wed, Mar 26, 2014 at 11:11 PM, Rob Dodson notifications@github.comwrote:

I totally get what you're saying about Bower being a convenience, we've
just always told people to not put their things in whatever folder
bower is installing to and that's why I focus on it. We've specifically
said, that folder is sacred, do not touch.

From the bower readmehttps://github.com/bower/bower/blob/master/README.md
:

All package contents are installed in the bower_components directory by
default. You should never directly modify the contents of this
directory.

If the boilerplate goes this route, it requires reeducation which will
meet with confusion and possibly resistance. Something akin to telling Node
developers "You can put your stuff in the node_modules folder now." It's
that confusion that I'm concerned about, not whether or not it's
conceptually ok to do it. I concede that you can probably put whatever you
want in bower_components and (with the possible exception of bower update)
it won't break anything. But I think we'll be swimming against the current
if we try to sell that idea.

FWIW, I'm not trying to stir things up. Just looking for the simplest
solution for new developers

@wibblymat https://github.com/wibblymat wdyt?


Reply to this email directly or view it on GitHubhttps://github.com/webcomponents/element-boilerplate/issues/11#issuecomment-38772025
.

@addyosmani
Copy link
Member

I'm coming around to @sjmiles world view of not trying to shape the shareable package in the same form as what we intend users to deploy to gh-pages. At the same time, I'm woefully aware that the reason we've seen so many custom elements built off the back of the current element-boilerplate has been ease of forkability and & sharability with minimum tooling and configuration. We need to take care here.

We're trying to balance lowering the barrier of entry with enabling users to publish packages which are not going to be easily reusable when installed via Bower, which I think we want to avoid. It lowers the value proposition if I have to go editing paths and re-hooking up dependencies once I've installed a component. Especially so if this needs to be done multiple times.

Scott mentioned that the Polymer team construct their gh-pages from master using a shell script. Looking at the dependencies required there, this requires git + Bower. It doesn't seem like a big ask for a developer to run a script and we could probably drop an npm install -g bower in there in case they haven't set it up or unaware how to. If it really takes less than 30 seconds, I wouldn't see this as being a huge ask. I'd certainly prefer this over a build step for deployment (however, do remember we already have a Gruntfile in the repo. A grunt deploy could be used).

@sjmiles ooi, could you share your script just for interest sake? I'm curious how much push back there would be from introducing this step and share Rob and Zeno's concerns about increasing the barrier of entry, but it seems like this path might work.

@robdodson
Copy link
Contributor

I think, in the short term, rather than defy the Bower documentation, we should use a grunt task to strip out mention of bower_components as it moves the element from src to dist. Maybe someday we can change the behavior of Bower but we need to get something that works today.

@robdodson
Copy link
Contributor

PR over here webcomponents/element-boilerplate#12

@zenorocha
Copy link
Member Author

Could you guys check @robdodson's PR #12? I want see if we're all in the same page before adding this solution to other boilerplates.

@zenorocha
Copy link
Member Author

FYI gh-pages is no longer the default branch. We're using master + a Grunt task to send files to gh-pages.

See 737d947 for more info.

@pennyfx
Copy link

pennyfx commented Apr 28, 2014

I came across this thread from here

FWIW, on X-Tag, I went with Bower and Grunt to ease the pain of dealing with dependencies. For our stub and generator you must run bower install & grunt build to bring in dependencies, but I also created grunt-smush-components so I don't have to reference each dependency individually. These lines in declarative components and multiple script tags in html always drove me crazy.

Smush-components crawls through bower list --jsonobject combining the files found in main:. It then outputs the css and js to some destination path. Example Grunt. As long as every component adds their css and js to the main: property in bower.json, it becomes easily consumable. Once I started using this method, I never worried about dependencies again. Simply add them via bower, grunt smush-components, and it's working.

@robdodson
Copy link
Contributor

Interesting. I'll try to give grunt-smush-component a look later this week. Thanks!

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

No branches or pull requests

6 participants