Skip to content

Commit 4d0faca

Browse files
fix: server reload, race condition and environment variable stubbed (#22)
1 parent d4976a8 commit 4d0faca

File tree

8 files changed

+88
-25
lines changed

8 files changed

+88
-25
lines changed

package-lock.json

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
"prettier": "^1.13.5",
6262
"pretty-quick": "^1.6.0",
6363
"semantic-release": "^15.6.0",
64-
"sinon": "^6.0.0",
64+
"sinon": "^6.0.1",
6565
"tslint": "^5.10.0",
6666
"tslint-immutable": "^4.6.0",
6767
"validate-commit-msg": "^2.14.0",
@@ -78,7 +78,7 @@
7878
"ng2-fused": "^0.5.1",
7979
"npm": "^6.1.0",
8080
"rxjs": "^6.2.1",
81-
"ts-node": "^6.1.2",
81+
"ts-node": "^7.0.0",
8282
"typescript": "2.7.2",
8383
"uglify-js": "^3.4.1",
8484
"yargs": "^11.0.0"

src/commands/serve.ts

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@ import {
66
JSONPlugin,
77
QuantumPlugin,
88
RawPlugin,
9-
SassPlugin
9+
SassPlugin,
10+
EnvPlugin
1011
} from 'fuse-box'
1112
import { resolve } from 'path'
1213
import { NgProdPlugin } from '../fusebox/ng.prod.plugin'
1314
import { NgPolyfillPlugin } from '../fusebox/ng.polyfill.plugin'
1415
import { NgCompilerPlugin } from '../fusebox/ng.compiler.plugin'
1516
import readConfig_ from '../utilities/read-config'
1617
import { Ng2TemplatePlugin } from 'ng2-fused'
18+
import { FuseProcess } from 'fuse-box/FuseProcess'
1719

1820
command(
1921
'serve [port][prod][aot][sw]',
@@ -92,9 +94,6 @@ function serve(isProdBuild = false) {
9294
uglify: config.fusebox.browser.prod.uglify,
9395
treeshake: config.fusebox.browser.prod.treeshake,
9496
bakeApiIntoBundle: 'vendor'
95-
// replaceProcessEnv: false,
96-
// processPolyfill: true,
97-
// ensureES5: true
9897
})
9998
] as any
10099
})
@@ -107,6 +106,9 @@ function serve(isProdBuild = false) {
107106
homeDir,
108107
output: `${serverOutput}/$name.js`,
109108
plugins: [
109+
EnvPlugin({
110+
FUSING_ANGULAR: JSON.stringify(config.environment)
111+
}),
110112
JSONPlugin(),
111113
Ng2TemplatePlugin(),
112114
['*.component.html', RawPlugin()],
@@ -131,23 +133,31 @@ function serve(isProdBuild = false) {
131133
]
132134
})
133135

136+
// tslint:disable-next-line:no-let
137+
let prevServerProcess: FuseProcess
138+
134139
fuseBrowser
135140
.bundle('vendor')
136141
.watch(watchDir)
137142
.instructions(` ~ ${browserModule}`)
143+
.completed(fn => {
144+
fuseServer
145+
.bundle('server')
146+
.instructions(` > [${config.fusebox.server.serverModule}]`)
147+
.completed(proc => {
148+
prevServerProcess && prevServerProcess.kill()
149+
proc.start()
150+
prevServerProcess = proc
151+
})
152+
fuseServer.run()
153+
})
138154

139155
fuseBrowser
140156
.bundle('app')
141157
.watch(watchDir)
142158
.instructions(` !> [${browserModule}]`)
143159

144-
fuseServer
145-
.bundle('server')
146-
.watch(watchDir)
147-
.instructions(` > [${config.fusebox.server.serverModule}]`)
148-
.completed(proc => proc.start())
149-
150-
fuseServer.run()
160+
logInfo('Bundling your application, this may take some time...')
151161
fuseBrowser.run()
152162
})
153163
}

