Skip to content

Better publicPath in webpack.conf #200

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

Open
zhangxin840 opened this issue Jul 20, 2016 · 33 comments
Open

Better publicPath in webpack.conf #200

zhangxin840 opened this issue Jul 20, 2016 · 33 comments

Comments

@zhangxin840
Copy link

Setting publicPath of webpack.conf to '/' is unnecessary. This will break the app if served form local file system, or a PhoneGap package.

@chrisvfritz
Copy link
Contributor

@zhangxin840 I believe that was originally added because it was required for code splitting. Have you checked that code splitting still works when it's not set?

@mixedCase
Copy link

I'm a bit new to the whole SPA/JS/WebPack/modern webdev kerfuffle, could I be of help somehow? Building with build.assetsPublicPath set to './' the default template (also adding the component) works just fine and all scripts seem to be built correctly and load. Is that example too simple to test what you believe may break @chrisvfritz ?

@zhangxin840
Copy link
Author

@chrisvfritz I set assetsPublicPath to '' and nothing goes wrong(at least in the project).

@LinusBorg
Copy link
Contributor

LinusBorg commented Sep 8, 2016

publicPath != assetsPublicPath

without an absolute public path, webpack fails to load split chunks when the url has changed (e.g. from using vue.router).

@mixedCase
Copy link

@LinusBorg Regardless it fixes the problem. I now am able to run my application over file:// with no issues. Everything builds just fine, I can serve the files just fine.

@LinusBorg
Copy link
Contributor

Yes, but we are not discussing assetPublicPath here.

@mixedCase
Copy link

@LinusBorg I think you're losing sight of the problem in favor of the details. In this case @zhangxin840 mentioned the problem explicitly. Changing assetsPublicPath to './' (instead of publicPath) solves the problem and everything seems to work on my end just fine afterwards, which was @chrisvfritz's worry.

In any case, how would I go about reproducing the problem you mentioned? Do you mean LiveReload breaks? Because the change is only applied to the build script, not dev.

@LinusBorg
Copy link
Contributor

