Webpack: Set the baseUrl for the dev-server

Created on 23 Feb 2017  路  17Comments  路  Source: vuejs-templates/webpack

I just spent many hours trying to work out how to mount the dev server at a child path in the URL.

For example; my application is mounted at a child path of /app/. The root of the url http://someaddress.com/ is owned by other code and the Vuejs app needed to be mounted under http://someaddress.com/app/

Finally I found the solution which is two part:

  1. Change the assetsPublicPath in the config/index.js file like so:
  dev: {
    env: require('./dev.env'),
    port: 2001,
    autoOpenBrowser: true,
    assetsSubDirectory: 'static',
    assetsPublicPath: '/app/',
    proxyTable: {},
    // CSS Sourcemaps off by default because relative paths are "buggy"
    // with this option, according to the CSS-Loader README
    // (https://github.com/webpack/css-loader#sourcemaps)
    // In our experience, they generally work as expected,
    // just be aware of this issue when enabling this option.
    cssSourceMap: false
  }

  1. In the dev-server.js file, change the connect-history-api-fallback middleware to support a new index path:
app.use(require('connect-history-api-fallback')({
  index: '/app/index.html'
}))


I suggest a change to the template to make it easier to change the base url used for mounting the app. I quick example of the change being something like this:

app.use(require('connect-history-api-fallback')({
  index: config.dev.publicPath + '/index.html'
}))

That dynamic path would need to be parsed but you get the idea. Maybe behind a flag of changeBaseUrl or something like that.

enhancement intend to implement

Most helpful comment

How I finally did it (I serve my backend from an other server)

build/dev-client.js

// add the full path "path=http://localhost:8080/__webpack_hmr"
var hotClient = require(
    'webpack-hot-middleware/client?noInfo=true&reload=true&path=http://localhost:8080/__webpack_hmr')

build/dev-server.js

var devMiddleware = require('webpack-dev-middleware')(compiler, {
  publicPath: webpackConfig.output.publicPath,
  headers: { 'Access-Control-Allow-Origin': '*' }, // add headers for CORS
  quiet: true
})

config/index.js

...
assetsSubDirectory: 'static',
assetsPublicPath: 'http://localhost:8080/', // put the full path here too (for hot-updates)
proxyTable: {},
...

All 17 comments

I've been thinking on this last night. Rather than some multi-option like changeBaseUrl it would be better just to expose the index file option. Something like this:

{
  defaultDocument: `/index.html`
}

// In the dev-server.js

app.use(require('connect-history-api-fallback')({
  index: config.dev.defaultDocument
}))

This then allows the user to set the value to anything rather than just change the sub-path. Couple this with a good documentation example of how to change the Vue application to a sup-path and you are set.

Also, an example which mentions nginx and other proxy solutions would help people searching the internet for it.

Ah, thanks @LinusBorg.
Documentation on those to extra references: https://github.com/jantimon/html-webpack-plugin

I don't think I need to change those setting in my use case however I'm not sure how you would want to expose them to a template user through configuration.

Maybe something like the following config options:

{
  htmlDevServerDefaultDocument: 'index.html',
  htmlTemplate: 'index.html',
  htmlBuildFile: 'index.html'
}

Another option would be to not add these configuration options and just document how to change them and what they do?

I think the browser default document should be added though because in its current state there is no configuration for the 'connect-history-api-fallback' constructor.

Thank you for the direction on getting this going... for me I also had to modify build/dev-client.js to have the __webpack_hmr requesting through the sub path by adding a path argument to the hotclient:

javascript var hotClient = require('webpack-hot-middleware/client?path=/app/__webpack_hmr&noInfo=true&reload=true')

Which if you may also want to consider for your configuration or documentation... Or if there is a better way of accomplishing the above please let me know.

@iAlexanderMoon Hi. I didn't know about this change. Thanks for chiming in. I'll try it out however the client seems to be working ok as it is. I am using nginx as a front-end so it might be handling it for me.

[Edit]
Ah! I was just about to look at this and read the change. I am not having issues because of my nginx config which has this section in it:

location ~ ^/__webpack_hmr {
  proxy_pass http://localnode:2001;
  proxy_redirect off;
  proxy_buffering off;
  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
}