src/fusebox/gzip.plugin.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { Plugin, BundleProducer } from 'fuse-box'
2+
import { gzipSync } from 'zlib'
3+
4+
// tslint:disable:no-class
5+
// tslint:disable:no-this
6+
// tslint:disable:no-if-statement
7+
// tslint:disable:no-object-mutation
8+
// tslint:disable:readonly-keyword
9+
const defaults: GzipPluginOptions = {
10+
enabled: true
11+
}
12+
13+
export interface GzipPluginOptions {
14+
enabled?: boolean
15+
fileTest?: string
16+
}
17+
18+
export class GzipPluginClass implements Plugin {
19+
constructor(public opts: GzipPluginOptions = defaults) {
20+
this.opts = {
21+
...defaults,
22+
...opts
23+
}
24+
}
25+
producerEnd?(producer: BundleProducer): any {
26+
return Promise.all(
27+
Array.from(producer.bundles).map(bundle => {
28+
const zipThis = bundle[1].context.source.getResult().content
29+
const zipped = gzipSync(zipThis, { level: 9 })
30+
return bundle[1].context.output.writeCurrent(zipped)
31+
})
32+
)
33+
}
34+
}
35+
36+
export const GzipPlugin = (options?: GzipPluginOptions) =>
37+
new GzipPluginClass(options)

src/generators/deps.const.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ export const ANGULAR_UNIVERSAL_DEPS = {
2929
export const ANGULAR_UNIVERSAL_DEV_DEPS = {
3030
'@types/compression': '^0.0.36',
3131
'@types/cookie-parser': '^1.4.1',
32-
'@types/express': '^4.16.0'
32+
'@types/express': '^4.16.0',
33+
reload: '^2.3.0'
3334
}
3435

3536
export const ANGULAR_UNIVERSAL_EXPRESS_DEPS = {

src/templates/core/server/server.app.ts.txt

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ import { resolve } from 'path'
55
import { ngExpressEngine } from '@nguniversal/express-engine'
66
import { AppServerModule } from './server.angular.module'
77
import { stat, writeFile } from 'fs'
8-
// import * as config from '../../fusing-angular.json'
98

9+
const environment = JSON.parse(process.env.FUSING_ANGULAR || '{}')
10+
const isLocalDevelopmentServer = environment.name === 'DEVELOPMENT'
1011
// const minifyHTML = require('express-minify-html')
1112
// const xhr2 = require('xhr2')
1213

@@ -31,14 +32,20 @@ const publicDir = `${dir}/public`
3132
// }
3233
// }
3334

35+
isLocalDevelopmentServer && require('reload')(expressApp)
36+
3437
expressApp.use(cookieParser())
3538
expressApp.use(compression())
3639

37-
expressApp.use('/favicon.ico', (req, res) => res.sendStatus(204)) // TODO: FAVICONS
38-
expressApp.use('/js', express.static(`${publicDir}/js`, { fallthrough: false }))
40+
expressApp.set('x-powered-by', false)
41+
expressApp.set('etag', false)
3942
expressApp.set('view engine', 'html')
43+
4044
expressApp.engine('html', ngExpressEngine({ bootstrap: AppServerModule }))
4145

46+
expressApp.use('/favicon.ico', (req, res) => res.sendStatus(204)) // TODO: FAVICONS
47+
expressApp.use('/js', express.static(`${publicDir}/js`, { fallthrough: false, etag: false }))
48+
4249
const virtualIndex = (req: express.Request,
4350
res: express.Response, document: string, path = `${publicDir}/index.html`) => {
4451

@@ -71,6 +78,7 @@ expressApp.get('**', (req, res) => {
7178
<app-root></app-root>
7279
<script src="/js/vendor.js"></script>
7380
<script src="/js/app.js"></script>
81+
${isLocalDevelopmentServer ? '<script src="/reload/reload.js"></script>' : ''}
7482
</body>
7583
</html>`
7684
virtualIndex(req, res, document)
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { createServer } from 'http'
22
import { expressApp } from './server.app'
33

4+
const config = JSON.parse(process.env.FUSING_ANGULAR || '{}')
45
const server = createServer(expressApp)
56

6-
server.listen(5000, () => {
7-
console.log('Angular Universal Server listening')
7+
server.listen(config.server.port, () => {
8+
console.log(`Angular Universal server listening on port: ${config.server.port}`)
89
})

src/utilities/read-config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,15 @@ export interface FuseBoxConfig {
3333
readonly verbose: boolean
3434
}
3535

36+
export interface EnvironmentConfig {
37+
readonly server: any
38+
readonly app: any
39+
}
40+
3641
export interface FusingAngularConfig {
3742
readonly favicon: FaviconConfig
3843
readonly fusebox: FuseBoxConfig
44+
readonly environment: EnvironmentConfig
3945
}
4046

4147
export default function readConfig_() {

0 commit comments

Comments
 (0)