Skip to content

Commit b1fe7cf

Browse files
committed
chore(dev): use webpack dev server, HMR
1 parent cc019c2 commit b1fe7cf

File tree

8 files changed

+134
-102
lines changed

8 files changed

+134
-102
lines changed

Diff for: templates/app/_package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
},
5151
"devDependencies": {
5252
<%# CLIENT %>
53+
"@angularclass/hmr-loader": "^3.0.2",
5354
"@angularclass/match-control": "^2.0.0",
5455
"reflect-metadata": "^0.1.3",
5556
"rxjs": "5.0.0-beta.12",
@@ -139,8 +140,7 @@
139140
"lazypipe": "^1.0.1",
140141
<%# WEBPACK %>
141142
"webpack": "2.2.0",
142-
"webpack-dev-middleware": "^1.9.0",
143-
"webpack-dev-server": "^2.2.0-rc.0",
143+
"webpack-dev-server": "^2.2.0",
144144
"extract-text-webpack-plugin": "2.0.0",
145145
"html-webpack-plugin": "^2.24.1",
146146
"html-webpack-harddisk-plugin": "~0.0.2",

Diff for: templates/app/client/app/app.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import '!!style!css!sass!./app.<%= styleExt %>';
1+
import '!!style-loader!css-loader!sass-loader!./app.scss';
22

33
import './polyfills';
44

Diff for: templates/app/client/app/app.module.js

+55-2
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,26 @@
4444
// })<% } %>;
4545

4646

47-
import { NgModule, ErrorHandler, Injectable } from '@angular/core';
47+
import {
48+
NgModule,
49+
ErrorHandler,
50+
Injectable,
51+
ApplicationRef,
52+
} from '@angular/core';
4853
import { BrowserModule } from '@angular/platform-browser';
4954
import {
5055
HttpModule,
5156
BaseRequestOptions,
5257
RequestOptions,
5358
RequestOptionsArgs,
5459
} from '@angular/http';
60+
import {
61+
removeNgStyles,
62+
createNewHosts,
63+
disposeOldHosts,
64+
createInputTransfer,
65+
restoreInputValues,
66+
} from '@angularclass/hmr';
5567
<%_ if (filters.uirouter) { -%>
5668
import { UIRouterModule } from 'ui-router-ng2';<% } %>
5769
import { provideAuth } from 'angular2-jwt';
@@ -99,4 +111,45 @@ if(constants.env === 'development') {
99111
],
100112
bootstrap: [AppComponent]
101113
})
102-
export class AppModule {}
114+
export class AppModule {
115+
static parameters = [ApplicationRef];
116+
constructor(appRef/*: ApplicationRef*/) {
117+
this.appRef = appRef;
118+
}
119+
120+
hmrOnInit(store) {
121+
if (!store || !store.state) return;
122+
console.log('HMR store', store);
123+
console.log('store.state.data:', store.state.data)
124+
// inject AppStore here and update it
125+
// this.AppStore.update(store.state)
126+
if ('restoreInputValues' in store) {
127+
store.restoreInputValues();
128+
}
129+
// change detection
130+
this.appRef.tick();
131+
delete store.state;
132+
delete store.restoreInputValues;
133+
}
134+
135+
hmrOnDestroy(store) {
136+
var cmpLocation = this.appRef.components.map(cmp => cmp.location.nativeElement);
137+
// recreate elements
138+
store.disposeOldHosts = createNewHosts(cmpLocation)
139+
// inject your AppStore and grab state then set it on store
140+
// var appState = this.AppStore.get()
141+
store.state = {data: 'yolo'};
142+
// store.state = Object.assign({}, appState)
143+
// save input values
144+
store.restoreInputValues = createInputTransfer();
145+
// remove styles
146+
removeNgStyles();
147+
}
148+
149+
hmrAfterDestroy(store) {
150+
// display new elements
151+
store.disposeOldHosts()
152+
delete store.disposeOldHosts;
153+
// anything you need done the component is removed
154+
}
155+
}

