Cách báo cho máy chủ phát triển webpack để phục vụ index.html cho bất kỳ tuyến đường nào


148

React router cho phép các ứng dụng phản ứng xử lý /arbitrary/route. Để làm việc này, tôi cần máy chủ của mình gửi ứng dụng React trên bất kỳ tuyến đường phù hợp nào.

Nhưng máy chủ webpack dev không xử lý các điểm cuối tùy ý.

Có một giải pháp ở đây bằng cách sử dụng máy chủ tốc hành bổ sung. Cách cho phép webpack-dev-server cho phép các điểm vào từ bộ định tuyến phản ứng

Nhưng tôi không muốn kích hoạt một máy chủ tốc hành khác để cho phép khớp tuyến. Tôi chỉ muốn nói với máy chủ phát triển webpack phù hợp với bất kỳ url nào và gửi cho tôi ứng dụng phản ứng của tôi. xin vui lòng.


Bạn đã xem React Router Mega Demo chưa?
rojobuffalo

Câu trả lời:


169

Tôi tìm thấy giải pháp dễ nhất để bao gồm một cấu hình nhỏ:

  devServer: {
    port: 3000,
    historyApiFallback: {
      index: 'index.html'
    }
  }

Tôi đã tìm thấy điều này bằng cách truy cập: PUSHSTATE VỚI WEBPACK-DEV-SERVER .


18
bạn cũng có thể sử dụng nó làm tùy chọn CLI:--history-api-fallback
VonD

7
Tôi đã phải sử dụng một cái gì đó như thế này với phiên bản mới hơn 2.devServer: { port: 3000, historyApiFallback: true },
Adrian Moisa

1
Thật vậy, bạn phải sử dụng cả hai tùy chọn cli "--history-api-fallback" và trên cấu hình máy chủ dev của gói webpack của bạn đặt độ phân giải cho tệp chỉ mục của bạn như được mô tả trong câu trả lời ở trên.
Jc Figueroa

86

Tùy chọn historyApiFallback trên tài liệu chính thức cho webpack-dev-server giải thích rõ ràng cách bạn có thể đạt được bằng cách sử dụng

historyApiFallback: true

mà chỉ đơn giản là quay trở lại index.html khi không tìm thấy tuyến đường

hoặc là

// output.publicPath: '/foo-app/'
historyApiFallback: {
  index: '/foo-app/'
}

1
Liên kết được cập nhật: webpack.js.org/configuration/dev-server/#devserver
jacob

Nhưng thực sự webpack-dev-server hiện đang được bảo trì. Người kế nhiệm của nó là github.com/webpack-contrib/ , hỗ trợhistoryApiFallback
jacob

3
Đối với bất kỳ ai đọc điều này vào năm 2019, theo github.com/webpack-contrib/webpack-serve#webpack-serve webpack-dev-server là người kế thừa webpack-serve, không phải là cách khác như được đề cập trong stackoverflow.com/questions/31945763/ .
ur5us

Nhận xét của ur5us là sai. webpack-phục vụ là sự kế thừa kế hoạch cho webpack-dev-server. Tôi là tác giả của webpack-phục vụ và là người duy trì trước đây của webpack-dev-server. Khi tôi nghỉ một chút, các thành viên org cay đắng không tán thành webpack-phục vụ, và tôi đã phát hành nó dưới cái nĩa của mình.
shellscape 18/03/19

23

Thêm đường dẫn công khai vào cấu hình giúp webpack hiểu được root thực sự ( /) ngay cả khi bạn đang ở trong chương trình con, vd./article/uuid

Vì vậy, sửa đổi cấu hình webpack của bạn và thêm sau đây:

output: {
    publicPath: "/"
}

devServer: {
    historyApiFallback: true
}

Không có publicPathtài nguyên có thể không được tải đúng cách, chỉ index.html.

Đã thử nghiệm trên Webpack 4.6

Phần lớn hơn của cấu hình (chỉ để có hình ảnh tốt hơn):

entry: "./main.js",
output: {
  publicPath: "/",
  path: path.join(__dirname, "public"),
  filename: "bundle-[hash].js"
},
devServer: {
  host: "domain.local",
  https: true,
  port: 123,
  hot: true,
  contentBase: "./public",
  inline: true,
  disableHostCheck: true,
  historyApiFallback: true
}

Wow điều này làm việc cho tôi là tốt! Thủ historyApiFallbackthuật chỉ hoạt động cho phần cuối của URL vì một số lý do. /testsẽ làm việc nhưng /test/testsẽ cung cấp 404.
Alex. P.

Ngoài historyApiFallback: {index: '/'} hoặc historyApiFallback: true(cả hai đều hoạt động với tôi), việc cài đặt publicPathcũng rất cần thiết trong trường hợp của tôi (Bộ định tuyến 5.2).
Marcus Junius Brutus

17

Làm việc cho tôi như thế này

devServer: {
    contentBase: "./src",
    hot: true,
    port: 3000,
    historyApiFallback: true

},

Làm việc trên ứng dụng bạo loạn


14

Tình huống của tôi hơi khác một chút, vì tôi đang sử dụng CLI góc với webpack và tùy chọn 'eject' sau khi chạy lệnh ng eject . Tôi đã sửa đổi tập lệnh npm bị đẩy ra cho 'npm start' trong gói.json để chuyển qua cờ --history-api-fallback

"bắt đầu": "webpack-dev-server --port = 4200 --history-api-fallback "

"scripts": {
"ng": "ng",
"start": "webpack-dev-server --port=4200 --history-api-fallback",
"build": "webpack",
"test": "karma start ./karma.conf.js",
"lint": "ng lint",
"e2e": "protractor ./protractor.conf.js",
"prepree2e": "npm start",
"pree2e": "webdriver-manager update --standalone false --gecko false --quiet",
"startold": "webpack-dev-server --inline --progress --port 8080",
"testold": "karma start",
"buildold": "rimraf dist && webpack --config config/webpack.prod.js --progress --profile --bail"},

6

Nếu bạn chọn sử dụng webpack-dev-server, bạn không nên sử dụng nó để phục vụ toàn bộ ứng dụng React của mình. Bạn nên sử dụng nó để phục vụ bundle.jstập tin của bạn cũng như các phụ thuộc tĩnh. Trong trường hợp này, bạn sẽ phải khởi động 2 máy chủ, một cho các điểm nhập Node.js, thực sự sẽ xử lý các tuyến và phục vụ HTML và một máy chủ khác cho gói và tài nguyên tĩnh.

Nếu bạn thực sự muốn một máy chủ, bạn phải ngừng sử dụng webpack-dev-servervà bắt đầu sử dụng webpack-dev-middleware trong máy chủ ứng dụng của bạn. Nó sẽ xử lý các gói "nhanh chóng" (tôi nghĩ rằng nó hỗ trợ bộ nhớ đệm và thay thế mô-đun nóng) và đảm bảo các cuộc gọi của bạn bundle.jsluôn được cập nhật.


2
Tôi chỉ sử dụng webpack-dev-server để phát triển tải lại bản đồ nguồn, v.v. Nếu không, tôi có một trang web tĩnh nơi tôi có thể lưu trữ các tệp từ bất cứ đâu.
eguneys

3

Bạn có thể kích hoạt historyApiFallbackđể phục vụ index.htmlthay vì lỗi 404 khi không tìm thấy tài nguyên nào khác tại vị trí này.

let devServer = new WebpackDevServer(compiler, {
    historyApiFallback: true,
});

Nếu bạn muốn phân phát các tệp khác nhau cho các URI khác nhau, bạn có thể thêm các quy tắc viết lại cơ bản vào tùy chọn này. Các index.htmlvẫn sẽ được phục vụ cho các đường khác.

let devServer = new WebpackDevServer(compiler, {
    historyApiFallback: {
        rewrites: [
            { from: /^\/page1/, to: '/page1.html' },
            { from: /^\/page2/, to: '/page2.html' },
            { from: /^\/page3/, to: '/page3.html' },
        ]
    },
});

2

Tôi biết câu hỏi này dành cho webpack-dev-server, nhưng dành cho bất kỳ ai sử dụng webpack-phục vụ 2.0. với gói web 4.16.5 ; webpack-phục vụ cho phép các tiện ích bổ sung. Bạn sẽ cần tạo serve.config.js:

const serve = require('webpack-serve');
const argv = {};
const config = require('./webpack.config.js');

const history = require('connect-history-api-fallback');
const convert = require('koa-connect');

serve(argv, { config }).then((result) => {
  server.on('listening', ({ server, options }) => {
      options.add: (app, middleware, options) => {

          // HistoryApiFallback
          const historyOptions = {
              // ... configure options
          };

          app.use(convert(history(historyOptions)));
      }
  });
});

Tài liệu tham khảo

Bạn sẽ cần phải thay đổi tập lệnh dev từ webpack-servesang node serve.config.js.


2

Đối với tôi, tôi đã có dấu chấm "." trong đường dẫn của tôi, ví dụ như /orgs.csvvậy, tôi phải đặt cái này vào confg webpack của mình.

devServer: {
  historyApiFallback: {
    disableDotRule: true,
  },
},

0

Tôi đồng ý với phần lớn các câu trả lời hiện có.

Một điều quan trọng tôi muốn đề cập là nếu bạn gặp sự cố khi tải lại các trang theo cách thủ công trên các đường dẫn sâu hơn , nơi nó giữ tất cả trừ phần cuối cùng của đường dẫn và xử lý tên jstệp bó của bạn, bạn có thể cần một cài đặt bổ sung (cụ thể là publicPathcài đặt ).

Ví dụ: nếu tôi có một đường dẫn /foo/barvà tập tin gói của tôi được gọi bundle.js. Khi tôi cố gắng làm mới trang theo cách thủ công, tôi nhận được thông báo 404 /foo/bundle.jskhông thể tìm thấy. Thật thú vị nếu bạn thử tải lại từ đường dẫn /foomà bạn thấy không có vấn đề gì (điều này là do dự phòng xử lý nó).

Hãy thử sử dụng kết hợp bên dưới với webpackcấu hình hiện tại của bạn để khắc phục sự cố. output.publicPathlà mảnh ghép quan trọng!

output: {
    filename: 'bundle.js',
    publicPath: '/',
    path: path.resolve(__dirname, 'public')
},
...
devServer: {
    historyApiFallback: true
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.