PageSourceSearch

https://johnnyreilly.com/assets/js/c47d8059.83a5428c.js

js johnnyreilly.com collected 2026-09-24 19:32:19 UTC 12,014 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkjohnnyreilly_com=self.webpackChunkjohnnyreilly_com||[]).push([["26110"],{14076(e,t,n){n.r(t),n.d(t,{assets:()=>r,contentTitle:()=>l,default:()=>c,frontMatter:()=>s,metadata:()=>o,toc:()=>d});var o=n(46349),i=n(74848),a=n(28453);let s={slug:"npm-please-stop-hurting-visual-studio",title:"npm please stop hurting Visual Studio",authors:"johnnyreilly",date:new Date("2015-06-29T00:00:00.000Z"),tags:["node.js"],hide_table_of_contents:!1,description:"Windows handling of long paths can be problematic when using Visual Studio with npm; using rimraf for deletions can help until npm 3.0 comes out.",atUri:"at://did:plc:yy3apqjlms24kso7ahn7lbmb/site.standard.document/3mr5bswwtkl2w"},l,r={authorsImageUrls:[void 0]},d=[{value:"The Latest Infraction",id:"the-latest-infraction",level:2},{value:"rimraf to the Rescue",id:"rimraf-to-the-rescue",level:2}];function h(e){let t={a:"a",code:"code",em:"em",h2:"h2",img:"img",li:"li",p:"p",pre:"pre",ul:"ul",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"I don't know about you but I personally feel that the following sentence may well be the saddest in the English language:"}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.code,{children:"2&gt;ASPNETCOMPILER : error ASPRUNTIME: The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters."})}),"\n",(0,i.jsxs)(t.p,{children:["The message above would suggest there is some kind of ASP.Net issue going on. There isn't - the problem actually lies with Windows. It's ",(0,i.jsx)(t.a,{href:"/gulp-npm-long-paths-and-visual-studio-fight",children:"not the first time it's come up"})," but for those of you not aware there is something you need to know about Windows: ",(0,i.jsx)(t.em,{children:"It handles long paths badly."})]}),"\n",(0,i.jsx)(t.p,{children:"There's a number of caveats which people may attach the above sentence. But essentially what I have said is true. And it becomes brutally apparent to you the moment you start using a few node / npm powered tools in your workflow. You will likely see that horrible message and you won't be able to get much further forward. Sigh. I thought this was the future..."}),"\n",(0,i.jsxs)(t.p,{children:["This post is about how to deal with the long path issue when using npm with Visual Studio. This should very much be a short term workaround as ",(0,i.jsx)(t.a,{href:"https://github.com/npm/npm/releases/tag/v3.0.0",children:"npm 3.0"})," is planned to make long paths with npm a thing of the past. But until that golden dawn...."]}),"\n",(0,i.jsx)(t.h2,{id:"the-latest-infraction",children:"The Latest Infraction"}),"\n",(0,i.jsxs)(t.p,{children:["I'm a big fan of Gulp and Bower. They rock. ",(0,i.jsx)(t.a,{href:"https://twitter.com/codecadwallader",children:"Steve Cadwallader"})," wrote an excellent blog post about ",(0,i.jsx)(t.a,{href:"http://www.codecadwallader.com/2015/03/15/integrating-gulp-into-your-tfs-builds-and-web-deploy/",children:"integrating Gulp into your Visual Studio build"}),". Essentially the Gist of his post is this: forget using ",(0,i.jsx)(t.a,{href:"https://visualstudiogallery.msdn.microsoft.com/8e1b4368-4afb-467a-bc13-9650572db708",children:"Task Runner Explorer"})," to trigger your Gulp / Grunt jobs. No, actually plug it into the build process by tweaking your ",(0,i.jsx)(t.code,{children:".csproj"})," file. The first time I used this approach it was a dream come true. It just worked and I was a very happy man."]}),"\n",(0,i.jsxs)(t.p,{children:["Since this approach was so marvellous I took a look at the demo / docs part of ",(0,i.jsx)(t.a,{href:"https://github.com/johnnyreilly/jQuery.Validation.Unobtrusive.Native",children:"jQuery Validation Unobtrusive Native"})," with a view to applying it there. I originally wrote this back in 2013 and at the time used NuGet for both server and client side package management. I decided to migrate it to use Bower for the client side packages (which I planned to combine with a Gulp script which was going to pull out the required JS / CSS etc as needed). However it wasn't the plain sailing I'd imagined. The actual switchover from NuGet to Bower was simple. Just a case of removing NuGet packages and adding their associated Bower counterpart. The problem came when the migration was done and I hit \"compile\". That's when I got to see ",(0,i.jsx)(t.code,{children:"2&gt;ASPNETCOMPILER : error ASPRUNTIME: The specified path, file name, or both are too long..."})," etc"]}),"\n",(0,i.jsxs)(t.p,{children:["For reasons that I don't fully understand, Visual Studio is really upset by the presence in the project structure of one almighty long path. Oddly enough, not a path that's actually part of the Visual Studio project in question at all. Rather one that has come along as a result of our Gulp / Bower / npm shenanigans. Quick as a flash, I whipped out Daniel Schroeder's ",(0,i.jsx)(t.a,{href:"https://pathlengthchecker.codeplex.com/",children:"Path Length Checker"})," to see where the problem lay:"]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{src:`https://res.cloudinary.com/priou/image/fetch/f_auto,q_auto,w_auto,dpr_auto/https://johnnyreilly.com${n(98297).A}`,width:"640",height:"497",loading:"eager",fetchpriority:"high"})}),"\n",(0,i.jsx)(t.p,{children:"And lo, the fault lay with Bower. Poor show, Bower, poor show."}),"\n",(0,i.jsx)(t.h2,{id:"rimraf-to-the-rescue",children:"rimraf to the Rescue"}),"\n",(0,i.jsxs)(t.p,{children:[(0,i.jsx)(t.a,{href:"https://github.com/isaacs/rimraf",children:"rimraf"}),' is "the ',(0,i.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Rm_(Unix)",children:"UNIX command"}),(0,i.jsx)(t.code,{children:"rm -rf"}),' for node". (By the way, what is it with node and the pathological hatred of capital letters?)']}),"\n",(0,i.jsxs)(t.p,{children:["What this means is: rimraf can delete. Properly. So let's get it: ",(0,i.jsx)(t.code,{children:"npm install -g rimraf"}),". Then at any time at the command line we can dispose of a long path in 2 shakes of lamb's tail."]}),"\n",(0,i.jsxs)(t.p,{children:["In my current situation the contents of the ",(0,i.jsx)(t.code,{children:"node_modules"})," folder is causing me heartache. But with rimraf in play I can get rid of it with the magic words: ",(0,i.jsx)(t.code,{children:"rimraf ./node_modules"}),". Alakazam! So let's poke this command into the extra commands that I've already shoplifted from Steve's blog post. I'll end up with the following section of XML at the end of my ",(0,i.jsx)(t.code,{children:".csproj"}),":"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-xml",children:'<PropertyGroup>\n    <CompileDependsOn>\n      $(CompileDependsOn);\n      GulpBuild;\n    </CompileDependsOn>\n    <CleanDependsOn>\n      $(CleanDependsOn);\n      GulpClean\n    </CleanDependsOn>\n    <CopyAllFilesToSingleFolderForPackageDependsOn>\n      CollectGulpOutput;\n      $(CopyAllFilesToSingleFolderForPackageDependsOn);\n    </CopyAllFilesToSingleFolderForPackageDependsOn>\n    <CopyAllFilesToSingleFolderForMsdeployDependsOn>\n      CollectGulpOutput;\n      $(CopyAllFilesToSingleFolderForPackageDependsOn);\n    </CopyAllFilesToSingleFolderForMsdeployDependsOn>\n  </PropertyGroup>\n  <Target Name="GulpBuild">\n    <Exec Command="npm install" />\n    <Exec Command="bower install" />\n    <Exec Command="gulp" />\n    <Exec Command="rimraf ./node_modules" />\n  </Target>\n  <Target Name="GulpClean">\n    <Exec Command="npm install" />\n    <Exec Command="gulp clean" />\n    <Exec Command="rimraf ./node_modules" />\n  </Target>\n  <Target Name="CollectGulpOutput">\n    <ItemGroup>\n      <_CustomFiles Include="build\\**\\*" />\n      <FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">\n        <DestinationRelativePath>build\\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>\n      </FilesForPackagingFromProject>\n    </ItemGroup>\n    <Message Text="CollectGulpOutput list: %(_CustomFiles.Identity)" />\n  </Target>\n'})}),"\n",(0,i.jsxs)(t.p,{children:["So let's focus on the important bits in the ",(0,i.jsx)(t.code,{children:"GulpBuild"})," target:"]}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:'&lt;Exec Command="npm install" /&gt;'}
1)," - install the node packages our project uses as specified in ",(0,i.jsx)(t.code,{children:"package.json"}),". This will include Gulp and Bower. The latter package is going to contain super-long, Windows wrecking paths."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:'&lt;Exec Command="bower install" /&gt;'})," - install the bower packages specified in ",(0,i.jsx)(t.code,{children:"bower.json"})," using Bower (which was installed by npm just now)."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:'&lt;Exec Command="gulp" /&gt;'})," - do a little dance, make a little love, copy a few files, get down tonight."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:'&lt;Exec Command="rimraf ./node_modules" /&gt;'})," - remove the ",(0,i.jsx)(t.code,{children:"node_modules"})," folder populated by the ",(0,i.jsx)(t.code,{children:"npm install"})," command."]}),"\n"]}),"\n",(0,i.jsxs)(t.p,{children:["With that addition of ",(0,i.jsx)(t.code,{children:"rimraf ./node_modules"})," to the build phase the problem goes away. During each build a big, big Windows path is being constructed but then it's wiped again before it has chance to upset anyone. I've also added the same to the ",(0,i.jsx)(t.code,{children:"GulpClean"})," target."]}),"\n",(0,i.jsx)(t.p,{children:"You are very welcome."})]})}function c(e={}){let{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},98297(e,t,n){n.d(t,{A:()=>o});let o=n.p+"assets/images/bower-with-the-long-paths-809754f96c480d0a06dc9eded60c8187.png"},28453(e,t,n){n.d(t,{R:()=>s,x:()=>l});var o=n(96540);let i={},a=o.createContext(i);function s(e){let t=o.useContext(a);return o.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),o.createElement(a.Provider,{value:t},e.children)}},46349(e){e.exports=JSON.parse('{"permalink":"/npm-please-stop-hurting-visual-studio","editUrl":"https://github.com/johnnyreilly/blog.johnnyreilly.com/edit/main/blog-website/blog/2015-06-29-npm-please-stop-hurting-visual-studio/index.md","source":"@site/blog/2015-06-29-npm-please-stop-hurting-visual-studio/index.md","title":"npm please stop hurting Visual Studio","description":"Windows handling of long paths can be problematic when using Visual Studio with npm; using rimraf for deletions can help until npm 3.0 comes out.","date":"2015-06-29T00:00:00.000Z","tags":[{"inline":false,"label":"Node.js","permalink":"/tags/node-js","description":"The Node.js runtime."}],"readingTime":4.82,"hasTruncateMarker":true,"authors":[{"name":"John Reilly","title":"OSS Engineer - TypeScript, Azure, React, Node.js, .NET","url":"https://johnnyreilly.com/about","imageURL":"https://johnnyreilly.com/img/profile-2025.jpg","key":"johnnyreilly","page":null}],"frontMatter":{"slug":"npm-please-stop-hurting-visual-studio","title":"npm please stop hurting Visual Studio","authors":"johnnyreilly","date":"2015-06-29T00:00:00.000Z","tags":["node.js"],"hide_table_of_contents":false,"description":"Windows handling of long paths can be problematic when using Visual Studio with npm; using rimraf for deletions can help until npm 3.0 comes out.","atUri":"at://did:plc:yy3apqjlms24kso7ahn7lbmb/site.standard.document/3mr5bswwtkl2w"},"unlisted":false,"prevItem":{"title":"Upgrading to Globalize 1.x for Dummies","permalink":"/upgrading-to-globalize-1x-for-dummies"},"nextItem":{"title":"Back to the Future with Code First Migrations","permalink":"/Back-to-the-Future-with-Code-First-Migrations"}}')}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.