प्रतिक्रिया-राउटर से प्रवेश बिंदुओं की अनुमति देने के लिए वेबपैक-डेव-सर्वर के लिए कैसे अनुमति दें


117

मैं एक ऐप बना रहा हूं, जो प्रतिक्रिया-राउटर के साथ-साथ विकास में वेबपैक-देव-सर्वर का उपयोग करता है।

ऐसा लगता है कि वेबपैक-देव-सर्वर इस धारणा के आसपास बनाया गया है कि आपके पास एक स्थान (यानी "/") पर एक सार्वजनिक प्रवेश बिंदु होगा, जबकि प्रतिक्रिया-राउटर असीमित मात्रा में प्रवेश बिंदुओं की अनुमति देता है।

मैं वेबपैक-देव-सर्वर के लाभों को चाहता हूं, विशेष रूप से हॉट रीलोडिंग फीचर जो उत्पादकता के लिए बहुत अच्छा है, लेकिन मैं अभी भी प्रतिक्रिया-राउटर में निर्धारित मार्गों को लोड करने में सक्षम होना चाहता हूं।

कोई इसे ऐसे कैसे लागू कर सकता है कि वे एक साथ काम करें? क्या आप इस तरह से अनुमति देने के लिए वेबपैक-देव-सर्वर के सामने एक एक्सप्रेस सर्वर चला सकते हैं?


मेरे पास यहां किसी चीज़ का बेहद हैकरी संस्करण है, लेकिन यह नाजुक है और केवल सरल मार्गों को मिलान करने की अनुमति देता है: github.com/natew/react-base (मेक-वेबपैक-कॉन्फ़िगरेशन देखें) और (ऐप / मार्ग.जेएस)
नाथन वीनरट

क्या आपने इस समस्या को हल करने के लिए प्रबंधन किया है नाथन? यदि हां, तो कैसे? कृपया मेरे सवाल का जवाब देने की कोशिश करें यहां stackoverflow.com/questions/31091702/… । धन्यवाद..!
सूडोप्लज

जवाबों:


69

मैंने इसे प्राप्त करने के लिए एक प्रॉक्सी स्थापित किया है:

आपके पास एक नियमित एक्सप्रेस वेबसर्वर है जो किसी भी मार्ग पर index.html का काम करता है, सिवाय इसके कि कोई संपत्ति मार्ग हो। यदि यह एक परिसंपत्ति है, तो अनुरोध वेब-देव-सर्वर से जुड़ा हुआ है

आपकी प्रतिक्रिया गर्म प्रविष्टि अभी भी सीधे वेबपैक देव सर्वर पर इंगित करेगी, इसलिए हॉट रीलोडिंग अभी भी काम करता है।

मान लें कि आप 8081 पर webpack-dev-server चलाते हैं और 8080 पर आपका प्रॉक्सी। आपका server.js फ़ाइल इस तरह दिखेगा:

"use strict";
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var config = require('./make-webpack-config')('dev');

var express = require('express');
var proxy = require('proxy-middleware');
var url = require('url');

## --------your proxy----------------------
var app = express();
## proxy the request for static assets
app.use('/assets', proxy(url.parse('http://localhost:8081/assets')));

app.get('/*', function(req, res) {
    res.sendFile(__dirname + '/index.html');
});


# -----your-webpack-dev-server------------------
var server = new WebpackDevServer(webpack(config), {
    contentBase: __dirname,
    hot: true,
    quiet: false,
    noInfo: false,
    publicPath: "/assets/",

    stats: { colors: true }
});

## run the two servers
server.listen(8081, "localhost", function() {});
app.listen(8080);

अब अपनी प्रविष्टि को वेबपैक कॉन्फिगर में इस तरह बनाएँ:

 entry: [
     './src/main.js',
     'webpack/hot/dev-server',
     'webpack-dev-server/client?http://localhost:8081'
 ]

हॉट्रेलोड के लिए 8081 पर सीधे कॉल पर ध्यान दें

यह भी सुनिश्चित करें कि आप output.publicPathविकल्प के लिए एक पूर्ण यूआरएल पास करते हैं :

 output: {
     publicPath: "http://localhost:8081/assets/",
     // ...
 }

1
अरे, यह बहुत बढ़िया है। मैं वास्तव में इस सेटअप पर कुछ समय पहले पहुंचा था और एक उत्तर पोस्ट करने जा रहा था, लेकिन मुझे लगता है कि आपने एक बेहतर काम किया है।
नाथन वीनरर्ट

1
एक प्रश्न, असंबंधित का एक प्रकार तो मैं एक नया प्रश्न खोल सकता हूं यदि आवश्यकता हो लेकिन मैं ध्यान देता हूं कि अब वेबपैक देव सर्वर से कंसोल आउटपुट स्ट्रीम नहीं किया गया है। इससे पहले, आप इसे संकलित करके देख सकते हैं और गड़बड़ी को बढ़ाते हुए देख सकते हैं, अब यह संकलन के बाद आउटपुट को ब्लॉक करता है।
नाथन वीनरर्ट