Diff for: templates/app/gulpfile.babel.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -299,8 +299,8 @@ gulp.task('jscs', () => {
299299
gulp.task('clean:tmp', () => del(['.tmp/**/*'], {dot: true}));
300300

301301
gulp.task('start:client', cb => {
302-
whenServerReady(() => {
303-
open('http://localhost:' + config.browserSyncPort);
302+
return require('./webpack.server').start(config.clientPort).then(() => {
303+
open(`http://localhost:${config.clientPort}`);
304304
cb();
305305
});
306306
});

Diff for: templates/app/server/config/environment/index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ var all = {
1919
// Root path of server
2020
root: path.normalize(`${__dirname}/../../..`),
2121

22-
// Browser-sync port
23-
browserSyncPort: process.env.BROWSER_SYNC_PORT || 3000,
22+
// dev client port
23+
clientPort: process.env.CLIENT_PORT || 3000,
2424

2525
// Server port
2626
port: process.env.PORT || <%= devPort %>,

Diff for: templates/app/server/config/express.js

-58
Original file line numberDiff line numberDiff line change
@@ -86,64 +86,6 @@ export default function(app) {
8686
}));
8787
}<% } %>
8888

89-
if(env === 'development') {
90-
const webpackDevMiddleware = require('webpack-dev-middleware');
91-
const stripAnsi = require('strip-ansi');
92-
const webpack = require('webpack');
93-
const makeWebpackConfig = require('../../webpack.make');
94-
const webpackConfig = makeWebpackConfig({ DEV: true });
95-
const compiler = webpack(webpackConfig);
96-
const browserSync = require('browser-sync').create();
97-
98-
app.use(cors({
99-
origin: true,
100-
credentials: true,
101-
}));
102-
103-
app.use(function(req, res, next) {
104-
res.setHeader('Access-Control-Allow-Origin', `http://localhost:${config.browserSyncPort}`);
105-
next();
106-
});
107-
108-
/**
109-
* Run Browsersync and use middleware for Hot Module Replacement
110-
*/
111-
browserSync.init({
112-
open: false,
113-
logFileChanges: false,
114-
proxy: `localhost:${config.port}`,
115-
ws: true,
116-
middleware: [
117-
webpackDevMiddleware(compiler, {
118-
noInfo: false,
119-
stats: {
120-
colors: true,
121-
timings: true,
122-
chunks: false
123-
}
124-
})
125-
],
126-
port: config.browserSyncPort,
127-
plugins: ['bs-fullscreen-message']
128-
});
129-
130-
/**
131-
* Reload all devices when bundle is complete
132-
* or send a fullscreen error message to the browser instead
133-
*/
134-
compiler.plugin('done', function(stats) {
135-
console.log('webpack done hook');
136-
if(stats.hasErrors() || stats.hasWarnings()) {
137-
return browserSync.sockets.emit('fullscreen:message', {
138-
title: "Webpack Error:",
139-
body: stripAnsi(stats.toString()),
140-
timeout: 100000
141-
});
142-
}
143-
browserSync.reload();
144-
});
145-
}
146-
14789
if(env === 'development' || env === 'test') {
14890
app.use(errorHandler()); // Error handler - has to be last
14991
}

Diff for: templates/app/webpack.make.js

+18-35
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use strict';
22
/*eslint-env node*/
3+
const _ = require('lodash');
34
var webpack = require('webpack');
45
var autoprefixer = require('autoprefixer');
56
var HtmlWebpackPlugin = require('html-webpack-plugin');
@@ -84,7 +85,7 @@ module.exports = function makeWebpackConfig(options) {
8485
modulesDirectories: [
8586
'node_modules'
8687
],
87-
extensions: ['', '.js', '.ts']
88+
extensions: ['.js', '.ts']
8889
};
8990
}
9091

