使用webpack-dev-server运行节点表达服务器

时间:2016-02-05 20:53:06

标签: node.js express webpack webpack-dev-server

我正在使用webpack使用以下配置成功运行我的反应前端:

{
    name: 'client',
    entry: './scripts/main.js',
    output: {
        path: __dirname,
        filename: 'bundle.js'  
    },
    module: {
        loaders: [
            {
                test: /.jsx?$/,
                loader: 'babel-loader',
                exclude: /node_modules/,
                query:{
                    presets: ['es2015', 'react', 'stage-2']
                }
            }
        ]
    }
}

我正在尝试建立一个node.js表达后端,并希望通过webpack运行它,这样我就有一台服务器同时运行后端和前端,因为我想使用babel转换我的javascript。

我做了一个快速的测试服务器,看起来像这样:

var express = require('express');
console.log('test');

var app = express();

app.get('/', function(req, res){
    res.send("Hello world from Express!!");
});

app.listen(3000, function(){
    console.log('Example app listening on port 3000');
});

如果我使用node index.js运行此操作并在localhost:3000上打开浏览器,则会打印出来自Express !!的“Hello world”。到现在为止还挺好。然后我尝试为它创建一个web-pack配置:

var fs = require('fs');
var nodeModules = {};
fs.readdirSync('node_modules')
    .filter(function(x) {
        return ['.bin'].indexOf(x) === -1;
    })
    .forEach(function(mod) {
        nodeModules[mod] = 'commonjs ' + mod;    
});

module.exports = [
{
    name: 'server',
    target: 'node',
    entry: './index.js',
    output: {
        path: __dirname,
        filename: 'bundle.js'
    },
    externals: nodeModules,
    module: {
        loaders: [
            { 
                test: /\.js$/,
                loaders: [
                    'babel-loader'
                ]
            },
            {
                test:  /\.json$/, 
                loader: 'json-loader'
            }
        ]
    }
}   

当我运行命令webpack-dev-server时,它会成功启动(似乎)。但是,如果我现在在localhost:3000上访问我的浏览器,它就会说网页不可用,就像服务器根本没有运行一样。

我对node和webpack都很陌生,所以要么我在某个地方犯了一个小错误,要么我离开了;)

5 个答案:

答案 0 :(得分:82)

Webpack-dev-server非常适合客户端开发,但不会部署Express api或中间件。所以在开发中我建议运行两个独立的服务器:一个用于客户端,一个用于服务器端api。

Nodemon npm install --save-dev nodemon是一个很好的后端开发服务器,可以为您提供热重新部署的api,或者您可以在进行更改时使用快速重启。在生产中,客户端和api仍将由同一个快速服务器提供服务。

package.json中为nodemon和webpack-dev-server设置生命周期事件,以便轻松启动它们(例如:npm run dev-server)。

"scripts": {
   "start": "webpack --progress --colors",
   "dev-server": "nodemon ./server.js localhost 8080",
   "dev-client": "webpack-dev-server --port 3000",
}

或者,直接从节点运行表达:

"scripts": {
   "start": "webpack --progress --colors",
   "dev-server": "node dev-server.js",
   "dev-client": "webpack-dev-server --port 3000",
}
// dev-server.js
const express = require('express');
const app = express();
// Import routes
require('./_routes')(app);   // <-- or whatever you do to include your API endpoints and middleware
app.set('port', 8080);
app.listen(app.get('port'), function() {
    console.log('Node App Started');
});

注意:api服务器必须使用与webpack-dev-server不同的端口。

最后在你的webpack-dev-config中,你需要使用代理将你的api调用重定向到新端口:

devServer: {
  historyApiFallback: true,
  hot: true,
  inline: true,

  host: 'localhost', // Defaults to `localhost`
  port: 3000, // Defaults to 8080
  proxy: {
    '^/api/*': {
      target: 'http://localhost:8080/api/',
      secure: false
    }
  }
},
// and separately, in your plugins section
plugins: [
  new webpack.HotModuleReplacementPlugin({
    multiStep: true
  })
]

**使用单个脚本启动并杀死两个

的奖励积分

答案 1 :(得分:11)

由于webpack-dev-server只是一个小型快速服务器,具有编译更改和热重新加载。

因此,如果您已经有一个用于后端API的快速服务器,只需将compile on change and hot reload合并到您的快速服务器中。

然后看一下webpack-dev-serverpackage.json,我发现关键就是 webpack-dev-middleware

const express = require('express'); //your original BE server
const app = express();

const webpack = require('webpack');
const middleware = require('webpack-dev-middleware'); //webpack hot reloading middleware
const compiler = webpack({ .. webpack options .. }); //move your `devServer` config from `webpack.config.js`


app.use(middleware(compiler, {
  // webpack-dev-middleware options
}));