I got this trick in the past from working with browsersync.

I just tried your change and it is not working. Took out the section of the ngnix config and added the path string. The browser is requesting /app/__webpack_hmr which means the path change has taken effect. It is getting a 404 though.

OK, I got it working @iAlexanderMoon. Requires two changes:

1) dev-client.js add the path as you have shown above:

/* eslint-disable */
require('eventsource-polyfill')
var hotClient = require('webpack-hot-middleware/client?path=/app/__webpack_hmr&noInfo=true&reload=true')

hotClient.subscribe(function (event) {
  if (event.action === 'reload') {
    window.location.reload()
  }
})

2) In the dev-server.js add the path option:

var hotMiddleware = require('webpack-hot-middleware')(compiler, {
  path: '/app/__webpack_hmr',
  reload: true, // <= I changed this. Do we need it?
  log: console.log // <= I added this. I prefer more feedback in my console.
})

Note: The webpack-hot-middleware options came from here https://github.com/glenjamin/webpack-hot-middleware/blob/master/client.js

Change Dev Server Base URL Config Summary

To change the base url of the dev-server.js which is used during npm run dev on the template, you need to make the following changes. Note that the changes below assume a child path of /app/.

  1. Change the assetsPublicPath in the config/index.js file like so:
  dev: {
    env: require('./dev.env'),
    port: 2001,
    autoOpenBrowser: true,
    assetsSubDirectory: 'static',
    assetsPublicPath: '/app/',
    proxyTable: {},
    cssSourceMap: false
  }

  1. In the build/dev-server.js file, change the connect-history-api-fallback middleware to support a new index path:
app.use(require('connect-history-api-fallback')({
  index: '/app/index.html'
}))

  1. In the build/dev-client.js add the path into the option string for the hot module reload client:
/* eslint-disable */
require('eventsource-polyfill')
var hotClient = require('webpack-hot-middleware/client?path=/app/__webpack_hmr&noInfo=true&reload=true')

hotClient.subscribe(function (event) {
  if (event.action === 'reload') {
    window.location.reload()
  }
})

  1. In the build/dev-server.js file add the path option for the webpack-hot-middleware:
var hotMiddleware = require('webpack-hot-middleware')(compiler, {
  path: '/app/__webpack_hmr',
  reload: true, // <= I changed this. Do we need it?
  log: console.log // <= I added this. I prefer more feedback in my console.
})

  1. If you wish to change the default document from index.html so another name like default.htm then you will need to change the filename/template names in these files and in step 2 above:

https://github.com/vuejs-templates/webpack/blob/master/template/build/webpack.dev.conf.js#L29

https://github.com/vuejs-templates/webpack/blob/master/template/build/webpack.prod.conf.js#L54

@LinusBorg This should be broken up into two problems; default document name and child path.

How I finally did it (I serve my backend from an other server)

build/dev-client.js

// add the full path "path=http://localhost:8080/__webpack_hmr"
var hotClient = require(
    'webpack-hot-middleware/client?noInfo=true&reload=true&path=http://localhost:8080/__webpack_hmr')

build/dev-server.js

var devMiddleware = require('webpack-dev-middleware')(compiler, {
  publicPath: webpackConfig.output.publicPath,
  headers: { 'Access-Control-Allow-Origin': '*' }, // add headers for CORS
  quiet: true
})

config/index.js

...
assetsSubDirectory: 'static',
assetsPublicPath: 'http://localhost:8080/', // put the full path here too (for hot-updates)
proxyTable: {},
...

@BafS 's solution should be added to the README

I could be wrong here however @BafS solution is just proxying. This issue is about child paths.

Any idea how to make the paths in the router js file respect the base url app ?

the router has a base: option, check it out in the docs.

how to set the baseurl on production?

Since we switched to webpack-dev-server, this no longer applies afaics

For anyone looking into how to this with webpack-dev-server.
You just need to change assetsPublicPath and proxy everything that does not match it.

    assetsPublicPath: '/app/',
    proxyTable: {
      '!/app/**': {
        target: 'http://localhost:5000',
        changeOrigin: true
      }
    },

Thanks @schettino72 but i still cant enable hot reloading when using proxy

Was this page helpful?
0 / 5 - 0 ratings