2016-09-14 97 views
2

我正在使用Webpack和HMR开发我的Angular 2应用程序。在这个阶段有一个静态的应用程序,与后端没有任何交互。所有数据都是静态的虚拟数据。Angular 2,Webpack,Express,HMR

我已经到了开始添加express/node后端的时候了,所以我可以与数据库进行交互,但是我不想失去HMR功能。

是否有可能设置这让:

  1. 我可以用快递和玉从服务节点的角2个应用程序。
  2. 我对Angular 2应用程序进行了更改,HMR启动并将代码热插入浏览器窗口。

目前我的webpack设置分为三个文件(dev,prod,common)。我在下面的开发和通用文件,因为他们是最相关的。

启动命令

webpack-dashboard -- webpack-dev-server --inline --hot --progress --port 8080 

webpack.dev.js

var webpackMerge = require('webpack-merge'); 
var commonConfig = require('./webpack.common.js'); 
var helpers = require('./helpers'); 

module.exports = webpackMerge(commonConfig, { 
    devtool: 'cheap-module-eval-source-map', 

    output: { 
     path: helpers.root('dist'), 
     publicPath: 'http://localhost:8080/', 
     filename: '[name].js', 
     chunkFilename: '[id].chunk.js' 
    }, 

    devServer: { 
     historyApiFallback: true, 
     stats: 'minimal' 
    } 
}); 

webpack.common.js

var webpack = require('webpack'); 
var HtmlWebpackPlugin = require('html-webpack-plugin'); 
var helpers = require('./helpers'); 

module.exports = { 
    entry: { 
    'styles': './src/styles/main.scss', 
    'polyfills': './src/polyfills.ts', 
    'vendor': './src/vendor.ts', 
    'app': './src/main.ts' 

    }, 

    resolve: { 
    extensions: ['', '.js', '.ts', 'scss'] 
    }, 

    module: { 
    loaders: [ 
     { 
     test: /\.ts$/, 
     loaders: ['ts', 'angular2-template-loader'] 
     }, 
     { 
     test: /\.html$/, 
     loader: 'html' 
     }, 
     { 
     test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/, 
     loader: 'file?name=assets/[name].[hash].[ext]' 
     } 
     , 
     { 
     test: /\.scss$/, 
     loaders: ['style', 'css', 'sass'] 
     } 

    ] 
    }, 

    plugins: [ 
    new webpack.optimize.CommonsChunkPlugin({ 
     name: ['app', 'vendor', 'polyfills', 'styles'] 
    }), 

    new HtmlWebpackPlugin({ 
     template: 'src/index.html' 
    }) 
    ] 
}; 

的package.json

{ 
    "name": "Raceloop", 
    "version": "1.0.0", 
    "scripts": { 
    "start": "webpack-dashboard -- webpack-dev-server --inline --hot --progress --port 8080", 
    "build": "rimraf dist && webpack --config config/webpack.prod.js --progress --profile --bail", 
    "postinstall": "typings install", 
    "typings": "typings" 
    }, 
    "dependencies": { 
    "@angular/common": "2.0.0-rc.6", 
    "@angular/compiler": "2.0.0-rc.6", 
    "@angular/core": "2.0.0-rc.6", 
    "@angular/forms": "2.0.0-rc.6", 
    "@angular/http": "2.0.0-rc.6", 
    "@angular/platform-browser": "2.0.0-rc.6", 
    "@angular/platform-browser-dynamic": "2.0.0-rc.6", 
    "@angular/router": "^3.0.0-rc.2", 
    "@angular2-material/button": "^2.0.0-alpha.8-1", 
    "@angular2-material/button-toggle": "^2.0.0-alpha.8-1", 
    "@angular2-material/card": "^2.0.0-alpha.8-1", 
    "@angular2-material/checkbox": "^2.0.0-alpha.8-1", 
    "@angular2-material/core": "^2.0.0-alpha.8-1", 
    "@angular2-material/grid-list": "^2.0.0-alpha.8-1", 
    "@angular2-material/icon": "^2.0.0-alpha.8-1", 
    "@angular2-material/input": "^2.0.0-alpha.8-1", 
    "@angular2-material/list": "^2.0.0-alpha.8-1", 
    "@angular2-material/menu": "^2.0.0-alpha.8-1", 
    "@angular2-material/progress-bar": "^2.0.0-alpha.8-1", 
    "@angular2-material/progress-circle": "^2.0.0-alpha.8-1", 
    "@angular2-material/radio": "^2.0.0-alpha.8-1", 
    "@angular2-material/sidenav": "^2.0.0-alpha.8-1", 
    "@angular2-material/slide-toggle": "^2.0.0-alpha.8-1", 
    "@angular2-material/slider": "^2.0.0-alpha.8-1", 
    "@angular2-material/tabs": "^2.0.0-alpha.8-1", 
    "@angular2-material/toolbar": "^2.0.0-alpha.8-1", 
    "@angular2-material/tooltip": "^2.0.0-alpha.8-1", 
    "@ngrx/core": "1.1.0", 
    "@ngrx/effects": "2.0.0-beta.3", 
    "@ngrx/store": "2.1.2", 
    "@types/hammerjs": "^2.0.32", 
    "angular2-apollo": "^0.4.5", 
    "apollo-client": "^0.4.14", 
    "core-js": "2.4.1", 
    "hammerjs": "2.0.8", 
    "immutable": "3.8.1", 
    "moment": "^2.15.0", 
    "reflect-metadata": "0.1.8", 
    "rxjs": "5.0.0-beta.11", 
    "typed-immutable-record": "0.0.5", 
    "zone.js": "0.6.17" 
    }, 
    "devDependencies": { 
    "angular2-template-loader": "0.5.0", 
    "codelyzer": "0.0.28", 
    "css-loader": "0.25.0", 
    "extract-text-webpack-plugin": "1.0.1", 
    "file-loader": "0.9.0", 
    "html-loader": "0.4.3", 
    "html-webpack-plugin": "2.22.0", 
    "json-loader": "0.5.4", 
    "node-sass": "^3.9.3", 
    "null-loader": "0.1.1", 
    "raw-loader": "0.5.1", 
    "rimraf": "2.5.4", 
    "sass-loader": "^4.0.2", 
    "style-loader": "0.13.1", 
    "ts-loader": "0.8.2", 
    "tslint": "^3.15.1", 
    "typescript": "2.1.0-dev.20160903", 
    "typings": "1.3.3", 
    "webpack": "2.1.0-beta.21", 
    "webpack-dashboard": "0.1.8", 
    "webpack-dev-server": "2.1.0-beta.3", 
    "webpack-merge": "0.14.1", 
    "worker-loader": "0.7.1" 
    } 
} 

