vuejs / vue

This is the repo for Vue 2. For Vue 3, go to https://github.com/vuejs/core
http://v2.vuejs.org
MIT License
207.73k stars 33.68k forks source link

CLI service IMHO is too smart with message "Avoid modifying webpack output.publicPath directly". What if we really need it? #12247

Closed ivictbor closed 3 years ago

ivictbor commented 3 years ago

Version

@vue/cli-service 3.5.0

Environment info


  System:
    OS: Linux 4.19 Ubuntu 20.04.2 LTS (Focal Fossa)
    CPU: (12) x64 Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
  Binaries:
    Node: 12.22.1 - /usr/bin/node
    Yarn: 1.17.3 - /mnt/c/Program Files (x86)/Yarn/bin/yarn
    npm: 7.11.1 - /usr/bin/npm
  Browsers:
    Chrome: Not Found
    Firefox: Not Found
  npmPackages:
    @fortawesome/vue-fontawesome: ^0.1.8 => 0.1.10 
    @vue/babel-helper-vue-jsx-merge-props:  1.2.1 
    @vue/babel-plugin-transform-vue-jsx:  1.2.1 
    @vue/babel-preset-app:  3.12.1 
    @vue/babel-preset-jsx:  1.2.4 
    @vue/babel-sugar-composition-api-inject-h:  1.2.1 
    @vue/babel-sugar-composition-api-render-instance:  1.2.4 
    @vue/babel-sugar-functional-vue:  1.2.2 
    @vue/babel-sugar-inject-h:  1.2.2 
    @vue/babel-sugar-v-model:  1.2.3 
    @vue/babel-sugar-v-on:  1.2.3 
    @vue/cli-overlay:  3.12.1 
    @vue/cli-plugin-babel: ^3.5.0 => 3.12.1 
    @vue/cli-plugin-eslint: ^3.5.0 => 3.12.1 
    @vue/cli-plugin-pwa: ^4.5.10 => 4.5.13 
    @vue/cli-service: ^3.5.0 => 3.12.1 
    @vue/cli-shared-utils:  3.12.1 (4.5.13)
    @vue/component-compiler-utils:  3.2.0 
    @vue/eslint-config-airbnb: ^4.0.0 => 4.0.1 
    @vue/eslint-config-prettier: ^4.0.1 => 4.0.1 
    @vue/eslint-config-standard: ^4.0.0 => 4.0.0 
    @vue/preload-webpack-plugin:  1.1.2 
    @vue/web-component-wrapper:  1.3.0 
    emoji-mart-vue-fast: ^8.0.3 => 8.0.3 
    eslint-plugin-vue: ^5.0.0 => 5.2.3 (4.7.1)
    vue: ^2.6.6 => 2.6.12 
    vue-affix: ^0.5.2 => 0.5.2 
    vue-avatar-editor-improved: ^1.0.4 => 1.0.7 
    vue-blurhash: ^0.1.4 => 0.1.4 
    vue-carousel: ^0.18.0 => 0.18.0 
    vue-cli-plugin-webpack-bundle-analyzer: ^2.0.0 => 2.0.0 
    vue-cli-webpack:  1.0.0 
    vue-click-outside: ^1.0.7 => 1.1.0 
    vue-ctk-date-time-picker: ^2.4.0 => 2.5.0 
    vue-custom-scrollbar: ^1.1.0 => 1.4.0 
    vue-debounce: ^2.3.0 => 2.6.0 
    vue-eslint-parser:  5.0.0 (2.0.3)
    vue-hot-reload-api:  2.3.4 
    vue-loader:  15.9.7 
    vue-observe-visibility:  0.4.6 
    vue-resize:  0.4.5 
    vue-router: ^3.0.1 => 3.5.1 
    vue-slicksort: ^1.1.3 => 1.2.0 
    vue-smooth-dnd: ^0.8.1 => 0.8.1 
    vue-style-loader:  4.1.3 
    vue-template-compiler: ^2.5.21 => 2.6.12 
    vue-template-es2015-compiler:  1.9.1 
    vue-virtual-scroller: ^1.0.0-rc.2 => 1.0.10 
    vuejs-datepicker: ^1.6.2 => 1.6.2 
    vuex: ^3.0.1 => 3.6.2 
  npmGlobalPackages:
    @vue/cli: Not Found

Steps to reproduce

Define output.publicPath in vue.config.js

What is expected?

I need a way to pass output.publicPath without this exception message. My usecase:

I serve same Vue SPA on hundreds-thouthands subdomains:

https://sub1.mydomain.com/ https://sub2.mydomain.com/ https://sub3.mydomain.com/ https://sub4.mydomain.com/

etc. Like workpsaces in Slack.

Every time when new user joins service and creates new workpace on new subdomain, it does not hit a cache on CDN because URL is always different https://sub123.mydomain.com/js/app.js, https://sub124.mydomain.com/js/app.js.

So CDN bypasses the request to slower upstream and takes redundant place in caches store by storing same files on different urls.

To solve this, only one simple thing which I need to do is:

 configureWebpack: {
    output: {
      publicPath: process.env.NODE_ENV === 'production'
        ? 'https://sub1.mydomain.com/'

(+add cors settings on serving end) so now the cache on CDN will not be separated and all new users will hit one cache when they load JS/CSS/fonts.

If I use native top-level publicPath option, some Vue runtime code creates a redirect and breaks a route by adding domain there, but I don't want redirect, I really want index.html to be served from https://sub2.mydomain.com/, I only need to change URLs of assets, not route of the application.

I had to destroy validateWebpackConfig.js in my CI build pipeline to solve this issue quickly, and after this, applications works perfectly:

ADD package-lock.json .
ADD package.json .

RUN npm ci

# ugly fix to prevent Avoid modifying webpack output.publicPath directly.
RUN echo "module.exports = function validateWebpackConfig () {}" > 'node_modules/@vue/cli-service/lib/util/validateWebpackConfig.js'

But it would be better if we can disable this "smart mode" and allow some flexibility, at least if we would have an option like allowOutputPublicPath :

if (!singleConfig.allowOutputPublicPath &&  target === 'app' && singleConfig.output.publicPath !== options.publicPath) {
only then drop exception

Is there any better ways to point all statics to be loaded from different domain? This definitely not super popular case, but from time to time developers might need it.

What is actually happening?

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

posva commented 3 years ago

Open this in Vue cli repo