when you use vue-router (or change the url history any other way), a relative publicpath (and most likely, also assetPublicPath will break your build.

At least I personally experienced that webpack will try to fetch chunks (from code splitting) relative to the current URL if public path is not absolute - which will fail if you are not in the root.

@mixedCase
Copy link

I use vue-router in my project. I have not touched publicPath, only assetPublicPath. As I said, everything builds and works just fine.

@LinusBorg
Copy link
Contributor

have you used code-splitting?

@mixedCase
Copy link

@LinusBorg I'm using ES6 modules. They compile together just fine.

@mixedCase
Copy link

@LinusBorg This is still a bug and should be reopened. In config/index.js changing build.assetsPublicPath to './' and leaving dev.assetsPublicPath fixes serving over file:/// protocol while at the same time allowing the npm run dev webserver to keep working.

Everything builds correctly in both situations. The files in dist can be used both over file and tested hosting them with python -m http.server and npm's http-server package with no issues found.

I haven't seen an example using code-splitting to test wether it breaks or not. But not working under Cordova is as much an issue.

@LinusBorg
Copy link
Contributor

LinusBorg commented Oct 22, 2016

This is still a bug

I fail to see why a config setting's default value should be considered a bug, just because it does not fit your specific usecase. If you need another value, change the config setting, that's what it is for.

Everything builds correctly in both situations.

Did you test with vue-router? Because relative asset Paths will break paths to your assets when using vue-router in history mode, which is a very popular usecase (or manipulate history API any other way): When you navigate from '/' to '/users', an asset's path will change with it, i.e. from './logo.png' will now point to './users/logo.npg' - and the file won't exist at that path, of course.

@mixedCase
Copy link

It's not "my" usecase. It's the default config breaking the file:/// protocol. Whenever it started doing that it became a bug. Not to mention that this not only affects Cordova (currently the only way to deploy Vue as a mobile application, at least until Weex starts supporting it) but pretty sure also affects Electron, another huge platform for cross-platform desktop development.

I'm using vue-router and just tested history mode with nginx. Works perfectly with assetsPublicPath set to './'.

@LinusBorg
Copy link
Contributor

LinusBorg commented Oct 22, 2016

When you build for production, it even tells you that the result is not intended to be used from file://.

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

It's not a bug. It's a default value that you have to change if you want to do something that the default is not intended for.

@LinusBorg
Copy link
Contributor

LinusBorg commented Oct 22, 2016

And, as explained at the very beginning of this issue, an absolute path is required for code splitting. That's a fact.

If you need a relative path for cordova, no problem . Change the setting, done.

@mixedCase
Copy link

I'd say with quite some confidence that the file:/// protocol is a bigger standard than code-splitting and therefore has more merit as a default.

But even if the default is not changed, even if there's a consensus among all devs that Electron, Cordova, the Principle Of Least Astonishment and standard local development all together matter less than code-splitting, shouldn't it be acknowledged in some place beside this issue (like the message shown on build you mentioned or an alternative build script that supports the norm of file:/// working) that there's a way to build without breaking the mentioned standard?

@LinusBorg
Copy link
Contributor

LinusBorg commented Oct 22, 2016

The question which is the bigger standard is not as important as the question what the default purpose of the template is.

Which is single file web applications, potentially big ones, which need code splitting (we advertise for it in various locations of our docs).

This template is simply not meant for mobile applications first and foremost. (and eg for electron there are templates provided by the community that are far better suited as a starting point than this one)

However,, note in the config can never be a bad idea., so I will reopen this issue for that.

But someone else will have to pick up as I'm on vacation for the next ten days.

@LinusBorg LinusBorg reopened this Oct 22, 2016
@chrisvfritz
Copy link
Contributor

I can add that note, though first I'd love to hear what other templates people are using and enjoying for mobile/electron. I'd like to add a few alternatives rather than just saying, "No!" 😄

@asselin
Copy link

asselin commented Feb 18, 2017

I ran a simple test on the latest template with code splitting and setting assetsPublicPath to './', and everything seems to work fine. Take a look at https://github.com/asselin/vue-webpack-codesplit-test.

Does this resolve the final concern about changing assetsPublicPath to './' as a default?

Setting assetsPublicPath to './' fixes Cordova, file://, and serving from a higher directory (e.g. building into test/dist and serving test/), so it would be nice to make it the default if it there are no remaining reasons not to.

cc: @LinusBorg @chrisvfritz @mixedCase

@LinusBorg
Copy link
Contributor

Yeah, guess we should change it.

@LinusBorg LinusBorg self-assigned this Feb 18, 2017
@asselin
Copy link

asselin commented Feb 21, 2017

@LinusBorg Is there anything I can do to help get this change in?

@LinusBorg
Copy link
Contributor

We accept PRs :)

@asselin
Copy link

asselin commented Feb 21, 2017

@LinusBorg Submitted PR #541 for this issue. Also, could you please take a look at PR #530 at the same time? It fixes a similar type of path issue loading fonts.

Thanks!

@asselin
Copy link

asselin commented Feb 22, 2017

@LinusBorg I tested vue-router history mode, and ran into some issues. If the URL is only 1 level deep (e.g. /index.html or /menu), everything works fine. If it's 2+ levels deep (e.g. /user/menu), the relative URLs break.

Having said that, I'd still like to make a case for changing the default.

  1. I checked 3 sites that use history mode: Facebook, Twitter, and Blogger. All 3 sites serve their static assets from absolute URLs from a completely different top level path or domain. For example, all of Twitter's static assets are served from https://abs.twimg.com, and all of Facebook's are served from https://www.facebook.com/rsrc.php/. My suspicion is that they did that so that the app servers don't have to serve static resources, and instead they're served by dedicated web servers and/or a CDN. Since this seems to be common (perhaps best) practice, in production, if you're going to use history mode, you'd wind up changing assetsPublicPath anyway, and not using the default.
  2. I agree with @mixedCase that history mode is used less often than a) serving an app out of a subdirectory (i.e. building to /app/dist and serving /app) b) serving from file:// (especially Cordova)
  3. The template's use of vue-router doesn't enable history mode. I assume this is done because history mode doesn't work unless you configure your webserver correctly. IMO, since history mode isn't enabled by default in the template, it's inconsistent to default assetsPublicPath to '/' so that history mode works. My suggestion is to add a chapter to the documentation "Enabling HTML history mode" that has step by step what to do to make it work (e.g. 1. Change assetsPublicPath 2. Add "mode: 'history'" 3. Configure your server per https://router.vuejs.org/en/essentials/history-mode.html etc.)

