我正在使用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都很陌生,所以要么我在某个地方犯了一个小错误,要么我离开了;)
答案 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-server的package.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。我遇到了同样的问题,这就是我如何处理它 -
特别是您可以将所有供应商文件(如JQuery,React等)放入一个块中。这样,即使修改源文件,您的供应商文件也将保持不变。您可以将此行添加到您的webpack配置
entry: {
vendors: ['react','reactDom','jquery'] //Any other libraries
}
使用CommonsChunkPlugin
让webpack确定您最常使用的代码/模块,并将其放在一个单独的包中,以便在应用程序的任何位置使用。
plugins: [
new webpack.optimize.CommonsChunkPlugin('vendors', 'dist/js/vendors.js', Infinity),
]
运行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
index.html
页面中的脚本标记如果你的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>
webpack-dev-server --hot --inline
,等待捆绑完成,然后在浏览器中点击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 上。热模块替换也有效!