在 Browsersync 中手动重写对特定 URL 的请求

Manually rewrite requests to specific URLs in Browsersync

我在一个有点奇怪的设置中使用 BrowserSync,我在其中代理我的 Web 服务器(Docker 容器中的 Apache),但也从 Webpack 开发服务器提供热模块替换 (HMR) .

在我的本地开发环境中,设置如下所示:

https://mytestsite.localhost – Docker 容器中的 Apache 服务

https://localhost:8888 – Webpack 开发服务器,服务于 HMR

https://localhost:3000 – BrowserSync`

对于硬重新加载,这一切都很好——webpack 开发服务器似乎传递了需要重新加载的消息,一切正常。

我遇到的问题是热重载。 BS 代理服务的文档应该读取 webpack-dev-server 服务的 hotupdate.json。在收到热更新时,页面会尝试加载 /hotupdate.json(我相信这会告诉它要选择哪段代码),但是,因为它是相对的 URL,浏览器会尝试 GET https://localhost:3000/hotupdate.json,这是 404s,因为这个 hotupdate.json 实际上是由 Webpack 服务器提供的,例如https://localhost:8888/hotupdate.json.

因为我知道这个资源的绝对 URL,所以我想强制 BrowserSync 将任何请求重定向到 /hotupdate.jsonhttps://localhost:8888/hotupdate.json。我以为我可以用一些中间件来做到这一点,但我很挣扎,可能是因为我从来没有完全理解 Express 风格的中间件。

我试过类似的方法,但没有用!

browserSync({
    proxy: {
        target: `https://${process.env.APP_HOST_PATH}`,
        middleware: [
            dontProxyHotUpdate,
            require('webpack-dev-middleware')(bundler, {
                noInfo: true,
                publicPath: webpackConfig.output.path
            }),
        ]
    },
    files: [
      'app/css/*.css',
      'app/*.html'
    ]
});

function dontProxyHotUpdate (req, res, next){
    if(req.url === '/hotupdate.json'){
        req.url = 'https://127.0.0.1:8888/hotupdate.json';
    }
    next();
}

它肯定会尽我所能加载中间件,比如 console.log(req.url),但我无法重写请求 URL。我想可能的解决方案是重写请求 URL,或者直接覆盖响应。

N.B。有人可能会问为什么我不直接使用 webpack-dev-server,因为它自己很好地服务于 HMR。它确实如此,但它也不允许很好地重写页面中的锚元素,例如将 https://mytestsite.localhost/link 更改为 https://localhost:3000/link。这对于在开发过程中浏览站点显然很重要(这很好,但不是必需的),但对于重写资产链接更为重要——特别是 SVG,除非路径、主机和端口都匹配,否则不会加载.

嗯,最后我解决了自己的问题!

我最终使用 http-proxy-middlware 编写了自己的中间件 - 就像这样。

var proxy = require('http-proxy-middleware');

browserSync({
    proxy: {
        target: `https://${process.env.APP_HOST_PATH}`,
        middleware: [
            dontProxyHotUpdate,
            require('webpack-dev-middleware')(bundler, {
                noInfo: true,
                publicPath: webpackConfig.output.path
            }),
            // require("webpack-hot-middleware")(bundler) // I don't think that we want this here as it can be handled by the webpack dev server
        ],
    },

    // no need to watch '*.js' here, webpack will take care of it for us,
    // including full page reloads if HMR won't work
    files: [
      path.join(source, '**/*.php'),
      path.join(source, 'style.css')
    ]
});

var dontProxyHotUpdate = proxy('/hotupdate*', {
    target: 'https://127.0.0.1:8888/',
    changeOrigin: true, // for vhosted sites, changes host header to match to target's host
    logLevel: 'debug',
    secure: false
});