{"id":1510,"date":"2015-01-19T16:48:27","date_gmt":"2015-01-19T15:48:27","guid":{"rendered":"http:\/\/blog.gocept.com\/?p=1510"},"modified":"2015-02-26T07:14:23","modified_gmt":"2015-02-26T06:14:23","slug":"manage-javascript-dependencies-with-fanstatic","status":"publish","type":"post","link":"https:\/\/blog.gocept.com\/2015\/01\/19\/manage-javascript-dependencies-with-fanstatic\/","title":{"rendered":"Manage JavaScript dependencies with Fanstatic"},"content":{"rendered":"

Until the beginning of this year, we were using Fanstatic<\/a> to manage dependencies to external JavaScript libraries. In case you are not familiar with Fanstatic, here is a short overview. I will discuss benefits and drawbacks later on.<\/p>\n

How it works<\/h2>\n

Imagine you want to use jQuery<\/a> in one of your projects. Therefore you build an integration package, say js.jquery<\/code>, which contains the jquery.js<\/code> file. You also add a resource.py<\/code> which would look like this:<\/p>\n

from fanstatic import Library, Resource\r\n\r\nlibrary = Library('jquery', 'resources')\r\njquery = Resource(library, 'jquery.js', minified='jquery.min.js')\r\n<\/pre>\n

To finish up, you state the version of the downloaded jquery.js<\/code> in the setup.py<\/code> and upload the package to PyPI<\/a>.<\/p>\n

After wrapping your app with Fanstatic, you can declare JavaScript dependencies by listing the integration package inside your setup.py<\/code>. To use them, you write js.jquery.need()<\/code> inside any view. Of course you can also add a resource.py<\/code> and declare a local resource with dependencies:<\/p>\n

import fanstatic\r\nimport js.jquery\r\n\r\nlibrary = fanstatic.Library('custom', 'resources')\r\nmy_awesome_js_code = fanstatic.Resource(\r\n    library, 'js\/my_awesome_js_code.js',\r\n    minified='js\/my_awesome_js_code.min.js',\r\n    depends=[js.jquery.jquery])\r\n<\/pre>\n

Every time you call my_awesome_js_code.need()<\/code> inside a view, it will also load jQuery.<\/p>\n

Benefits<\/h2>\n

With Fanstatic you no longer need to copy the JavaScript files inside your project and link them statically, you just declare them as a dependency to your own JavaScript code and call my_awesome_js_code.need()<\/code> inside a view.<\/p>\n

The preparation described above can be tedious, but the assumption is, that someone else has built the integration package before, so you can reuse it. Installing a dependency therefore is as easy as adding a line to your setup.py<\/code> and declare it as a dependency of one of your resources.<\/p>\n

Fanstatic makes it a lot easier to update external libraries, since you only need to increase the version number in your setup.py<\/code>. You can also make sure to use the same version across many projects, e.g. by sharing some buildout configuration across projects.<\/p>\n

And besides many small nice features, Fanstatic can also create bundles, i.e. it will merge my_awesome_js_code<\/code> and all of its dependencies into one big file and deliver it to the client, rather delivering all files separately. This usually makes the initial page load much faster.<\/p>\n

Drawbacks<\/h2>\n

Despite all the benefits Fanstatic offers, we were getting more and more frustrated with it. The main reason is, that we feel a decline in the activity of the Fanstatic user group. With fewer people using Fanstatic, we often have to build the integration packages ourselves. This eliminates one of the main benefits, i.e. that we could reuse the integration packages of others.<\/p>\n

For example, in a big project we did last year, we used integration packages for js.jquery<\/a>, js.classy<\/a>, js.chosen<\/a> and many more. Those are pretty popular packages and the integration worked out of the box.<\/p>\n

However, even those packages have issues: The integration package for jQuery does not offer version 2.0 or higher and Chosen is only available in a single (outdated) version. We often stumbled upon similar issues with other libraries, e.g. the integration package for js.modernizr<\/a> is more than 2 years behind.<\/p>\n

In addition, some newly developed libraries may not be available at all. Of course we could write the integration packages for those or update the jQuery integration package. But this would mean to find out where the code for an integration package is hosted, write a pull request and wait for a merge, as well as a new release on PyPI. In case the owner is not active anymore, you are out of luck and must add a duplicate package to PyPI. Tedious and unsatisfactory.<\/p>\n

This is why we started to look for an alternative to Fanstatic. And maybe we have found it, but this is a story for another day, where I will talk about our experiences with Bower<\/a> and Bowerstatic<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"

Until the beginning of this year, we were using Fanstatic to manage dependencies to external JavaScript libraries. In case you are not familiar with Fanstatic, here is a short overview. I will discuss benefits and drawbacks later on. How it works Imagine you want to use jQuery in one of your projects. Therefore you build … Continue reading “Manage JavaScript dependencies with Fanstatic”<\/span><\/a><\/p>\n","protected":false},"author":21108265,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_newsletter_tier_id":0,"footnotes":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false}}},"categories":[10221],"tags":[457],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_likes_enabled":true,"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/pFP3y-om","jetpack-related-posts":[{"id":1525,"url":"https:\/\/blog.gocept.com\/2015\/03\/06\/manage-javascript-dependencies-with-bowerstatic\/","url_meta":{"origin":1510,"position":0},"title":"Manage JavaScript dependencies with BowerStatic","author":"","date":"March 6, 2015","format":false,"excerpt":"Last month I explained how to use Fanstatic to manage JS dependencies. Since we were more and more displeased by using Fanstatic, we recently switched to BowerStatic, the new kid on the block. Since the setup is a bit more complicated and you need more tools to have the same\u2026","rel":"","context":"In "en"","block_context":{"text":"en","link":"https:\/\/blog.gocept.com\/category\/en\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":349,"url":"https:\/\/blog.gocept.com\/2012\/12\/17\/yafowil-in-a-pyramid-project\/","url_meta":{"origin":1510,"position":1},"title":"yafowil in a Pyramid project","author":"Michael Howitz","date":"December 17, 2012","format":false,"excerpt":"In a new Pyramid\u00a0project we used deform\u00a0to render forms. We did not really like it. (The reasons might be detailed in another post.) To see if other form libraries do better I\u00a0gave yafowil\u00a0a try at our\u00a0gocept Developer Punsch\u00a03: yafowil comes with written documentation. To get a form in our Pyramid\u2026","rel":"","context":"In "en"","block_context":{"text":"en","link":"https:\/\/blog.gocept.com\/category\/en\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":236,"url":"https:\/\/blog.gocept.com\/2012\/10\/24\/upcoming-talks-at-pycon-de-2012\/","url_meta":{"origin":1510,"position":2},"title":"Upcoming talks at PyCon DE 2012","author":"","date":"October 24, 2012","format":false,"excerpt":"Most of gocept is headed towards the German PyCon next week! We're excited and look forward to meeting people, exchanging ideas and learning new things. We have prepared several talks to share some of the experiences we gained over the last year: Christian Kauhaus: nagiosplugin library Christian Theune: batou deployment\u2026","rel":"","context":"In "en"","block_context":{"text":"en","link":"https:\/\/blog.gocept.com\/category\/en\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":280,"url":"https:\/\/blog.gocept.com\/2012\/11\/30\/notizen-aus-dem-norden\/","url_meta":{"origin":1510,"position":3},"title":"Notizen aus dem Norden","author":"","date":"November 30, 2012","format":false,"excerpt":"Heute neigt sich unser diesj\u00e4hriger Sprint dem Ende. Am Dienstag sind wir gen Norden auf die Insel R\u00fcgen gefahren, um uns f\u00fcr 3 Tage intensiv dar\u00fcber zu unterhalten, wie wir in Zukunft Software entwickeln wollen. Der Fokus lag dabei auf der Client-Seite, also dem Teil der Anwendung, der im Browser\u2026","rel":"","context":"In "de"","block_context":{"text":"de","link":"https:\/\/blog.gocept.com\/category\/de\/"},"img":{"alt_text":"Das gocept-Team","src":"https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2012\/11\/011.jpg?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2012\/11\/011.jpg?resize=350%2C200 1x, https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2012\/11\/011.jpg?resize=525%2C300 1.5x, https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2012\/11\/011.jpg?resize=700%2C400 2x"},"classes":[]},{"id":127,"url":"https:\/\/blog.gocept.com\/2012\/01\/30\/sprint-fruits-gocept-exttest-and-gocept-package\/","url_meta":{"origin":1510,"position":4},"title":"Sprint fruits: gocept.exttest and gocept.package","author":"","date":"January 30, 2012","format":false,"excerpt":"The whole company spent three days in Kloster Dr\u00fcbeck sprinting on internal tools and topics. We overhauled our workflow for generating invoices and identified steps that we could automate. We polished and released gocept.exttest, which integrates for example JavaScript unittest to Python's unittest framework. In a nutshell, it allows you\u2026","rel":"","context":"In "en"","block_context":{"text":"en","link":"https:\/\/blog.gocept.com\/category\/en\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.gocept.com\/wp-content\/uploads\/2012\/01\/6754824273_981f3a0c34.jpg?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":12,"url":"https:\/\/blog.gocept.com\/2009\/11\/24\/adding-round-corners-to-boxes-using-css-and-javascript\/","url_meta":{"origin":1510,"position":5},"title":"Adding round corners to boxes using CSS and JavaScript","author":"","date":"November 24, 2009","format":false,"excerpt":"Curvycorners has a way to make gorgeous\u00a0roundings to your boxes without having to split each box into pieces of background images. You simply need to include one JavaScript file and add two lines of CSS code to your box (or to the box's class definition). First, include the curvycorners javascript\u2026","rel":"","context":"In "en"","block_context":{"text":"en","link":"https:\/\/blog.gocept.com\/category\/en\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/blog.gocept.com\/wp-json\/wp\/v2\/posts\/1510"}],"collection":[{"href":"https:\/\/blog.gocept.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.gocept.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.gocept.com\/wp-json\/wp\/v2\/users\/21108265"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.gocept.com\/wp-json\/wp\/v2\/comments?post=1510"}],"version-history":[{"count":11,"href":"https:\/\/blog.gocept.com\/wp-json\/wp\/v2\/posts\/1510\/revisions"}],"predecessor-version":[{"id":1523,"href":"https:\/\/blog.gocept.com\/wp-json\/wp\/v2\/posts\/1510\/revisions\/1523"}],"wp:attachment":[{"href":"https:\/\/blog.gocept.com\/wp-json\/wp\/v2\/media?parent=1510"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.gocept.com\/wp-json\/wp\/v2\/categories?post=1510"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.gocept.com\/wp-json\/wp\/v2\/tags?post=1510"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}