Как разрешить для webpack-dev-server разрешать точки входа из реагирующего маршрутизатора

91

Я создаю приложение, которое использует webpack-dev-сервер в разработке вместе с реакционным маршрутизатором.

Похоже, что webpack-dev-сервер построен на основе предположения, что у вас будет открытая точка входа в одном месте (например, "/" ), тогда как "реактивный маршрутизатор" допускает неограниченное количество точек входа.

Я хочу использовать преимущества webpack-dev-сервера, особенно горячую перезагрузку, которая отлично подходит для производительности, но я все же хочу иметь возможность загружать маршруты, установленные в маршрутизаторе реакции.

Как можно реализовать его так, чтобы они работали вместе? Не могли бы вы запустить экспресс-сервер перед webpack-dev-сервером таким образом, чтобы это разрешить?

  • 0
    У меня есть очень хакерская версия чего-то, но она хрупкая и позволяет сопоставлять только простые маршруты: github.com/natew/react-base (см. Make-webpack-config) и (app / rout.js)
  • 0
    Вам удалось решить эту проблему, Натан? Если так, как? Пожалуйста, попробуйте ответить на мой вопрос здесь stackoverflow.com/questions/31091702/… . Спасибо..!
Теги:
react-router
webpack

8 ответов

61
Лучший ответ

Я установил прокси для этого:

У вас есть обычный экспресс-сервер, который обслуживает index.html на любом маршруте, за исключением того, что это маршрут ресурса. если это актив, запрос проксируется на веб-dev-сервере

ваши ответные горячие точки входа по-прежнему будут отображаться непосредственно на сервере webpack dev, поэтому горячая перезагрузка все равно работает.

Предположим, вы запустили webpack-dev-сервер на 8081 и ваш прокси-сервер на 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'
    ]

Обратите внимание на прямой вызов 8081 для hotreload

также убедитесь, что вы передаете абсолютный URL-адрес опции output.publicPath:

    output: {
        publicPath: "http://localhost:8081/assets/",
        // ...
    }
  • 1
    Эй, это круто На самом деле я пришел к этой настройке незадолго до этого и собирался опубликовать ответ, но я думаю, что вы справились лучше.
  • 1
    Один вопрос, вроде как не связанный, так что я могу открыть новый вопрос, если это будет необходимо, но я заметил, что теперь вывод консоли с сервера разработки веб-пакетов не передается. Раньше вы могли наблюдать за его компиляцией и видеть рост процентов, теперь он просто блокирует выходные данные после компиляции.
Показать ещё 12 комментариев
78

Вы должны установить historyApiFallback of 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);
});
  • 0
    Вы пропустите строку состояния в верхней части вашего index.html, но это прекрасно работает :)
  • 7
    Это должен быть принятый ответ. Из документации сервера разработки веб-пакетов: «Если вы используете API истории HTML5, вам, вероятно, нужно предоставить свой index.html вместо 404 ответов, что можно сделать, установив historyApiFallback: true». Если я правильно понимаю вопрос, это решит проблему. эта проблема.
Показать ещё 5 комментариев
14

Для всех, кто еще может найти этот ответ. Я собрал простой прокси-прокси, который достигает этого без особых хлопот, и конфигурация переходит в файл 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';
        }
      }
    }
  }
} 
  • 0
    Работал хорошо для меня
  • 0
    Работал красиво! .. Спасибо!
Показать ещё 1 комментарий
3

Если вы используете webpack-dev-сервер с использованием CLI, вы можете настроить его через 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 будет отбрасываться до: путь" ).

Изображение 2706

  • 0
    Удивительно, именно то, что мне было нужно - спасибо!
2

Я хотел бы добавить ответ на случай, когда вы запускаете изоморфное приложение (т.е. рендеринг на стороне сервера).

В этом случае вы, вероятно, также захотите автоматически перезагрузить сервер при изменении одной из ваших компонентов React. Вы делаете это с помощью пакета piping. Все, что вам нужно сделать, это установить его и добавить require("piping")({hook: true}) где-то в начале сервера server.js. Это. Сервер будет перезагружен после изменения любого используемого им компонента.

Это еще одна проблема: если вы запустите сервер webpack из того же процесса, что и ваш экспресс-сервер (как в принятом ответе выше), сервер webpack также перезагрузится и будет перекомпилировать ваш пакет каждый раз. Чтобы этого избежать, вы должны запускать главный сервер и сервер веб-пакетов в разных процессах, чтобы трубопроводы перезапускали только ваш экспресс-сервер и не касались веб-пакета. Вы можете сделать это с помощью пакета concurrently. Вы можете найти пример этого в react-isomorphic-starterkit. В пакете .json он имеет:

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

который запускает оба сервера одновременно, но в отдельных процессах.

  • 0
    Значит ли это, что некоторые файлы просматриваются дважды? Такие как общие изоморфные / универсальные файлы?
1

Может быть не во всех случаях, но кажется, что опция publicPath: '/' в devServer - это самое простое решение для исправления проблемы с глубокими маршрутами, см.: https://github.com/ReactTraining/react-router/issues/676

1

historyApiFallback также может быть объектом, а не булевым, содержащим маршруты.

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

Это сработало для меня: просто добавьте сначала webpack middlewares и app.get('*'... index.html resolver позже,

поэтому выражение сначала проверит, соответствует ли запрос одному из маршрутов, предоставляемых 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)
})

Ещё вопросы

Сообщество Overcoder
Наверх
Меню