1
1
import * as connect from 'connect' ;
2
2
import * as webpack from 'webpack' ;
3
3
import * as url from 'url' ;
4
+ import * as fs from 'fs' ;
5
+ import * as path from 'path' ;
4
6
import { requireNewCopy } from './RequireNewCopy' ;
5
7
6
8
export type CreateDevServerResult = {
@@ -91,11 +93,24 @@ function attachWebpackDevMiddleware(app: any, webpackConfig: webpack.Configurati
91
93
92
94
// Attach Webpack dev middleware and optional 'hot' middleware
93
95
const compiler = webpack ( webpackConfig ) ;
96
+ const originalFileSystem = compiler . outputFileSystem ;
94
97
app . use ( require ( 'webpack-dev-middleware' ) ( compiler , {
95
98
noInfo : true ,
96
99
publicPath : webpackConfig . output . publicPath
97
100
} ) ) ;
98
101
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
+
99
114
if ( enableHotModuleReplacement ) {
100
115
let webpackHotMiddlewareModule ;
101
116
try {
@@ -107,6 +122,22 @@ function attachWebpackDevMiddleware(app: any, webpackConfig: webpack.Configurati
107
122
}
108
123
}
109
124
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
+
110
141
function beginWebpackWatcher ( webpackConfig : webpack . Configuration ) {
111
142
const compiler = webpack ( webpackConfig ) ;
112
143
compiler . watch ( { /* watchOptions */ } , ( err , stats ) => {
0 commit comments