webpack-dev-server가 react-router의 진입 점을 허용하도록 허용하는 방법


117

React-router와 함께 개발에서 webpack-dev-server를 사용하는 앱을 만들고 있습니다.

webpack-dev-server는 한곳에 공개 진입 점 (예 : "/")이 있다는 가정하에 구축 된 것으로 보이지만 react-router는 무제한 진입 점을 허용합니다.

webpack-dev-server의 이점, 특히 생산성에 좋은 핫 리로딩 기능을 원하지만 여전히 react-router에 설정된 경로를로드 할 수 있기를 원합니다.

함께 작동하도록 어떻게 구현할 수 있습니까? 이를 허용하는 방식으로 webpack-dev-server 앞에서 익스프레스 서버를 실행할 수 있습니까?


여기에는 매우 해키 버전이 있지만 깨지기 쉽고 간단한 경로 만 일치시킬 수 있습니다. github.com/natew/react-base (make-webpack-config 참조) 및 (app / routes.js)
Nathan Wienert

이 문제를 해결할 수 있었습니까 Nathan? 그렇다면 어떻게? 여기 stackoverflow.com/questions/31091702/… 내 질문에 대답 해보십시오 . 감사합니다..!
SudoPlz 2015-06-27

답변:


69

이를 위해 프록시를 설정했습니다.

자산 경로 인 경우를 제외하고 모든 경로에서 index.html을 제공하는 정규 익스프레스 웹 서버가 있습니다. 자산 인 경우 요청은 web-dev-server로 프록시됩니다.

반응 핫 진입 점은 여전히 ​​웹팩 개발 서버를 직접 가리 키므로 핫 리로딩은 여전히 ​​작동합니다.

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

이제 webpack 구성에서 다음과 같이 진입 점을 만드십시오.

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

hotreload를 위해 8081로 직접 호출하십시오.

또한 절대 URL을 output.publicPath옵션에 전달했는지 확인하십시오 .

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

1
야, 이거 대단해. 저는 실제로이 설정 직전에이 설정에 도착했고 답변을 게시하려고했지만 더 나은 작업을 수행했다고 생각합니다.
Nathan Wienert 2014 년

1
하나의 질문, 일종의 관련이 없으므로 필요한 경우 새 질문을 열 수 있지만 이제 webpack dev 서버의 콘솔 출력이 스트리밍되지 않습니다. 이전에는 컴파일을보고 퍼센트가 상승하는 것을 볼 수 있었지만 이제는 컴파일 후 출력을 차단합니다.
Nathan Wienert 2014 년

잘 했어요. 이것이 정확히 수행되어야하는 방법입니다. output.publicPath절대 URL이어야 하는 옵션 에 대한 메모를 추가했습니다 .
Tobias K.

5
대신 내장 웹팩 프록시 를 사용하는 것이 더 쉬울 것입니다. 따라서 서버 자체를 방해하지 않고 서버를 순수하게 둡니다 . 대신 webpack config에 약간 (3-5 줄)을 추가하면됩니다. 덕분에 개발 목적을 위해 개발 스크립트 만 수정하고 프로덕션 코드 (server.js)를 평화롭게 남겨두고 (사용자 버전과 달리) imo를 사용하는 것이 적절한 방법입니다.
jalooc

3
이 답변은 약간 날짜가 있지만 여전히 정확합니다. 이제 더 간단한 방법을 사용할 수 있습니다 historyApiFallback..
Eugene Kulabuhov

102

당신은 설정해야합니다 historyApiFallbackWebpackDevServer일이 마찬가지한다. 다음은 작은 예입니다 (목적에 맞게 조정).

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

7
이것은 받아 들여진 대답이어야합니다. 웹팩 개발 서버 문서에서 : "HTML5 히스토리 API를 사용하는 경우 404 응답 대신 index.html을 제공해야합니다. 이는 historyApiFallback : true를 설정하여 수행 할 수 있습니다." 질문을 올바르게 이해하면 해결 될 것입니다. 문제.
Sebastian

너무 간단합니다 ... 감사합니다!
smnbbrv

1
@smnbbrv 문제가 없습니다. 실제로 아래에 connect-history-api-fallback을 사용하며 원하는 경우 미들웨어 특정 옵션으로 객체를 전달할 수 있습니다 true.
Juho Vepsäläinen

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

나를 위해 잘 작동했습니다
Nath

잘 했어요! .. 감사합니다!
Dhrumil Bhankhar

이것은 빠르고 쉬운 완벽한 대답입니다.
domino

12

CLI를 사용하여 webpack-dev-server를 실행하는 경우 devServer 객체를 전달하는 webpack.config.js를 통해 구성 할 수 있습니다.

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

404가 발생할 때마다 index.html로 리디렉션됩니다.

참고 : publicPath를 사용하는 경우 devServer에도 전달해야합니다.

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

출력의 처음 몇 줄을 살펴보면 모든 것이 올바르게 설정되었는지 확인할 수 있습니다 ( "404s는 다음으로 대체됩니다 : 경로 ").

여기에 이미지 설명 입력


11

최신 답변 인 webpack (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

동형 앱을 실행할 때 (즉, React 컴포넌트 서버 측 렌더링) 경우에 대한 답변에 추가하고 싶습니다.

이 경우 React 구성 요소 중 하나를 변경할 때 서버를 자동으로 다시로드 할 수도 있습니다. piping패키지 로이 작업을 수행 합니다. 당신이해야 할 일은 그것을 설치하고 server.jsrequire("piping")({hook: true}) 시작 부분에 추가 하는 것 입니다. 그게 다야. 서버에서 사용하는 구성 요소를 변경하면 서버가 다시 시작됩니다.

그러나 이것은 또 다른 문제를 야기합니다. 위의 대답에서와 같이 익스프레스 서버와 동일한 프로세스에서 웹팩 서버를 실행하면 웹팩 서버도 다시 시작되고 매번 번들을 다시 컴파일합니다. 이를 피하려면 파이핑이 익스프레스 서버 만 다시 시작하고 웹팩을 건드리지 않도록 다른 프로세스에서 메인 서버와 웹팩 서버를 실행해야합니다. concurrently패키지로 할 수 있습니다 . react-isomorphic-starterkit 에서 이에 대한 예를 찾을 수 있습니다 . 에서 package.json 그는이있다 :

"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

이것은 나를 위해 일했습니다. 먼저 webpack 미들웨어를 추가하고 app.get('*'...나중에 index.html 리졸버 를 추가하십시오 .

따라서 express는 먼저 요청이 webpack에서 제공하는 경로 중 하나 (예 : /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)
})
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.