11import * as connect from 'connect' ;
22import * as webpack from 'webpack' ;
33import * as url from 'url' ;
4+ import * as fs from 'fs' ;
5+ import * as path from 'path' ;
46import { requireNewCopy } from './RequireNewCopy' ;
57
68export type CreateDevServerResult = {
@@ -91,11 +93,24 @@ function attachWebpackDevMiddleware(app: any, webpackConfig: webpack.Configurati
9193
9294 // Attach Webpack dev middleware and optional 'hot' middleware
9395 const compiler = webpack ( webpackConfig ) ;
96+ const originalFileSystem = compiler . outputFileSystem ;
9497 app . use ( require ( 'webpack-dev-middleware' ) ( compiler , {
9598 noInfo : true ,
9699 publicPath : webpackConfig . output . publicPath
97100 } ) ) ;
98101
102+ // After each compilation completes, copy the in-memory filesystem to disk.
103+ // This is needed because the debuggers in both VS and VS Code assume that they'll be able to find
104+ // the compiled files on the local disk (though it would be better if they got the source file from
105+ // the browser they are debugging, which would be more correct and make this workaround unnecessary).
106+ // Without this, Webpack plugins like HMR that dynamically modify the compiled output in the dev
107+ // middleware's in-memory filesystem only (and not on disk) would confuse the debugger, because the
108+ // file on disk wouldn't match the file served to the browser, and the source map line numbers wouldn't
109+ // match up. Breakpoints would either not be hit, or would hit the wrong lines.
110+ ( compiler as any ) . plugin ( 'done' , stats => {
111+ copyRecursiveSync ( compiler . outputFileSystem , originalFileSystem , '/' , [ / \. h o t - u p d a t e \. ( j s | j s o n ) $ / ] ) ;
112+ } ) ;
113+
99114 if ( enableHotModuleReplacement ) {
100115 let webpackHotMiddlewareModule ;
101116 try {
@@ -107,6 +122,22 @@ function attachWebpackDevMiddleware(app: any, webpackConfig: webpack.Configurati
107122 }
108123}
109124
125+ function copyRecursiveSync ( from : typeof fs , to : typeof fs , rootDir : string , exclude : RegExp [ ] ) {
126+ from . readdirSync ( rootDir ) . forEach ( filename => {
127+ const fullPath = path . join ( rootDir , filename ) ;
128+ const shouldExclude = exclude . filter ( re => re . test ( fullPath ) ) . length > 0 ;
129+ if ( ! shouldExclude ) {
130+ const fileStat = from . statSync ( fullPath ) ;
131+ if ( fileStat . isFile ( ) ) {
132+ const fileBuf = from . readFileSync ( fullPath ) ;
133+ to . writeFile ( fullPath , fileBuf ) ;
134+ } else if ( fileStat . isDirectory ( ) ) {
135+ copyRecursiveSync ( from , to , fullPath , exclude ) ;
136+ }
137+ }
138+ } ) ;
139+ }
140+
110141function beginWebpackWatcher ( webpackConfig : webpack . Configuration ) {
111142 const compiler = webpack ( webpackConfig ) ;
112143 compiler . watch ( { /* watchOptions */ } , ( err , stats ) => {
0 commit comments