app.listen(3000, () => console.log('Example app listening on port 3000!'))

所以,当你运行你的BE服务器时,它将使用webpack编译所有的东西,并注意变化,LOL~

另外,为热重新加载功能添加webpack-hot-middleware,请参阅Hot Module Replacement

答案 2 :(得分:7)

根据您的问题和here,您似乎正在使用带有ES6的ReactJS。我遇到了同样的问题,这就是我如何处理它 -

  1. 为您的应用程序提供多个入口点

  2. 特别是您可以将所有供应商文件(如JQuery,React等)放入一个块中。这样,即使修改源文件,您的供应商文件也将保持不变。您可以将此行添加到您的webpack配置

    entry: {
        vendors: ['react','reactDom','jquery'] //Any other libraries
    }
    

    使用CommonsChunkPlugin让webpack确定您最常使用的代码/模块,并将其放在一个单独的包中,以便在应用程序的任何位置使用。

    plugins: [
        new webpack.optimize.CommonsChunkPlugin('vendors', 'dist/js/vendors.js', Infinity),
    ]
    
    1. 使用React Hot Loader

    2. 运行npm install react-hot-loader --save-dev。确保先安装webpack-dev-server

      然后你需要将你的加载器更改为 -

      loaders: [
              { 
                  test: /\.jsx?$/, 
                  loaders: ['react-hot'],
                  include: path.join(__dirname, 'public')
      
              },{ 
                 loader: 'babel',
                  query: {
                      presets: ['react', 'es2015']
                  },
                  include: path.join(__dirname, 'public')
              }, 
          ]
      

      确保React Hot Loader在加载器阵列中位于Babel之前。还要确保你有include: path.join(__dirname, 'public')以避免处理node_modules,否则你可能会收到这样的错误 -

      Uncaught TypeError: Cannot read property 'NODE_ENV' of undefined

      1. 修改index.html页面中的脚本标记

      2. 如果你的html有这样的东西 -

        <script src="/dist/js/vendors.js"></script>
        <script src="/dist/js/app.bundle.js"></script>
        

        将其更改为指向您的webpack-dev-server代理 -

        <script src="http://localhost:8080/dist/js/vendors.js"></script>
        <script src="http://localhost:8080/dist/js/app.bundle.js"></script>
        
        1. 运行webpack-dev-server --hot --inline

        2. 等待捆绑完成,然后在浏览器中点击http://localhost:3000(您的快速服务器端口)。

          如果您遇到任何错误,您会发现此troubleshooting guide非常有用。

          希望这会有所帮助,您可以查看我的项目here

          的webpack设置

答案 3 :(得分:1)

正面临着同样的问题,并提出了另一种解决方案(稍后会找到更多有关此问题的信息,但这就是这里)。

使用webpack --watch命令代替使用webpack-dev-server,以便在更改后重新编译文件。在dist(或任何其他编译文件的文件夹)上更新文件后,您可以设置为在dist文件夹上运行nodemon并仅查看dist文件。

通过这种方式,可以像在生产环境(或某种环境)中那样使Express服务器运行并为前端服务,并从快速重装中受益。

a link和一些解决方案结合了webpack watch和nodemon。

此刻我的脚本部分是这样的(我正在使用全部解决方案):

  "scripts": {
    "serve": "npm-run-all --parallel serve:webpack serve:nodemon",
    "serve:webpack": "webpack --progress --colors --watch",
    "serve:nodemon": "nodemon ./dist/app.js --watch dist"
  },

答案 4 :(得分:0)

我发现这是一个非常简单的解决方案,适用于 create-react-app,您只想使用 npm start 来启动 webpack-dev-server 并且您不能乱用 webpack配置。只需在 Express 中使用 http-proxy-middleware 将服务器本身不处理的所有请求代理到 webpack-dev-server:

import express from "express"
import { createProxyMiddleware } from "http-proxy-middleware"
const app = express()

// Put your web APIs here, for example:
app.get("/hello", (req, res) => {
   res.send("Hello World")
})

...

// This goes after all your other routes:
if (!isProduction) {
   app.use("*", createProxyMiddleware({ target: "http://127.0.0.1:3000", ws: true }))
}

app.listen(5000)

注意 1:为了简单起见,我没有使用 HTTPS。 (使用环境变量 HTTPS=false 让 webpack-dev-server 使用 HTTP。)

注意 2:您只想在开发模式下创建代理 - 在生产中,您可能会使用 express.static 来为您编译的单页应用提供服务。

在您的 React 项目上运行 npm start 并启动您的 Express 服务器。然后(使用示例代码中的端口号)浏览到 http://localhost:5000。您将看到您的 React 前端,它将能够将 API 请求发送到您的 Express 服务器,所有这些都在端口 5000 上。热模块替换也有效!