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

Øyv*_*hen 58 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']
                }
            }
        ]
    }
}
Run Code Online (Sandbox Code Playgroud)

我也试图建立一个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');
});
Run Code Online (Sandbox Code Playgroud)

如果我运行它node index.js并打开我的浏览器,localhost:3000它会打印出"Hello Express from Express !!".到现在为止还挺好.然后我尝试为它创建一个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'
            }
        ]
    }
}   
Run Code Online (Sandbox Code Playgroud)

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

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

per*_*hap 88

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

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

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

"scripts": {
   "start": "webpack --progress --colors",
   "dev-server": "nodemon ./server.js localhost 8080",
   "dev-client": "webpack-dev-server --port 3000",
}
Run Code Online (Sandbox Code Playgroud)

或者,直接从节点运行express:

"scripts": {
   "start": "webpack --progress --colors",
   "dev-server": "node dev-server.js",
   "dev-client": "webpack-dev-server --port 3000",
}
Run Code Online (Sandbox Code Playgroud)
// 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');
});
Run Code Online (Sandbox Code Playgroud)

注意: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
  })
]
Run Code Online (Sandbox Code Playgroud)

**使用单个脚本启动并杀死两者的加分点

  • 此设置无法解决任何CORS问题.从一个端口向另一个端口发出请求是跨域访问,如果不处理则会引发错误.(使用镀铬工具检查) (5认同)
  • 实际上@stevematdavies,因为它使用代理,CORS应该不是一个问题,对吧? (3认同)
  • @Sequential 不确定我理解这个问题。您应该为生产和开发使用相同的文件结构,这是一个很好的一般规则,可以使您的开发环境尽可能接近/方便生产。Express 将同时服务 API 和客户端。webpack-dev-server 不会,但我们想用它来开发,因为热重载非常棒。 (2认同)
  • @zehelvion ma'am其实,但谢谢! (2认同)

Sha*_*ang 15

因为webpack-dev-server只是一个小型的快速服务器,可以在更改和热重载时进行编译.

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

再看看在后package.json的WebPack-dev的服务器,我觉得关键是刚刚 的WebPack-DEV-中间件

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!'))
Run Code Online (Sandbox Code Playgroud)

因此,当您运行BE服务器时,它将使用webpack编译所有内容,并注意更改,LOL~

另外,添加webpack-hot-middleware以进行热重装功能,请参阅热模块更换

  • 赞成,我实际上更喜欢这个答案而不是最高投票的答案,因为它以更简洁的方式整合了我的后端和前端。我的实现略有不同,但在精神上相似。我有 server.js do `module.exports = app` 和一个包装器 `dev-start.js` 脚本,它将 webpack 中间件添加到类似于上面的代码的返回对象。这样我就直接在生产中生成了 server.js,除非我在开​​发中,否则这个 webpack 逻辑甚至不会被加载。 (3认同)

boo*_*ter 7

从您在这里和这里的问题看来,您正在使用ReactJS和ES6.我遇到了同样的问题,这就是我如何处理它 -

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

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

entry: {
    vendors: ['react','reactDom','jquery'] //Any other libraries
}
Run Code Online (Sandbox Code Playgroud)

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

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

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')
        }, 
    ]
Run Code Online (Sandbox Code Playgroud)

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

Uncaught TypeError: Cannot read property 'NODE_ENV' of undefined

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

如果你的HTML有这样的东西 -

<script src="/dist/js/vendors.js"></script>
<script src="/dist/js/app.bundle.js"></script>
Run Code Online (Sandbox Code Playgroud)

将其更改为指向您的webpack-dev服务器代理 -

<script src="http://localhost:8080/dist/js/vendors.js"></script>
<script src="http://localhost:8080/dist/js/app.bundle.js"></script>
Run Code Online (Sandbox Code Playgroud)
  1. webpack-dev-server --hot --inline,

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

如果您遇到任何错误,您可能会发现此故障排除指南非常有用.

希望这会有所帮助,您可以在这里查看我的项目的webpack设置

  • 也许我错了,但这不是前端应用程序的设置吗?如果您只想提供后端(快速)应用程序,该怎么办? (6认同)
  • >哦,但我确实想使用Webpack作为后端.打字稿支持,捆绑,缩小,资源加载器等等东西都可以与Webpack一起使用 - 也可以在后端使用.最后我使用nodemon来运行Webpack生成的包..它完美无缺地工作.. (6认同)

小智 5

刚刚面临同样的问题并提出了另一个解决方案(稍后找到了更多有关它的信息,但这里是)。

不要使用 webpack-dev-server,而是使用webpack --watch命令,以便在更改时再次编译文件。一旦 dist(或任何其他已编译的文件文件夹)上的文件更新,您可以设置在 dist 文件夹上运行 nodemon 并仅监视 dist 文件。

这样,就可以像在生产环境(或类似环境)中一样运行 Express 服务器并为前端提供服务,并从快速重新加载中受益。

这里有一些结合 webpack watch 和 nodemon 的解决方案的链接。

我的脚本部分此时是这样的(我正在使用 run-all 解决方案):

  "scripts": {
    "serve": "npm-run-all --parallel serve:webpack serve:nodemon",
    "serve:webpack": "webpack --progress --colors --watch",
    "serve:nodemon": "nodemon ./dist/app.js --watch dist"
  },
Run Code Online (Sandbox Code Playgroud)