Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot run at non-web root URL - remote development #2358

Closed
1 of 2 tasks
methodbox opened this issue Dec 18, 2019 · 21 comments
Closed
1 of 2 tasks

Cannot run at non-web root URL - remote development #2358

methodbox opened this issue Dec 18, 2019 · 21 comments

Comments

@methodbox
Copy link

methodbox commented Dec 18, 2019

  • Operating System: tested on macOS and remote dev server Debian Stretch
  • Node Version: 12.x
  • NPM Version: 6.9
  • webpack Version: 4.41.2
  • webpack-dev-server Version: 3.9.0
  • Browser: Chrome
  • This is a bug
  • This is a modification request

Code

// webpack.config.js
const webpack = require("webpack");
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

const config = {
  entry: ["react-hot-loader/patch", "./src/index.js"],
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "[name].[contenthash].js"
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        use: "babel-loader",
        exclude: /node_modules/
      },
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"]
      }
    ]
  },
  resolve: {
    extensions: [".js", ".jsx"],
    alias: {
      "react-dom": "@hot-loader/react-dom"
    }
  },
  devServer: {
    contentBase: "./dist",
    publicPath: "/testing"
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: require("html-webpack-template"),
      inject: false,
      appMountId: "app"
    })
  ],
  optimization: {
    runtimeChunk: "single",
    splitChunks: {
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: "vendors",
          chunks: "all"
        }
      }
    }
  }
};

module.exports = (env, argv) => {
  if (argv.hot) {
    // Cannot use 'contenthash' when hot reloading is enabled.
    config.output.filename = "[name].[hash].js";
  }

  return config;
};
// additional code, remove if not needed.

Expected Behavior

Setting publicPath should allow the dev server to serve the app at a non-web-root url (i.e. domain.com/urlnamehere vs. domain.com/ ).

This is particularly an issue when working with remote development a la VS Code as the app can't run on root and must be run at an alternate URL. This isn't a technical requirement, but a require in my environment.

Actual Behavior

When using the publicPath, for example, of /testing, and setting Nginx with a proxy_pass, the app is "served" by Nginx, but displays 'Cannot get /testing`.

The built app works with webpack prod build. It serves the app fine. It's the dev server that won't.

Note that on the same server, with the same configuration, I have an Express API running at a non-web-root URL; I am 100% familiar with how to configure this on the Nginx side.

Locally, setting publicPath to /testing simply shows a white page, whether it's accessed at root or at /testing.

**If this isn't the right way to do this, please tell me how I can run the dev server on a remote server at /testing (and not web root). Thanks. **

For Bugs; How can we reproduce the behavior?

Change the publicPath value, watch it not work.

For Features; What is the motivation and/or use-case for the feature?

My primary need is developing remotely. This is 100% necessary as I am working with an iframe which requires same-origin to develop features which target the iframe; bringing the iframe in remotely makes the content of the iframe inaccessible due to browser security.

It's also silly to not be able to use an alternate URL path to serve from.

@hiroppy
Copy link
Member

hiroppy commented Dec 18, 2019

Please submit the reproable repo

@methodbox
Copy link
Author

Please submit the reproable repo

I don't understand WTF that means. You need a repo to test my webpack config?

@rishabh3112
Copy link
Member

rishabh3112 commented Dec 18, 2019

@methodbox its exactly what he meant, recreate the issue with minimum possible files and share it here if you want us to dig into your issue.

@methodbox
Copy link
Author

Here's a minimal example. Credit to createapp.dev. I literally just changed the value to match the same webpack example as shown above.

https://github.com/methodbox/wds-example