अच्छा किया। ठीक ऐसा ही होना चाहिए। मैंने output.publicPathविकल्प के बारे में एक नोट जोड़ा , जो एक पूर्ण यूआरएल भी होना चाहिए।
टोबियास के।

5
इसके बजाय बिल्ट-इन वेबपैक प्रॉक्सी का उपयोग करना आसान होगा । इस प्रकार आप स्वयं सर्वर में हस्तक्षेप नहीं करते हैं, आप सर्वर को शुद्ध छोड़ देते हैं । इसके बजाय, आप वेबपैक कॉन्फिगर के अलावा थोड़ा (3-5 लाइन) काम करते हैं। इसके लिए धन्यवाद कि आप देव उद्देश्यों के लिए केवल देव लिपियों को संशोधित करते हैं और उत्पादन कोड (server.js) को शांति से छोड़ते हैं (आपके संस्करण के विपरीत) और imo कि जाने का उचित तरीका है।
जिलेटो

3
यह उत्तर अभी भी सही है, हालांकि थोड़ा दिनांकित है। अधिक सरल तरीके अब उपलब्ध हैं, तलाश करें historyApiFallback
यूजीन कुलबुहोव

102

आप स्थापित करना चाहिए historyApiFallbackके WebpackDevServerकाम करने के लिए इस के लिए सच के रूप में। यहाँ एक छोटा सा उदाहरण है (अपने उद्देश्यों के लिए ट्वीक):

var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');

var config = require('./webpack.config');


var port = 4000;
var ip = '0.0.0.0';
new WebpackDevServer(webpack(config), {
    publicPath: config.output.publicPath,
    historyApiFallback: true,
}).listen(port, ip, function (err) {
    if(err) {
        return console.log(err);
    }

    console.log('Listening at ' + ip + ':' + port);
});

आप अपने index.html के शीर्ष पर स्थित स्थिति पट्टी को याद करेंगे, लेकिन यह बढ़िया काम करता है :)
swennemen 16

7
यह स्वीकृत उत्तर होना चाहिए। Webpack डेव सर्वर डॉक्स से: "आप एचटीएमएल 5 इतिहास एपीआई, जो historyApiFallback निर्धारित करके किया जा सकता है तो आप शायद 404 प्रतिक्रियाओं के स्थान पर आपका index.html सेवा करने के लिए की जरूरत है उपयोग कर रहे हैं: सच" अगर मैं सवाल समझ में सही ढंग से इस का समाधान होगा समस्या।
सेबस्टियन

बहुत सरल ... धन्यवाद!
smnbbrv

1
@smnbbrv प्रोब्स नहीं। यह वास्तव में कनेक्ट-हिस्ट्री-एपी-फॉलबैक के नीचे का उपयोग करता है और आप मिडवेवेयर के विशिष्ट विकल्पों के साथ एक ऑब्जेक्ट पास कर सकते हैं यदि आप सिर्फ इसके बजाय चाहते हैं true
जुहो वेपसैलीन जू

1
या यदि आप cli का उपयोग कर रहे हैं,webpack-dev-server --history-api-fallback
Levi

27

किसी और के लिए जो अभी भी इस उत्तर की तलाश में है। मैंने एक साधारण प्रॉक्सी बाईपास को एक साथ रखा जो बहुत परेशानी के बिना इसे प्राप्त करता है और कॉन्फ़िगर webpack.config.js में चला जाता है

मुझे यकीन है कि रेगेक्स का उपयोग करके स्थानीय सामग्री के परीक्षण के लिए बहुत अधिक सुरुचिपूर्ण तरीके हैं, लेकिन यह मेरी जरूरतों के लिए काम करता है।

devServer: {
  proxy: { 
    '/**': {  //catch all requests
      target: '/index.html',  //default target
      secure: false,
      bypass: function(req, res, opt){
        //your custom code to check for any exceptions
        //console.log('bypass check', {req: req, res:res, opt: opt});
        if(req.path.indexOf('/img/') !== -1 || req.path.indexOf('/public/') !== -1){
          return '/'
        }

        if (req.headers.accept.indexOf('html') !== -1) {
          return '/index.html';
        }
      }
    }
  }
} 

मेरे लिए अच्छी तरह से काम किया
नाथ

अच्छी तरह से काम किया! .. धन्यवाद!
ध्रूमिल भानखर

यह सिर्फ सही जवाब है, त्वरित और आसान है।
डोमिनोज़

12

यदि आप CLI का उपयोग करके webpack-dev-server चला रहे हैं, तो आप इसे webpack.config.js पासिंग devServer ऑब्जेक्ट के माध्यम से कॉन्फ़िगर कर सकते हैं:

module.exports = {
  entry: "index.js",
  output: {
    filename: "bundle.js"
  },
  devServer: {
    historyApiFallback: true
  }
}

यह index.html पर पुनर्निर्देशित करेगा, हर बार यह 404 का सामना करना पड़ता है।

नोट: यदि आप publicPath का उपयोग कर रहे हैं, तो आपको इसे devServer में भी पास करना होगा:

