vuejs / vue-cli

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

More assets configuration options #2730

Closed ghenry closed 5 years ago

ghenry commented 5 years ago

What problem does this feature solve?

Setting a custom path for where static files are requested with index.html static file.

It's time to deploy my migrated vue cli 2 to vue cli 3 SPA. I want to put the static files in ../../static but also have the assets served up from href="/static/js/app.a7as86ad8.js" etc. See https://forum.vuejs.org/t/baseurl-at-but-files-within-index-html-to-be-served-at-static/45777/4

On vue cli 2, I had:

build: {
...

// Paths
assetsRoot: path.resolve(__dirname, '../../../'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',

so my SPA lives at app.example.com but within index.html files were served at /static/js and /static/css etc.

What does the proposed API look like?

Allow control over asset paths used in index.html in vue.config.js

LinusBorg commented 5 years ago

The Vue-cli 3.0 equivalent for the assetsPublicPath of the 2.0 webpack template is the baseUrl option in 3.0

Did you try that? The forum thread doesn't indicate it.

ghenry commented 5 years ago

Hi Thor sten,

That would work but the docs state it will affect history mode, which I use. Like I mentioned, this lives at the base url default of /. I can't see any other way.

Thanks.

LinusBorg commented 5 years ago

That would work but the docs state it will affect history mode,

That's not exactly what it states - the warning about history mode is about relative baseURL values only.

You should be able to adjust the base option of router manually to / (it's set to process.env.BASE_URL by default)

ghenry commented 5 years ago

Thanks. This works and I already had base in router set to what I wanted anyway:

// SureVoIP configs - GH
module.exports = {
  devServer: {
    port: 8081,
    overlay: {
      warnings: true,
      errors: true
    }
  },
  baseUrl: "/static/", // just used within index.tt and asset serving within
  outputDir: "../../static",
  indexPath: "../src/client_side/index.tt" // keep in root/src/
}

// SureVoIP common things - GH
const GitRevisionPlugin = require("git-revision-webpack-plugin")
const git = new GitRevisionPlugin({ versionCommand: "rev-parse --short HEAD" })

process.env.VUE_APP_COPYRIGHT = require("./package.json").copyright
process.env.VUE_APP_COMPANY = require("./package.json").company
process.env.VUE_APP_DESCRIPTION = require("./package.json").description
process.env.VUE_APP_VERSION = require("./package.json").version
process.env.VUE_APP_GIT_REV = git.version()

its doesn't feel to clunky. I do feel some docs update for your first comment would be good re assetsPublicPath

Thanks for your time to help.

ghenry commented 5 years ago

Morning. This has actually had an impact with routing for some reason with npm run serve (and probably in prod too as this isn't live yet). My / base alias stopped working for /dashboard, i.e. when I and my test visits "/" :

const router = new VueRouter({
  mode: "history",
  base: "/", // we live at https://portal.surevoip.co.uk/
  linkActiveClass: "active",
  routes: [
    {
      path: "/",
      name: "Container",
      component: Container,
      children: [
        {
          path: "/user/profile",
          name: "UserProfile",
          component: UserProfile,
          meta: { requireRole: false }
        },
        {
          path: "/settings",
          name: "Settings",
          component: Settings,
          meta: { requireRole: true, requiredRoles: ["admin"] }
        },
        {
          path: "/about",
          name: "About",
          component: About,
          meta: { requireRole: false }
        },
        {
          path: "/basket",
          name: "ShoppingBasket",
          component: ShoppingBasket,
          meta: { requireRole: true, requiredRoles: ["admin"] }
        },
        {
          path: "/dashboard",
          name: "Dashboard",
          component: Dashboard,
          alias: "/",
          meta: { requireRole: true, requiredRoles: ["admin", "dashboard"] }
        },
        <snip>

removing baseUrl from vue.config.js below and it works again, so where else is baseUrl used?

// SureVoIP configs - GH
module.exports = {
  devServer: {
    port: 8081,
    overlay: {
      warnings: true,
      errors: true
    }
  },
  baseUrl: "/static/", // just used within index.tt and asset serving within
  outputDir: "../../static",
  indexPath: "../src/client_side/index.tt" // keep in root/src/
}

Thanks.

LinusBorg commented 5 years ago

My / base alias stopped working for /dashboard, i.e. when I and my test visits "/" :

What does "stopped working" mean in that context? What is expected, and what happens instead?

Can you share some kind of runnable reproduction?

ghenry commented 5 years ago

Hi, in that the Dashboard component is no longer displayed unless you navigate to /dashboard, whereas the alias statement presented the Dashboard when visiting /.

ghenry commented 5 years ago

I'll confirm my public/index.html base url vars etc. and report back. Probably typos or missing things.

ghenry commented 5 years ago

Can't reproduce. Closing. Thanks!

ghenry commented 5 years ago

In vue cli 3.3 baseUrlhas been removed which now breaks all of above for me....what do I use now? App lives at https://app.example.com but all assets and initial js in index.html need to be set to /static/js not /js

Thanks.

LinusBorg commented 5 years ago

How does it break things? baseUrl has been deprecated, but not removed, it will be replaced with the new preferred option publicPath in v4.

Nothing changed, really, except the option now has a new preferred name.

ghenry commented 5 years ago

Thanks. I'm preparing for that which doesn't let me set what should go in the path to serve the js in the index template. A a per my original issue report. I'm fact, base url didn't solve that. Still wants to serve the dev app via npm run serve at /static.

On Fri, 22 Mar 2019, 17:41 Thorsten Lünborg, notifications@github.com wrote:

How does it break things? baseUrl has been deprecated, but not removed, it will be replaced with the new preferred option publicPath in v4.

— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/vuejs/vue-cli/issues/2730#issuecomment-475714290, or mute the thread https://github.com/notifications/unsubscribe-auth/AAJveCE3uY3jMaU9ppDGZf165U8l9g0Kks5vZRXJgaJpZM4Xa2ba .

LinusBorg commented 5 years ago

https://cli.vuejs.org/config/#assetsdir

ghenry commented 5 years ago

Thanks @LinusBorg See https://github.com/vuejs/vue-cli/issues/2730#issuecomment-429769052

That config setting is used for writing out the files on the filesystem which I use, but within the generated index.html (or what ever you set with indexPath) I want the path names for the js to be /static/js/app.xxx.js not /js/app.xxx.js. If I use baseUrl, that does it, but then the publicPathUrl becomes app.example.com/static/ when you do npm run serve.

The static files are all served up via /static/ but there's no way to set that in the generated index file when you use npm run build IF your app lives at app.example.com/.

I thought this was solved months ago and I'm just back on to this now and it's not.

Make sense?

Thanks for reading!

LinusBorg commented 5 years ago

No I don't see the issue. assetsDir will both define the output sub directory and change the src paths in index.html just like you want it to.

And publicPath (previously: baseURL) can be / just like you want it to.

ghenry commented 5 years ago

Ah, I see. Your description doesn't reflect the docs. I think that's my misunderstanding. Will test!

ghenry commented 5 years ago

So if "A directory (relative to outputDir) to nest generated static assets (js, css, img, fonts) under." could be expanded to include "under and define the src paths in index.html (or indexPath)" would be perfect.

LinusBorg commented 5 years ago

I guess the docs description kind of assumes that the reader is aware that this option would break any build if it would not also be reflected in the src paths.

Something to improve i would say

LinusBorg commented 5 years ago

Up for a PR?

ghenry commented 5 years ago

This is driving me mental :-)

module.exports = {
  devServer: {
    port: 8081,
    overlay: {
      warnings: true,
      errors: true
    }
  },
  assetsDir: "static",
  outputDir: "../../static/",
  indexPath: "../src/client_side/index.tt"
}

assetsDir is relative to outputDir, so if I remove static, my whole ../../ gets deleted. --no-remove is not the right option:

hostname ~/src/SureVoIP-Portal/root/src/client_side [client_side*]$ ls ../../static/
apple-touch-icon-114x114.png  apple-touch-icon-152x152.png  apple-touch-icon-72x72.png  favicon-16x16.png    favicon-96x96.png  surevoip-icon-white-80x80.png
apple-touch-icon-120x120.png  apple-touch-icon-57x57.png    apple-touch-icon-76x76.png  favicon-196x196.png  favicon.ico        surevoip_spinner.js
apple-touch-icon-144x144.png  apple-touch-icon-60x60.png    favicon-128.png             favicon-32x32.png    static             TweenMax.min.js

hostname ~/src/SureVoIP-Portal/root/src/client_side [client_side*]$ ls ../../static/static/
css  fonts  img  js

The filenames within index.tt are fine. If I change to:

module.exports = {
  devServer: {
    port: 8081,
    overlay: {
      warnings: true,
      errors: true
    }
  },
  assetsDir: "",
  outputDir: "../../static/",
  indexPath: "../src/client_side/index.tt" // keep in root/src/
}

then the app.xxx.js path goes back to /js/app.xxx.js

and tried:

  assetsDir: "./",
  outputDir: "../../static",
  indexPath: "../src/client_side/index.tt" // keep in root/src/
}
ghenry commented 5 years ago

So, docs are my favourite so I can read about my mistake again. No problem.

LinusBorg commented 5 years ago

assetsDir is relative to outputDir, so if I remove static, my whole ../../ gets deleted. --no-remove is not the right option:

You lost me there, don't understand the problem.

ghenry commented 5 years ago

src=/../static/js/app.a97bf9a6.js in my built index file, using

  },
  assetsDir: "../static/",
  outputDir: "../../static",
  indexPath: "../src/client_side/index.tt" // keep in root/src/
}

I can't use assetsDir: "/", (it's relative to outputDir, so should work, as I get:

⠙  Building legacy bundle for production... ERROR  WebpackOptionsValidationError: Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
 - configuration.output.filename: A relative path is expected. However, the provided value "/js/[name]-legacy.[contenthash:8].js" is an absolute path!
   -> Specifies the name of each output file on disk. You must **not** specify an absolute path here! The `output.path` option determines the location on disk the files are written to, filename is used solely for naming the individual files.
   Please use output.path to specify absolute path and output.filename for the file name.
ghenry commented 5 years ago

I want src=/static/js/app.a97bf9a6.js in my built index file, using like I could do with vue cli 2 - https://github.com/vuejs/vue-cli/issues/2730#issue-369845821

LinusBorg commented 5 years ago

I'm sorry but i still don't get it. assetsDir works just like assetsSubDirectory in the old webpack template so I simply fail to see what the trouble is.

ghenry commented 5 years ago

So back to basics. I'm in:

/home/ghenry/src/SureVoIP-Portal/root/src/client_side

I want to put my index.tt file in the above directory (/home/ghenry/src/SureVoIP-Portal/root/src/client_side).

I want to put the generated js in ../../static/, i.e. ls ../../static/:

app.a97bf9a6.js app.a97bf9a6.js.map app-legacy.f1bc301a.js app-legacy.f1bc301a.js.map chunk-vendors.952d115d.js chunk-vendors.952d115d.js.map chunk-vendors-legacy.401bef6d.js chunk-vendors-legacy.401bef6d.js.map which IS working using:

  },
  outputDir: "../../static",
  indexPath: "../src/client_side/index.tt" // keep in root/src/
}

but within my index.tt file, the served path is /js/app.xxx.js. I want that to be /static/js/app.xxx.js.

No matter what I set assetsDir to be I can't generate /static/js/app.xxx.js.

ghenry commented 5 years ago

That should say:

"but within my index.tt file, the served path is /js/app.xxx.js. I want that to be /static/js/app.xxx.js."

LinusBorg commented 5 years ago
outputDir: "../../",
assetsDir: "./static",
indexPath: "../src/client_side/index.tt" // keep in root/src/

What's a .tt file btw?

ghenry commented 5 years ago

I already tried that https://github.com/vuejs/vue-cli/issues/2730#issuecomment-475782148 and it removes all my files (a functionality which I want to keep so stale js files get removed).

.tt is a Template Toolkit file http://template-toolkit.org/

ghenry commented 5 years ago

So these are in root/src/client_side and outputDir: "../../", will remove all of root/*

LinusBorg commented 5 years ago

Thanks, it finally clicked. phew...

use the --no-delete remove option and clear the static dir yourself, i.e. with the rimraf package, before running the build command.

ghenry commented 5 years ago

That's very smelly and seems like a step back from the lovely set up I had on vue cli 2 :-(

No way to get an extra option to assetsDir that switches off the relative to outputDir part?

ghenry commented 5 years ago

Anyway, thanks for your input. How do I use ramdir in vue.config.js?

ghenry commented 5 years ago

rimraf even

ghenry commented 5 years ago

Ah, I see. I'll put this in package.json

ghenry commented 5 years ago

For others, my package.json is like:

{
  "name": "surevoip-portal-spa",
  "version": "1.0.0",
  "private": true,
  "description": "SureVoIP Portal",
  "author": "Gavin Henry <ghenry@surevoip.co.uk>",
  "scripts": {
    "serve": "vue-cli-service serve",
    "clean": "rmdir ../../static",
    "build": "vue-cli-service build --modern --no-clean",
    "lint": "vue-cli-service lint",
    "docs:build": "vuepress build docs",
    "docs:dev": "vuepress dev docs",
    "test:e2e": "vue-cli-service test:e2e --mode e2e",
    "test:unit": "vue-cli-service test:unit",
    "test:unit:coverage": "vue-cli-service test:unit --collectCoverage"
  },
LinusBorg commented 5 years ago

I would put the rimraf call in the build command:

"rmdir ../../static && vue-cli-service build... 
ghenry commented 5 years ago

Yeah, I was thinking it would be shell interpretated. Thanks.

Anyway, this isn't working for me as nothing is going in the static folder using this method. Back to square one again.

LinusBorg commented 5 years ago

Oh come on! 😅🙈

That has to work. All your doing is emptying the directory before building into it.

But let's let this issue be, we usually are much more strict about usage support.

If you need further help, open a topic on forum.vuejs.org - I'll be there and we'll figure it out.

ghenry commented 5 years ago

No problem. I'm full of the cold and my brain is fuzzy. Will write up on the forum.