Vue-cli: Allow custom publicPath to be set alongside baseUrl

Created on 14 Sep 2018  路  14Comments  路  Source: vuejs/vue-cli

What problem does this feature solve?

Right now any attempt to set publicPath prevents the bundle from compiling with the following error:

Configuration Error: Avoid modifying webpack output.publicPath directly. Use the "baseUrl" option instead.

I understand why that validation is there, as it prevents accidental misconfiguration when users aren't aware of the baseUrl option. That said, there should be some way to bypass this error (or make it a warning).

My bundle gets served from my webapp which is running on a different localhost port (let's say 4000). As such, HMR attempts to load from http://localhost:4000/xxx instead of http://localhost:8080/xxx. I can't put the http://localhost:8080/ in the baseUrl because it simply tacks that onto itself (http://localhost:8080/http://localhost:8080/).

I really just need to override the publicPath for webpack, but keep the baseUrl exactly as it is. I've tried a thousand different things but there doesn't seem to be any other way around this.

What does the proposed API look like?

Either make it a warning, or add some kind of flag that says "hey, I know about baseUrl and I've set it, I just also want to set publicPath too."

Frankly, if both baseUrl and publicPath are set, it can probably be assumed that it's intentional. Maybe only display the error if publicPath is set without baseUrl.

cli-service serve

Most helpful comment

I stand corrected! It really seems like that should work, however, for some reason public only seems to affect the initial request (i.e. http://localhost:8080/sockjs-node/info?t=1537018718015).

After that, subsequent requests are still made to my app server (http://localhost:4000/09018356538331e29b1e.hot-update.json).

I've tried combining devServer.public and devServer.publicPath but it does not change the fact that it is still looking for the files relative to the window's location.

That said, I did try commenting out the validation code in validateWebpackConfig.js and it works with the (non dev-server) publicPath!

So this does not work:

module.exports = {
    devServer: {
        public: 'localhost:8080',
        publicPath: 'http://localhost:8080/',
        headers: {
            'Access-Control-Allow-Origin': '*',
        },
    },
}

But this does:

module.exports = {
    devServer: {
        headers: {
            'Access-Control-Allow-Origin': '*',
        },
    },

    configureWebpack: {
        output: {
            publicPath: 'http://localhost:8080/',
        },
    },
}

It's also worth noting that it isn't just the hot-update.json files that fail to load with the first method. Images and other static assets only load with the second option.

All 14 comments

Isn't devServer.public the better solution to your problem of HMR contacting the wrong backend?

Have you actually tried of changing the publicPath would solve your problem (by temporarily commenting out the codes raising the error in /node_modules/)?

The error is raised because we need to match the public path and some. Other paths we are setting, Changing it like you want to should most likely break the build.

Ah, shoot, I tried changing devServer.publicPath but I completely missed devServer.public. Judging from the docs that鈥檚 exactly what I need. Thanks!

I stand corrected! It really seems like that should work, however, for some reason public only seems to affect the initial request (i.e. http://localhost:8080/sockjs-node/info?t=1537018718015).

After that, subsequent requests are still made to my app server (http://localhost:4000/09018356538331e29b1e.hot-update.json).

I've tried combining devServer.public and devServer.publicPath but it does not change the fact that it is still looking for the files relative to the window's location.

That said, I did try commenting out the validation code in validateWebpackConfig.js and it works with the (non dev-server) publicPath!

So this does not work:

module.exports = {
    devServer: {
        public: 'localhost:8080',
        publicPath: 'http://localhost:8080/',
        headers: {
            'Access-Control-Allow-Origin': '*',
        },
    },
}

But this does:

module.exports = {
    devServer: {
        headers: {
            'Access-Control-Allow-Origin': '*',
        },
    },

    configureWebpack: {
        output: {
            publicPath: 'http://localhost:8080/',
        },
    },
}

It's also worth noting that it isn't just the hot-update.json files that fail to load with the first method. Images and other static assets only load with the second option.

(see below for a reproduction code)

Same issue here... Modifying validateWebpackConfig.js doesn't seem to be a good idea.

The problem is that the index.js dynamically loads the dynamic components:

/******/    // script path function
/******/    function jsonpScriptSrc(chunkId) {
/******/        return __webpack_require__.p + "" + ({"vendors.spgrid":"vendors.spgrid","spgrid":"spgrid"}[chunkId]||chunkId) + ".js"
/******/    }

It uses __webpack_require__.p:

/******/    // __webpack_public_path__
/******/    __webpack_require__.p = "/";

Because I'm using a different server (https://myserver/some/path/), it tries to load the resource from this server instead of the dev server:

https://myserver/vendors.spgrid.js instead of https://localhost:18827/vendors.spgrid.js.

There is a match that is done by jsonpScriptSrc:

// {"vendors.spgrid":"vendors.spgrid","spgrid":"spgrid"}
{
  "vendors.spgrid":"vendors.spgrid",
  "spgrid":"spgrid"
}

I'm not sure where it could be defined, but maybe it could be replaced by the below (instead of using publicPath):

{
  "vendors.spgrid":"https://localhost:18827/vendors.spgrid",
  "spgrid":"https://localhost:18827/spgrid"
}

Reproduction

  1. Clone https://github.com/Aymkdn/vue-cli-issue-2525
  2. npm install
  3. npm run serve (it launchs the dev server on port 2525).
  4. Open Chrome with disabling security: chrome.exe --disable-web-security --user-data-dir --ignore-certificate-errors
  5. Go to https://codepen.io/Aymkdn/pen/ePOEaX

In the console of CodePen you'll see:

GET https://codepen.io/helloworld.js 404 ()

Instead of:

GET https://localhost:2525/helloworld.js 404 ()

It's because HelloWorld is a dynamic component (see src/App.vue)

And the simple config:

module.exports = {
  devServer:{
    https:true,
    port:2525,
    host:'localhost',
    public:'localhost:2525'
  }
}

Same need/problem here :)

I am having this issue too. Using .NET Core to proxy the vue cli server for local dev. I think another option would be to allow a relative path for the HMR, so it would work no matter which URL. Alas, putting '/' does not work.

We have the same need for development environment

    devServer: {
      headers: {
        'Access-Control-Allow-Origin': '*'
      }
    },
    baseUrl: 'http://localhost:8081/'

Setting the base url works but it seems odd

image

@ralphchristianeclipse Agreed that this seems odd, but modifying vue.config.js is better than going and modifying dependency code. I had to make a small modification to get my dev and production builds working.

module.exports = {
  baseUrl: process.env.NODE_ENV === 'production'
    ? '/'
    : 'http://localhost:8080',

  devServer: {
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  },

I just ran into this same issue. I'm running Vue CLI inside a Vagrant box with SSL configured. Setting public and publicPath to something like https://dev.domain.com:8080 gets everything working _except_ for hot-update.json which ignores the port and makes the request to https://dev.domain.com. Adding baseUrl solved that and everything is working correctly but baseUrl triggers the warning that it is deprecated and to use publicPath (which again, I already am). Any ideas of another way to resolve this?

I was able to solve with both baseUrl and publicPath. I had problems with 'hot.update.json' files, for hot-reload: without baseUrl or publicPath the client pointed to localhost instead of the dev server address in the local network. In fact the webpack_require__.p address was '/' and not the ip of the server.
I'm using

"webpack": "^4.17.1",
"@vue/cli-service": "^3.0.1",

With baseUrl being removed with v4.0, what would be the workaround for this need?

Happy to report this is no longer an issue! I just tested this on v4.0, but it looks like it was actually fixed somewhere even before that. The important difference is that devServer.public is properly causing HMR to load updates from the other port.

For reference, here's a working configuration for those who want to force the browser to load the bundle and HMR updates from http://localhost:8080/:

// Change this to match the path to your files in production (could be S3, CloudFront, etc.)
const DEPLOYMENT_PATH = '/static/'

module.exports = {
    publicPath: process.env.NODE_ENV === 'production' ? DEPLOYMENT_PATH : 'http://localhost:8080/',

    devServer: {
        public: 'localhost:8080',
        headers: {
            'Access-Control-Allow-Origin': '*',
        },
    },
}

I done it by.
Step 1: checked vue/cli version
C:\Users***>vue --version
@vue/cli 4.3.1
Step 2: Created vue.config.js just inside project in Visual studio code
Step 3: Added below code in vue.config.js
// vue.config.js
module.exports = {
publicPath: '/tkm'
}

Was this page helpful?
0 / 5 - 0 ratings