vuejs / vue-cli

🛠️ webpack-based tooling for Vue.js Development
https://cli.vuejs.org/
MIT License
29.76k stars 6.33k forks source link

vue-cli-service serve serving stale app.js in dev mode on safari #2509

Open daetal-us opened 6 years ago

daetal-us commented 6 years ago

Version

3.0.3

Node and OS info

yarn 1.9.4

Steps to reproduce

https://github.com/vuejs/vue-cli/commit/0909bc86880d526e4015c3e642e9afa63adab2b1

What is expected?

serving via vue-cli-service serve serves up app.js on demand when developing in safari

What is actually happening?

a stale app.js is served and never updated following changes (hot-reloaded) in safari


creating issue for tracking since I couldn't find anything in issues (had to dig through commits and file changes)

daetal-us commented 6 years ago

I believe the out-of-box caching strategy suffers a few misconfigurations at the moment.

This is only a "real" issue in Safari at the moment but I submit:

  1. The weak Etag strategy is incorrect and should instead default to strong given the underlying etag generation process implications and representative validation values and,
  2. Cache-Control should be explicitly communicated as must-revalidate to the browser (otherwise left to suffer the unpredictability of browser defaults e.g. Safari aggressively caching "main resources")

In userland, you can configure your server via vue.config.js as follows:

module.exports = {
  devServer: {
    ...,
    before: app => {
      app.set('etag', 'strong')
      app.use((req, res, next) => {
        res.set('Cache-Control', 'must-revalidate')
        next()
      })
    }
  }
}

@sodatea: thoughts?

haoqunjiang commented 6 years ago

Thanks for the great help! Will add this fix to the next patch.

haoqunjiang commented 6 years ago

Well, this fix does not seem to work on my machine… image

daetal-us commented 6 years ago

@sodatea I ran into this initially as well; I could be wrong but I believe this particular scenario is only reached if the browser has already cached app.js with the previous headers and is managing cache accordingly -- before the updated headers. That is, this scenario should only arise when modifying cache-related headers. Emptying cache entirely and starting with a fresh initial load of app.js with the updated headers should, from there, appropriately validate/invalidate.

daetal-us commented 6 years ago

@sodatea you are correct. This remains an open issue in webkit.

I do think the header changes are technically still appropriate for more general purposes.

For this specific issue, my final solution has been to utilize filename hashing:

module.exports = {
  configureWebpack: {
    output: {
      filename: '[name].[hash].js'
    }
  },
  ...
}
JackyChan commented 5 years ago

Seems to be a problem with preload,remove the preload plugin fixed the problem.

// vue.config.js
module.exports = { 
  chainWebpack: (config) => {
    if (process.env.NODE_ENV === 'development') {
      config.plugins.delete('preload')
    }
  }
}
cdll commented 4 years ago

feel upset that

// file: vue.config.js
module.exports = {
  //...
  configureWebpack: {
    //...
  },
  chainWebpack (config) {
    config.plugins.delete('preload')
  }
}

not working for me...

ansf commented 3 years ago

We recently updated @vue/cli from 4.5.13 to 5.0.0-beta.4. Using safari 14.1.2 it seems to work now without any workarounds.