CINXE.COM
How to migrate away from Bower? · Bower blog
<!doctype html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="google-site-verification" content="1XwfuTPiyoCivlUjHLisCr8ukNu3tiv0Ax_wDx3-BhY"> <link rel="apple-touch-icon" href="/apple-touch-icon.png"> <!-- V2 --> <link href='/assets/global-c92e9c719e6e670850368807f772c43c.css' rel='stylesheet' type='text/css' /> <!-- Social Medias --> <meta property="og:url" content="https://bower.io/blog/2017/how-to-migrate-away-from-bower/"> <meta property="og:image" content="https://bower.io/img/bower-logo.png"> <title>How to migrate away from Bower? · Bower blog</title> <meta property="og:title" content="How to migrate away from Bower? · Bower blog"> </head> <body class="blog-page"> <header id="masthead"> <div class="container"> <ul class="network-nav nav"> <li class="nav-docs"><a href="/">Docs</a></li> <li class="nav-search"><a href="/search/">Search packages</a></li> <li class="nav-blog"><a href="/blog/">Blog</a></li> <li class="nav-stats"><a href="/stats/">Stats</a></li> </ul> <a href="/"> <img class="logo" src="/img/bower-logo.svg" alt="Bower logo" /> </a> <h1 class="page-title">Blog</h1> </div> </header> <div id="content"> <div class="container"> <article class="blog-post"> <div class="sidebar"> <p class="blog-post-date">02 Oct 2017</p> <img class="blog-post-author-avatar" src="https://avatars3.githubusercontent.com/u/292365" alt="Adam Stankiewicz"> <p class="blog-post-author-name"> by <a href="https://twitter.com/sheerun">Adam Stankiewicz</a> </p> </div> <div class="main"> <h1 class="blog-post-title"><a href="/blog/2017/how-to-migrate-away-from-bower/">How to migrate away from Bower?</a></h1> <div class="blog-post-content"> <blockquote> <p>If you came here because of “Request to xxx failed with 410” error, it’s enough to <a href="https://twitter.com/bower/status/918073147789889536">upgrade</a></p> </blockquote> <p>As you might have noticed, we started recommending <a href="https://yarnpkg.com">Yarn</a> as an alternative to Bower for <strong>new</strong> front-end projects. Main reasons are straightforward and written on its home page:</p> <ol> <li>Yarn uses checksums to verify the integrity of every installed package (like npm@5)</li> <li>Yarn uses lockfile to exactly reproduce installed packages each time (like npm@5)</li> <li>Yarn supports most features npm supports, and is able to force flattening of dependencies</li> </ol> <p>So far it just wasn’t obvious how one could use Yarn for <strong>legacy</strong> Bower projects. Indeed, until recently Yarn neither could install Bower packages (i.e. GitHub repositories without <code class="highlighter-rouge">package.json</code>) nor resolve semver ranges on git tags. I focused on this <a href="https://github.com/yarnpkg/yarn/pull/3624">for</a> <a href="https://github.com/yarnpkg/yarn/pull/3701">a</a> <a href="https://github.com/yarnpkg/yarn/pull/3855">while</a> and the result is pleasing: <strong>Yarn 1.x is able to install most of Bower packages</strong>. But there’s a catch: it cannot resolve Bower dependencies.</p> <p>But this is probably for the best as a) Yarn is meant as npm’s replacement b) one must admit npm’s CommonJS module ecosystem is <a href="https://medium.com/@trek/last-week-i-had-a-small-meltdown-on-twitter-about-npms-future-plans-around-front-end-packaging-b424dd8d367a">better integrated</a> than Bower’s globals/AMD modules c) Module authors currently suffer from supporting two module ecosystems (and dist files in repositories).</p> <p>Admitting this doesn’t change the fact that it’s difficult to migrate a project that uses globals/AMD components to CommonJS all at once. Ideally you’d be able to install such project with Yarn as-is, and only then gradually replace AMD modules with CommonJS/ES6 equivalents. Solution: <a href="https://github.com/sheerun/bower-away"><strong>bower-away</strong></a>.</p> <h3 id="how-it-works">How it works?</h3> <p>Yarn is not only unable to resolve dependencies of Bower components (i.e. dependencies defined in <code class="highlighter-rouge">bower.json</code>, it looks just for ones in <code class="highlighter-rouge">package.json</code>), it also cannot translate names of Bower components to URLs of repositories as <a href="https://bower.io/blog/2017/how-to-drop-bower-support/#why-step-4">described in previous blogpost</a>. <code class="highlighter-rouge">bower-away</code> gets away with this by resolving all dependencies with Bower, and adding all of them <strong>flattened</strong> to <code class="highlighter-rouge">package.json</code>.</p> <p>The result is something as follows:</p> <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w"> </span><span class="s2">"dependencies"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="s2">"@bower_components/almond"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"jrburke/almond#~0.2.9"</span><span class="p">,</span><span class="w"> </span><span class="s2">"@bower_components/angular"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"angular/bower-angular#^1.0.8"</span><span class="p">,</span><span class="w"> </span><span class="s2">"@bower_components/d3"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"mbostock-bower/d3-bower#~3.3.10"</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span></code></pre></div></div> <p>Now, if you install this <code class="highlighter-rouge">package.json</code> with Yarn, <code class="highlighter-rouge">node_modules/@bower_components</code> will contain all components in exactly the same way they would be installed by Bower (sans generated <code class="highlighter-rouge">.bower.json</code>).</p> <p>And not only that, if some component supports CommonJS interface, you can employ <a href="https://webpack.js.org/">Webpack</a> for precompiling and require it as so: <code class="highlighter-rouge">const almond = require('@bower_components/almond')</code>.</p> <p>For components that don’t support CommonJS, you can find their CommonJS equivalents and add them to project: <code class="highlighter-rouge">yarn add d3@~3.3.10</code>, then require as usual <code class="highlighter-rouge">const d3 = require('d3')</code></p> <p>But initially, the only change required in code is to change any reference to <code class="highlighter-rouge">bower_components</code> with <code class="highlighter-rouge">node_modules/@bower_components</code> (though you can link it somewhere else in postinstall script).</p> <hr /> <p>If you have any questions or find any issues with this script, please post issue at <a href="https://github.com/sheerun/bower-away">bower-away</a> repository.</p> </div> </div> </article> </div> <div class="container"> <div class="sidebar"></div> <div class="main"> <footer class="site-footer"> <p class="issue"><a href="https://github.com/bower/bower.github.io/issues">Help improve this post. Open an issue or pull request.</a></p> </footer> </div> </div> </div> <script src='/assets/global-e54f86d7a57a76019ff78ea767ebd50b.js' type='text/javascript'></script> <!--GA tracking--> <script> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-43531210-2', 'auto'); ga('require', 'linkid', 'linkid.js'); // Enable enhanced link attribution ga('require', 'displayfeatures'); // Enable Demographics and Interest Reports ga('send', 'pageview'); </script> </body> </html>