module.exports = {
  entry: "index.js",
  output: {
    filename: "bundle.js",
    publicPath: "admin/dashboard"
  },
  devServer: {
    historyApiFallback: {
      index: "admin/dashboard"
    }
  }
}

आप यह सत्यापित कर सकते हैं कि आउटपुट की पहली कुछ पंक्तियों को देखते हुए सब कुछ सही ढंग से सेटअप किया गया है ("404s के साथ हिस्सा कम हो जाएगा: पथ ")।

यहां छवि विवरण दर्ज करें


11

अधिक हाल के उत्तर के लिए, वेबपैक का वर्तमान संस्करण (4.1.1) आप इसे अपने webpack.config.js में इस तरह सेट कर सकते हैं:

const webpack = require('webpack');

module.exports = {
    entry: [
      'react-hot-loader/patch',
      './src/index.js'
    ],
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: ['babel-loader']
            },
            {
                test: /\.css$/,
                exclude: /node_modules/,
                use: ['style-loader','css-loader']
            }
        ]
    },
    resolve: {
      extensions: ['*', '.js', '.jsx']  
    },
    output: {
      path: __dirname + '/dist',
      publicPath: '/',
      filename: 'bundle.js'
    },
    plugins: [
      new webpack.HotModuleReplacementPlugin()
    ],
    devServer: {
      contentBase: './dist',
      hot: true,
      historyApiFallback: true
    }
  };

महत्वपूर्ण हिस्सा है historyApiFallback: true। कोई कस्टम सर्वर चलाने की आवश्यकता नहीं है, बस cli का उपयोग करें:

"scripts": {
    "start": "webpack-dev-server --config ./webpack.config.js --mode development"
  },

2

जब आप एक आइसोमॉर्फिक ऐप चलाते हैं (तो रिएक्ट कंपोनेंट सर्वर-साइड रेंडर करते हैं) इस केस के उत्तर में जोड़ना चाहूंगा।

इस मामले में आप शायद सर्वर को फिर से लोड करना चाहते हैं जब आप अपने रिएक्ट घटकों में से एक को बदलते हैं। आप pipingपैकेज के साथ ऐसा करते हैं । आपको बस इसे स्थापित करना है और सर्वरrequire("piping")({hook: true}) की शुरुआत में कहीं जोड़ना है । js बस। आपके द्वारा उपयोग किए गए किसी भी घटक को बदलने के बाद सर्वर पुनः आरंभ होगा।

यह हालांकि एक और समस्या को जन्म देता है - यदि आप अपने एक्सप्रेस सर्वर (जैसा कि ऊपर दिए गए उत्तर में है) के रूप में उसी प्रक्रिया से वेबपैक सर्वर चलाते हैं, तो वेबपैक सर्वर भी पुनरारंभ होगा और हर बार आपके बंडल को फिर से जोड़ देगा। इससे बचने के लिए आपको अपने मुख्य सर्वर और वेबपैक सर्वर को विभिन्न प्रक्रियाओं में चलाना चाहिए ताकि पाइपिंग केवल आपके एक्सप्रेस सर्वर को पुनः आरंभ करे और वेबपैक को न छुए। आप concurrentlyपैकेज के साथ ऐसा कर सकते हैं । आप इसका एक उदाहरण प्रतिक्रिया-आइसोमॉर्फिक-स्टार्टरकिट में पा सकते हैं । पैकेज में उसके पास:

"scripts": {
    ...
    "watch": "node ./node_modules/concurrently/src/main.js --kill-others 'npm run watch-client' 'npm run start'"
  },

जो दोनों सर्वरों को एक साथ चलाता है लेकिन अलग-अलग प्रक्रियाओं में।


क्या इसका मतलब है कि कुछ फ़ाइलों को दो बार देखा जा रहा है? जैसे कि साझा आइसोमॉर्फ़िक / सार्वभौमिक फाइलें?
डेविड सिंक्लेयर

1

historyApiFallback एक बूलियन के बजाय एक ऑब्जेक्ट भी हो सकता है, जिसमें रूट शामिल हैं।

historyApiFallback: navData && {
  rewrites: [
      { from: /route-1-regex/, to: 'route-1-example.html' }
  ]
}


-1

इसने मेरे लिए काम किया: बस पहले वेबपैक मिडलवेयर को जोड़ें और app.get('*'...बाद में index.html रिसॉल्वर को

यदि एक्सप्रेस वेबपैक द्वारा प्रदान किए गए मार्गों में से एक से मेल खाता है (जैसे: /dist/bundle.jsया /__webpack_hmr_) और यदि नहीं, तो एक्सप्रेस पहले जांच करेगा कि यह उसके index.htmlसाथ चलती है* रिज़ॉल्वर ।

अर्थात:

app.use(require('webpack-dev-middleware')(compiler, {
  publicPath: webpackConfig.output.publicPath,
}))
app.use(require('webpack-hot-middleware')(compiler))
app.get('*', function(req, res) {
  sendSomeHtml(res)
})
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.