Again, maybe this is simply a misunderstanding from the multiple issues previously opened on this exact same question, as well as the Webpack docs, but my understanding is that if I want to run the the dev server at 'domain.com/testing' I simply update the publicPath value to /testing (and of course configure my web server for that end point.

I get 404s on all the bundle scripts when I visit /testing:
GET http://localhost:8080/runtime.66d6220c8921630dc54e.js net::ERR_ABORTED 404 (Not Found) testing:13 GET http://localhost:8080/main.66d6220c8921630dc54e.js net::ERR_ABORTED 404 (Not Found) testing:12 GET http://localhost:8080/vendors.66d6220c8921630dc54e.js net::ERR_ABORTED 404 (Not Found) testing:13 GET http://localhost:8080/main.66d6220c8921630dc54e.js net::ERR_ABORTED 404 (Not Found)

I get a 404 on bundle.js only when I visit the root /:
GET http://localhost:8080/bundle.js net::ERR_ABORTED 404 (Not Found)
This is on my local machine, but the same result occurs when running behind Nginx on a remote server.

@alexander-akait
Copy link
Member

alexander-akait commented Dec 18, 2019

You can't run dev server under domain.com/testing, publicPath only for public path to assets, it is not dev server entry

@methodbox
Copy link
Author

You can't run dev server under domain.com/testing, publicPath only for public path to assets, it is not dev server entry

Awesome, so now we know that I did it wrong (as I suggested above) - how do I achieve what I'm trying to do?

How can I run at /testing on the server? I've tried this on the output config, too. Webpack refuses to run anywhere other than web root. There appears to be an open issue re: socket-js not working correctly with this config: https://webpack.js.org/configuration/dev-server/#devserverpublic - not sure if that's what I should be using?

@methodbox
Copy link
Author

Yeah, this doesn't work, either: https://webpack.js.org/configuration/dev-server/#devserverpublic - same result.

I've tried:
https://domain.com/testing
https://ipaddress/testing
(no http/s) domain.com/testing
... as the public value in:

devServer: {
    contentBase: path.join(__dirname, "dist"),
    host: "0.0.0.0",
    port: "5000",
    public: "....",
    hot: true,
    disableHostCheck: true
  }

@methodbox
Copy link
Author

You can't run dev server under domain.com/testing, publicPath only for public path to assets, it is not dev server entry

Also, this does appear to be a valid devServer entry, according to webpack docs:

https://webpack.js.org/configuration/dev-server/#devserverpublicpath-

@alexander-akait
Copy link
Member

It is impossible and out of scope webpack-dev-server, it is just simple dev server for development, it is not designed for this

@methodbox
Copy link
Author

methodbox commented Dec 19, 2019

It is impossible and out of scope webpack-dev-server, it is just simple dev server for development, it is not designed for this

I'm not sure it's "impossible"; there are clearly other people who have created issues ( you have an open one right now re: socket.io and serving while using Nginx, for example - which is technically possible if Nginx is configured to serve web sockets connections, too - which suggest others are doing the same w/remote dev).

You also have an extremely similar, related but different issue here: #2164 - to which you also replied asking for a reproducable example.

That user apparently hasn't realized it but they have a similar issue to me.

At the end of the day, this is simply asking for the ability to tell webpack what URL it will be served on; it seems from the various configurations this should be possible but I haven't sorted it yet, apparently.

You even provide the ability to proxy your own requests to an internal API, for example:

https://webpack.js.org/configuration/dev-server/#devserverproxy

There's also the public option, which only seems to work for webpack running on root, ironically:

https://webpack.js.org/configuration/dev-server/#devserverpublic

This seems to suggest it was designed for exactly what I'm requesting, based on your own docs:

When using inline mode and you're proxying dev-server, the inline client script does not always know where to connect to. It will try to guess the URL of the server based on window.location, but if that fails you'll need to use this.

For example, the dev-server is proxied by nginx, and available on myapp.test:

webpack.config.js

module.exports = {
 //...
 devServer: {
   public: 'myapp.test:80'
 }
};

EDIT: Maybe you don't understand the use case: I'm using this for development, I just happen to be running it in the environment where the app will run due to a few other dependencies which exist outside the app and aren't possible to run outside the server; it's not intended to act as a web server/app server.

@alexander-akait
Copy link
Member

alexander-akait commented Dec 19, 2019

@methodbox
Copy link
Author

https://stackoverflow.com/questions/44939908/how-to-make-a-server-listen-to-a-path-in-nodejs

I'm not trying to make a server "listen to a path". I'm simply trying to serve your app on a non-web root URL.

Nodejs-based web apps (which, for example, run on localhost:3000) are used with Nginx proxy_pass all the time. It's 100% possible.

Whether webpack allows it to be configured on the other hand, is a different story.

My question isn't how to make a server listen to a path (which Nginx does for you). My question is how to tell webpack that path is its root path.

In the mean time, the best solution is probably serving the /dist folder on that URL and manually refereshing; webpack can sit in the back ground and simply update my code.

However, this isn't a simple "it's impossible" because your understanding of what is being asked and what is actually being asked seem to be at odds, which is understandable, but please don't simply blow it off with an unrelated Stackoverflow link.

@alexander-akait
Copy link
Member

@methodbox please clarify what do you want, "listen to a path" - meaning serve the app at a non-web-root url (i.e. domain.com/urlnamehere vs. domain.com/ ). How we should implement this, do you look in source code?

@alexander-akait
Copy link
Member

alexander-akait commented Dec 19, 2019

We do not design dev server for all production purposes and we can't do it because it is dev server and should be used in maximum simple environment - no iframes, no remote run, no other complex setup.

This isn't a technical requirement, but a require in my environment.

If you need complex setup you can create own server code and working with this as you want.

@alexander-akait
Copy link
Member

I re-read everything that you write several times, and actually still can’t understand what you want to do and what you don’t get, when we ask create reproducible test repo it is mean create the environment is as similar as possible (include iframe, remote run and etc), this will allow us to quickly identify problems and errors and talk less

@methodbox
Copy link
Author

methodbox commented Dec 19, 2019

@methodbox please clarify what do you want, "listen to a path" - meaning serve the app at a non-web-root url (i.e. domain.com/urlnamehere vs. domain.com/ ). How we should implement this, do you look in source code?

Express can already do this; I would assume to do this in webpack would require a configurable variable for some Express config like app.get(${myURL}, () => ..). I haven't looked at your source to determine how this is done. Again, I think what I'm asking is probably already possible through webpack config, I just don't know how to achieve it.

Nginx can be used to setup a proxy_pass; if webpack could be made to understand it lives at "domain.com/webpack" ("/webpack" could be anything) instead of "domain.com" this would work like this:

In the Nginx config you have an endpoint that looks like this:

server {
    listen 443;
    # ssl config ...

    location / {
       # whatever runs on root domain is configured here
    }

    location /webpack {
       # proxy_pass takes requests on the front-end at domain.com/webpack
       # webpack runs on whatever port internally - 3000 in this case
       # Nginx takes front-end requests from port 443 (or 80) and proxies them to 3000
       # This is already how an Express API might work, for example, at /api
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }

When I hit domain.com/webpack Nginx sends the request to port 3000, WDS responds.

@methodbox
Copy link
Author

This article has a great example. I linked to the part of the page that gives a similar example to mine above.

https://www.digitalocean.com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-ubuntu-16-04#set-up-nginx-as-a-reverse-proxy-server

@alexander-akait
Copy link
Member

@methodbox i recommend use stackoverflow for questions and articles, your configuration looks good, what is problem?

@methodbox
Copy link
Author

methodbox commented Dec 22, 2019

@methodbox i recommend use stackoverflow for questions and articles, your configuration looks good, what is problem?

I know my Nginx config is good. WDS refuses to serve the page at /webpack in the example above. I simply says, “Cannot GET /webpack”. Looking in the console (as you can see in the console errors I posted above) you can see it’s not looking in the relative location (it’s not treating /webpack as it’s web root) for it’s files.

I’m not sure how to communicate this any other way.

@alexander-akait
Copy link
Member

I’m not sure how to communicate this any other way.

Maybe you can create couple containers (docker) and provide small readme what is you expected?

@methodbox
Copy link
Author

methodbox commented Dec 27, 2019

I’m not sure how to communicate this any other way.

Maybe you can create couple containers (docker) and provide small readme what is you expected?

As I said above, regarding my Nginx config:

When I hit domain.com/webpack Nginx sends the request to port 3000, WDS responds.

Everything works, except WDS doesn't render the site, and console shows it's not looking in the relative path for it's files - it's looking at domain.com/ instead of domain.com/webpack.

WDS is clearly able to run on the non-web root URL, it simply doesn't seem to be able to translate that to finding it's files.

  • I've worked around this, sort of, by instead pointing Nginx to the dist directory and manually reloading the browser after running a new build with webpack -p --mode production. It's not sexy, and it's slow and tedious but it allows me to do remote development.

Ideally, WDS would allow specifying a non-web root URL as its web root.

An example might be WordPress - it allows setting a base URL, or what it calls a "home" and "site" URL. This concept is similar, but not the same. Maybe it's something you're familiar with, though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants