4

I noticed that many (large) PHP applications use Composer for managing the dependencies. I'm currently trying to figure out if I should switch to Composer (at the moment I'm simply keeping my dependencies in a folder called vendor/ - without being able to automatically update them).

I prefer this way because:

  • I don't rely on 3rd party websites/repositories to get the source code (I find this as being a security concern as well); and, also, what happens if one of the repositories goes down for any reason? I will no longer be able to update/install my application?

  • I don't need Composer installed (on the local machine/production machine); this is just a minor issue;

  • It's faster; obviously, the updates can be pushed faster to production if they come from a single source - it's enough to just update my bundle (that contains all vendor packages) and then simply push/pull the changes to/from production;

  • I'm using many components that are not aware of Composer (standalone libraries, GitHub repositories that are lacking the composer.json file, many JS/CSS assets, even isolated single PHP classes that I prefer to think as 3rd party libraries etc); if I were to use Composer I would have to use a tool like Satis to manage these (and things get more complicated without a real benefit);

  • I have my application deployed to several domains (around 25) and it's easier to maintain it this way (a single bundle where all changes get [automatically] pushed and later on the bundle itself can be pushed to production);

  • There are many changes and updates (a few commits each day to the main application package) and I find it easier to simply push these commits to production rather than setting up tags for each commit so that Composer can see the difference and update to the new version;

On the other hand, there are some problems with my approach:

  • First of all, I'm including all the vendor packages in my codebase/build; I know this is not a good practice and I understand the arguments behind this (I'd prefer to avoid this);

  • It may be a good thing that I'm able to trace all source code changes to my application in a single repository (I use git). Obviously, all vendor changes will be reflected in the bundle repository. But on the other hand there's some redundancy - I'm also working myself on some of the dependent vendor packages so it doesn't make much sense to COMMIT the changes there and add the relevant message to the COMMIT and then the same changes to be commited on the bundle package, as well;

  • More bundles: I have a few applications that are extensions of the main application - they provide their own business logic, additional controllers etc; For these I need to create separate bundles that will again contain all the vendor packages - so, whenever a vendor package gets updates I need to propagate these changes to the additional bundles, too;

  • It's not that straightforward to work in a team: how should the process go? Each member should update the core application package then update the bundle itself? Then the other members will download both the bundle and the core application? Again, I find it somehow redundant;

My approach worked so far, but I think that I might be missing something in this whole developing/deployment process. I'm trying to stay focused on developing rather than managing dependencies/deploying so I'd prefer that the deployment process is as smooth and transparent as possible. Also, with this approach the update on each server takes about 30 seconds, with composer it would take a lot more (as the update in Composer needs to connect to all 3rd party repositories).

So, as a summary:

  • I think there's a redundancy in my current way of working;

  • I'd like to know if there are better ways to handle this (simple deployment process to all my 25 domains - about 20 of them are sharing the same codebase; no source code redundancy; team work friendly);

  • There are many updates to the source code each day so the update/deployment process should not be a hassle;

  • I really like the modular approach for developing: having an application that *requires* other modules; if I need the same application just slightly modified I add an additional module that changes some of the existing logic and that's it. I'd like to keep it this way without having to build bundles made up of modules and then install the bundle.

Any ideas for improvement?

Edit: I found two articles related to this topic that are quite interesting: http://www.redotheweb.com/2013/09/12/should-you-commit-dependencies.html and http://addyosmani.com/blog/checking-in-front-end-dependencies/. I believe that what they are mainly saying is that "it depends". So, I assume that, at least for me it would be better to checkin my dependencies.

    2 Answers 2

    1

    Most of your issues with Composer can be mitigated:

    • Host a copy of the dependencies yourself. You can even keep them updated automatically via a scheduled git pull. For a large project and/or a corporate environment this is a good step.
    • Use a build system or continuous integration server which creates a production ready bundle you can upload in one fell swoop. This can be as simple as a single shell script. If you're using a proper deploy system (as opposed to manual FTP uploads), this should be trivial to hook up.

    These two things should alleviate most of your concerns. You didn't indicate whether you're already using a deployment system; if not this may actually be your biggest problem. In an automated deployment your build step can be as complex as necessary, if it can all be scripted it doesn't really matter.

    Regarding:

    I'm using many components that are not aware of Composer; if I were to use Composer I would have to use a tool like Satis to manage these.

    You are aware that you can simply write an inline definition of the missing composer.json file inside your own composer.json? For most situations this allows you to retrofit Composer support without problems.

    There are many changes and updates and I find it easier to simply push these commits to production rather than setting up tags for each commit so that Composer can see the difference and update to the new version

    It is not necessary to create individual tags. You can use git commit numbers just as well.


    Composer is helpful just for the dependency resolution alone. More and more packages are becoming more and more complex, tracking down dependencies manually can be quite a chore. Not to mention the occasional version conflict, which is hard to catch manually and usually only manifests as obscure bugs at runtime if you don't use a dependency manager.

    Getting a proper development, dependency management, build, test, deploy workflow set up is one of those things that may take a while upfront, but saves you countless hours in the long run on sufficiently complex projects.

    2
    • Thank you! That's mainly what I'm doing right now: hosting a copy of the dependencies myself (I have a GIT repo that contains the bundle together with the dependencies). So, basically, you're saying that it's not necessary a bad thing that I'm deploying my application together with the dependencies, rather than pulling the dependencies on the production server, right? (I'm already using a deployment system, so everything happens automatically - this was not the issue; I'm just not happy with the fact that whenever a small part of business changes for a client I have to create a new bundle).
      – Razvan
      CommentedDec 20, 2014 at 13:01
    • IMO it simplifies things a lot. Keeping everything bundled up including its dependencies minimises problems. Yes, it's a larger bundle, but unless that's actually becoming a problem bandwidth or storage wise, I'd just accept it as the cost of managing dependencies.
      – deceze
      CommentedDec 20, 2014 at 22:12
    0

    It seems like your main issue with composer is speed. Since so much code is shared between projects, you could have symlinks for shared vendor subfolders so you only need to update in one of the projects and it will update all of them. You can then deploy to all the servers using rsync.

    I like to have a file with the build version in each project so I can use it in my deployment scripts to update the css/js minified file names with it for cache invalidation. You could even set up a temporary file with a global cache of all the projects' build versions so that you can compare when deploying and only push those that were updated.

      Start asking to get answers

      Find the answer to your question by asking.

      Ask question

      Explore related questions

      See similar questions with these tags.