回答

0

使用的WebPack热中间件插件,它实际上是相当简单的。

webpack.express.config.js

var webpack = require('webpack'); 
var HtmlWebpackPlugin = require('html-webpack-plugin'); 
var ExtractTextPlugin = require('extract-text-webpack-plugin'); 
var helpers = require('./helpers'); 
var hotMiddlewareScript = 'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000&reload=true'; 

module.exports = { 
    context: __dirname, 
    // Include the hot middleware with each entry point 
    entry: { 
     // Add the client which connects to our middleware 
     'styles': ['../src/styles/main.scss', hotMiddlewareScript], 
     'polyfills': ['../src/app/polyfills.ts', hotMiddlewareScript], 
     'vendor': ['../src/app/vendor.ts', hotMiddlewareScript], 
     'manager': ['../src/app/main-manager.ts', hotMiddlewareScript], 
     'authenticator': ['../src/app/main-authenticator.ts', hotMiddlewareScript] 
    }, 
    output: { 
     path: __dirname, 
     publicPath: '/', 
     filename: '[name].js', 
     chunkFilename: '[id].chunk.js' 
    }, 
    resolve: { 
     extensions: ['', '.js', '.ts', 'scss'] 
    }, 
    module: { 
     loaders: [ 
      { 
       test: /\.ts$/, 
       loaders: ['ts', 'angular2-template-loader'] 
      }, 
      { 
       test: /\.html$/, 
       loader: 'html' 
      }, 
      { 
       test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/, 
       loader: 'file?name=assets/[name].[hash].[ext]' 
      }, 
      { 
       test: /\.scss$/, 
       loaders: ['style', 'css', 'sass'] 
      } 

     ] 
    }, 
    devtool: 'cheap-module-eval-source-map', 
    plugins: [ 
     new webpack.optimize.CommonsChunkPlugin({ 
      name: ['mainapp', 'vendor', 'polyfills', 'styles'] 
     }), 

     //new HtmlWebpackPlugin({ 
     // template: '../src/index.html' 
     //}), 
     new webpack.optimize.OccurrenceOrderPlugin(), 
     new webpack.HotModuleReplacementPlugin(), 
     new webpack.NoErrorsPlugin() 
    ], 
}; 

Server.Js

/// <reference path="../typings/index.d.ts" /> 

let http = require('http'); 
let express = require('express'); 
let morgan = require('morgan'); 


let app = express(); 
app.use(morgan('short')); 
app.set('view engine', 'pug'); 

// ************************************ 
// This is the real meat of the example 
// ************************************ 
(function() { 

    let webpack = require('webpack'); 
    let webpackDevMiddleWare = require('webpack-dev-middleware'); 
    let webpackHotMiddleWare = require('webpack-hot-middleware'); 

    // Step 1: Create & configure a webpack compiler 
    let webpackConfig = require(process.env.WEBPACK_CONFIG ? process.env.WEBPACK_CONFIG : '../webpack.config'); 
    let compiler = webpack(webpackConfig); 

    // Step 2: Attach the dev middleware to the compiler & the server 
    app.use(webpackDevMiddleWare(compiler, { 
     noInfo: true, 
     publicPath: webpackConfig.output.publicPath 
    })); 

    // Step 3: Attach the hot middleware to the compiler & the server 
    app.use(webpackHotMiddleWare(compiler, { 
     log: console.log, 
     path: '/__webpack_hmr', 
     heartbeat: 10 * 1000 
     })); 
})(); 

// Do anything you like with the rest of your express application. 

app.get("/", function(req, res) { 
    res.sendFile(__dirname + '/app/index-manager.html'); 
}); 
app.get("/multientry", function(req, res) { 
    res.sendFile(__dirname + '/app/index-multientry.html'); 
}); 

if (require.main === module) { 
    let server = http.createServer(app); 
    server.listen(process.env.PORT || 4200, function() { 
     console.log("Listening on %j", server.address()); 
    }); 
}