Alternatively, if you're concerned about changing the default and breaking support of history mode, how about a question in the template "Enable HTML5 history mode?" that would configure assetsPublicPath to '/' and add mode: 'history' if Yes was selected?

@LinusBorg
Copy link
Contributor

LinusBorg commented Feb 23, 2017

That sounds good so far, but I think there's one testcase still missing:

Lazy-loading a component in a nested route. The reason that this could be a special case is that for lazy-loaded components, styles are not extracted into the seperate .css file - instead they are injected into the page's head section when the component is loaded.

That means that with lazy-loaded routes, you may end up with CSS in your <head> that points to a wrong bakground-image etc.

As I said, paths in webpack can be very tricky... :/

I agree with @mixedCase that history mode is used less often than a) serving an app out of a subdirectory (i.e. building to /app/dist and serving /app) b) serving from file:// (especially Cordova)

  1. To serve from a subdirectory, just change the assetsPath. We should improve the docs for this (no matter what path we take in the end -pun inteded), though, and make it easy to customize it during build with an ENV variable or something.
  2. I don't agree with the sentiment that history mode is used more often. I get nearly zeroi questions about cordova on SO and our forums, and some about subdirectories, but many more about history mode. Also, this template is not built with cordova, electron or any other wrapping technology in mind. It's built for websites first and foremost, and I don't think it would be a good idea to turn it into a "one size fits all" mutant-beast.

That is not to say that we can't switch to relative paths at all - we still have to do some tests.

But if relative paths have problems with lazy-loaded routes and other edge cases, I would rather vote for staying with defaults that work best for a typical webapp, rather than something like cordova, which is not a focus of this template.

@asselin
Copy link

asselin commented Feb 23, 2017

@LinusBorg Thanks for the reply. I'll take a look at lazy loaded components with assetsPath set to './' and see what's what.

I agree with you that Cordova isn't a focus for this template; I'm working on a Cordova template that I hope to publish soon.

Thinking about this some more, assuming lazy loaded components work, I think that adding a question at creation time about enabling history mode makes the most sense, that way the generated code is consistent.

I'll let you know what I find soon. Thank you!

@zannet
Copy link

zannet commented May 4, 2017

assetsPublicPath setting to './' not working on Cordova when enabling vue-router lazy loading feature(webpack code splitting), unable to load file:/// resource, how to solve this?

@LinusBorg
Copy link
Contributor

LinusBorg commented May 4, 2017

Please don't highjack issues to ask support questions. I saw you already asked on the forum.

@cristijora
Copy link

cristijora commented Sep 12, 2017

Hi everyone. I also think that this can be somehow improved.
Setting assetsPublicPath: '', allows for local usage, hosting as a static website and as I see in the comments above, cordova apps.
While assetsPublicPath: '/', covers more use-cases it forces to use some sort of web server to serve your website.
I think this stuff should be at least very well explained in the docs so it doesn't create confusion

Side note regarding code splitting: Code splitting works fine when used locally as a static website if the path is set to ''.

@LinusBorg LinusBorg removed their assignment Nov 20, 2017
@AbdullaevTimur
Copy link

You can solve this problem in the following way (If you are use vue-webpack-template):

  1. In your config/index.js in build options change your assetsPublicPath on "" or "./".
  2. Then in build/webpack.base.conf.js do the next trick in your fonts loaders options ("url-loader" or "file-loader"): { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: utils.assetsPath('fonts/[name].[hash:7].[ext]'), publicPath: process.env.NODE_ENV === 'production' ? '../../' : '/' } },
  3. And it is not necessary to use mode: "history" in vue-router

These settings are very useful for building applications using Cordova/Phonegap

@chamantonio
Copy link

chamantonio commented Jul 26, 2018

@AbdullaevTimur this finally worked for me! Thank you!
Just so other who the same setup as mine, you can try his points.

My setup:

  • vue-webpack wrapped in cordova

I had the ff issues:

  • working fine when app is ran using webpack-dev-server
  • only the App.vue is displayed , not all my other components called by when ran using www/dist/index.html --> therefore same behavior for the android build and all other Cordova builds.

Now working fine!

@vallemar
Copy link

vallemar commented Jun 11, 2020

I am setting publicPath: "./" but this doesn't work, the generated path is "js/...." and it should be "./js/...." In the documentation section it says this is possible but it doesn't work.

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

No branches or pull requests

10 participants