@@ -110,22 +111,18 @@ module.exports = function makeWebpackConfig(options) {
110111

111112
// Initialize module
112113
config.module = {
113-
noParse: [
114-
path.join(__dirname, 'node_modules', 'zone.js', 'dist'),
115-
path.join(__dirname, 'node_modules', '@angular', 'bundles'),
116-
],
117114
rules: [{
118115
// JS LOADER
119116
// Reference: https://github.com/babel/babel-loader
120117
// Transpile .js files using babel-loader
121118
// Compiles ES6 and ES7 into ES5 code
122119
test: /\.js$/,
123-
use: {
124-
loader: 'babel',
120+
use: [{
121+
loader: 'babel-loader',
125122
options: {
126123
plugins: TEST ? ['istanbul'] : [],
127124
}
128-
},
125+
}].concat(DEV ? '@angularclass/hmr-loader' : []),
129126
include: [
130127
path.resolve(__dirname, 'client/'),
131128
path.resolve(__dirname, 'server/config/environment/shared.js'),
@@ -136,13 +133,13 @@ module.exports = function makeWebpackConfig(options) {
136133
// Reference: https://github.com/s-panferov/awesome-typescript-loader
137134
// Transpile .ts files using awesome-typescript-loader
138135
test: /\.ts$/,
139-
use: {
136+
use: [{
140137
loader: 'awesome-typescript-loader',
141138
<%_ if(filters.ts) { -%>
142139
options: {
143140
tsconfig: path.resolve(__dirname, 'tsconfig.client.json')
144141
},<% } %>
145-
},
142+
}].concat(DEV ? '@angularclass/hmr-loader' : []),
146143
include: [
147144
path.resolve(__dirname, 'client/')
148145
]
@@ -154,21 +151,21 @@ module.exports = function makeWebpackConfig(options) {
154151
// Pass along the updated reference to your code
155152
// You can add here any file extension you want to get copied to your output
156153
test: /\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)([\?]?.*)$/,
157-
use: 'file'
154+
use: 'file-loader'
158155
}, {
159156
<%_ if(filters.pug) { _%>
160157
// Pug HTML LOADER
161158
// Reference: https://github.com/willyelm/pug-html-loader
162159
// Allow loading Pug throw js
163160
test: /\.(jade|pug)$/,
164-
use: 'pug-html'
161+
use: 'pug-html-loader'
165162
}, {<% } %>
166163
<%_ if(filters.html) { _%>
167164
// HTML LOADER
168165
// Reference: https://github.com/webpack/raw-loader
169166
// Allow loading html through js
170167
test: /\.html$/,
171-
use: 'raw'
168+
use: 'raw-loader'
172169
}, {<% } %>
173170
// CSS LOADER
174171
// Reference: https://github.com/webpack/css-loader
@@ -183,16 +180,16 @@ module.exports = function makeWebpackConfig(options) {
183180
//
184181
// Reference: https://github.com/webpack/style-loader
185182
// Use style-loader in development for hot-loading
186-
? ExtractTextPlugin.extract('style', 'css?sourceMap!postcss')
183+
? ExtractTextPlugin.extract({fallbackLoader: 'style-loader', loader: ['css-loader', 'postcss-loader']})
187184
// Reference: https://github.com/webpack/null-loader
188185
// Skip loading css in test mode
189-
: 'null'
186+
: 'null-loader'
190187
}<% if(!filters.css) { %>, {
191188
<%_ if(filters.sass) { _%>
192189
// SASS LOADER
193190
// Reference: https://github.com/jtangelder/sass-loader
194191
test: /\.(scss|sass)$/,
195-
use: ['raw', 'sass'],
192+
use: ['raw-loader', 'sass-loader'],
196193
include: [
197194
path.resolve(__dirname, 'node_modules/bootstrap-sass/assets/stylesheets/*.scss'),
198195
path.resolve(__dirname, 'client')
@@ -201,7 +198,7 @@ module.exports = function makeWebpackConfig(options) {
201198
// LESS LOADER
202199
// Reference: https://github.com/
203200
test: /\.less$/,
204-
use: ['style', 'css', 'less'],
201+
use: ['style-loader', 'css-loader', 'less-loader'],
205202
include: [
206203
path.resolve(__dirname, 'node_modules/bootstrap/less/*.less'),
207204
path.resolve(__dirname, 'client/app/app.less')
@@ -210,7 +207,7 @@ module.exports = function makeWebpackConfig(options) {
210207
// Stylus LOADER
211208
// Reference: https://github.com/
212209
test: /\.styl$/,
213-
use: ['style', 'css', 'stylus'],
210+
use: ['style-loader', 'css-loader', 'stylus-loader'],
214211
include: [
215212
path.resolve(__dirname, 'node_modules/bootstrap-styl/bootstrap/*.styl'),
216213
path.resolve(__dirname, 'client/app/app.styl')
@@ -238,8 +235,9 @@ module.exports = function makeWebpackConfig(options) {
238235
// Reference: https://github.com/webpack/extract-text-webpack-plugin
239236
// Extract css files
240237
// Disabled when in test mode or not in build mode
241-
new ExtractTextPlugin('[name].[hash].css', {
242-
disable: !BUILD || TEST
238+
new ExtractTextPlugin({
239+
filename: '[name].[hash].css',
240+
disable: !BUILD || TEST,
243241
}),
244242

245243
new webpack.LoaderOptionsPlugin({
@@ -366,21 +364,6 @@ module.exports = function makeWebpackConfig(options) {
366364
config.debug = false;
367365
}
368366

369-
/**
370-
* Dev server configuration
371-
* Reference: http://webpack.github.io/docs/configuration.html#devserver
372-
* Reference: http://webpack.github.io/docs/webpack-dev-server.html
373-
*/
374-
config.devServer = {
375-
contentBase: './client/',
376-
stats: {
377-
modules: false,
378-
cached: false,
379-
colors: true,
380-
chunk: false
381-
}
382-
};
383-
384367
config.node = {
385368
global: true,
386369
process: true,

Diff for: templates/app/webpack.server.js

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
const webpack = require('webpack');
2+
const WebpackDevServer = require('webpack-dev-server');
3+
const config = require('./webpack.make')({ DEV: true });
4+
const appConfig = require('./server/config/environment');
5+
const devServerEntry = [`webpack-dev-server/client?http://localhost:${appConfig.clientPort}/`, 'webpack/hot/dev-server'];
6+
7+
config.entry.app = devServerEntry.concat(config.entry.app);
8+
9+
console.log(config.entry);
10+
console.log(config.entry.app);
11+
12+
const compiler = webpack(config);
13+
14+
export const server = new WebpackDevServer(compiler, {
15+
contentBase: './client/',
16+
17+
hot: true,
18+
19+
historyApiFallback: true,
20+
21+
stats: {
22+
modules: false,
23+
cached: false,
24+
colors: true,
25+
chunk: false
26+
},
27+
quiet: false,
28+
noInfo: false,
29+
30+
proxy: {
31+
'/api': {
32+
target: 'http://localhost:9000',
33+
secure: false,
34+
},
35+
'/auth': {
36+
target: 'http://localhost:9000',
37+
secure: false,
38+
},
39+
'/socket.io': {
40+
target: 'http://localhost:9000',
41+
secure: false,
42+
},
43+
},
44+
});
45+
46+
/**
47+
* Starts the dev server
48+
* @returns {Promise}
49+
*/
50+
export function start() {
51+
return new Promise(resolve => {
52+
server.listen(appConfig.clientPort, resolve);
53+
});
54+
}

0 commit comments

Comments
 (0)