Exécuter un serveur node express en utilisant webpack-dev-server

j'utilise webpack pour exécuter mon frontal react avec succès en utilisant la configuration suivante:

{
    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']
                }
            }
        ]
    }
}

j'essaie de mettre en place un noeud.js express backend aussi, et j'aimerais l'exécuter via webpack aussi, de sorte que j'ai un seul serveur qui exécute à la fois le backend et frontend, et parce que je veux utiliser babel pour transférer mon javascript.

j'ai fait un testserver rapide ressemblant à ceci:

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');
});

Si I Lancez ceci avec node index.js et ouvrez mon navigateur sur localhost:3000 il imprime " Hello world from Express!!". So far So good. Puis j'ai essayé de créer une config web-pack pour elle:

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'
            }
        ]
    }
}   

quand j'exécute la commande webpack-dev-server il démarre avec succès (semble-t-il). Cependant, si je vais à mon navigateur sur localhost:3000 maintenant, il dit juste que la page Web n'est pas disponible, tout comme lorsque le serveur n'est pas en cours d'exécution du tout.

je suis très nouveau à la fois noeud et webpack, donc soit j'ai fait une petite erreur quelque part, ou que je suis loin ;)

47
demandé sur Øyvind Bråthen 2016-02-05 23:53:05

3 réponses

webpack-dev-server est idéal pour le développement côté client, mais il ne déploiera pas D'api Express ou d'middleware. Ainsi, en cours de développement, je recommande l'exécution de deux serveurs distincts: un pour le client et un pour votre api côté serveur.

Nodemon npm install --save-dev nodemon est un bon serveur de développement d'arrière-plan qui vous donnera un redéploiement à chaud de votre api, ou vous pouvez simplement utiliser express et redémarrer lorsque vous apportez des modifications. En production, le client et l'api seront toujours servis par même serveur express.

définit un événement lifecycle pour nodemon et webpack-dev-server dans votre package.json pour faciliter leur démarrage (exemple: npm run dev-server ).

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

Ou, pour exécuter exprimer directement à partir d'un nœud:

"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');
});

Note: le serveur api doit utiliser un port différent de celui de webpack-dev-server.

et enfin dans votre webpack-dev-config vous besoin d'utiliser un proxy pour rediriger les appels vers votre api pour le nouveau port:

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
  })
]

**points Bonus pour avoir un seul script pour démarrer et tuer les deux

64
répondu perilandmishap 2017-04-04 12:57:37

de vos questions ici et ici , il semble que vous utilisez ReactJS avec ES6. J'ai fait face à la même question, et voici comment je l'ai abordé -

  1. ont plusieurs points d'entrée pour votre demande

en particulier, vous pouvez mettre tous vos fichiers fournisseurs comme JQuery, React etc en un seul morceau. De cette façon, vos fichiers fournisseurs resteront les mêmes, même si vous modifier votre source de fichiers. Vous pouvez ajouter cette ligne à votre configuration webpack

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

utilisez le CommonsChunkPlugin pour que webpack détermine le code/les modules que vous utilisez le plus, et mettez-le dans un paquet séparé pour être utilisé n'importe où dans votre application.

plugins: [
    new webpack.optimize.CommonsChunkPlugin('vendors', 'dist/js/vendors.js', Infinity),
]
  1. "

Exécuter npm install react-hot-loader --save-dev . Assurez-vous d'avoir installé webpack-dev-server en premier.

alors vous devez changer vos chargeurs à ceci -

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

        },{ 
           loader: 'babel',
            query: {
                presets: ['react', 'es2015']
            },
            include: path.join(__dirname, 'public')
        }, 
    ]

assurez-vous que React Hot Loader vient avant Babel dans le tableau des chargeurs. Aussi assurez-vous que vous avez include: path.join(__dirname, 'public') pour éviter de traiter node_modules, ou vous pouvez obtenir une erreur comme ceci -

Uncaught TypeError: Cannot read property 'NODE_ENV' of undefined

  1. Modifications à vos balises de script dans votre index.html page

si votre html a quelque chose comme ça -

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

changez ceci pour pointer vers votre proxy 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. Exécuter webpack-dev-server --hot --inline ,

attendez la fin du bundling, puis appuyez sur http://localhost:3000 (votre port serveur express) dans votre navigateur.

si vous rencontrez toutes les erreurs, vous pourriez trouver ce guide de dépannage très utile.

espérons que cela aide, et vous pouvez jeter un oeil à la configuration webpack pour mon projet ici

7
répondu booleanhunter 2017-05-23 12:02:29

depuis webpack-dev-server est juste un petit serveur express Avec compilation sur changement et recharge à chaud.

donc, si vous avez déjà un serveur express pour L'API backend, fusionnez simplement le compile on change and hot reload dans votre serveur express.

Puis, après avoir jeter un oeil à la package.json de webpack-dev-serveur , je trouve que la clé est juste 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!'))

ainsi, lorsque vous exécutez votre serveur BE, Il compilera toutes les choses en utilisant webpack, et guetter les changements, LOL ~

ajouter aussi webpack-hot-middleware pour la fonction de rechargement à chaud, voir remplacement de Module à chaud

2
répondu Shawn Wang 2018-01-16 05:16:27