Skip to content

Need a way to use static resources with router.base #4544

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

Closed
loilo opened this issue Dec 13, 2018 · 19 comments
Closed

Need a way to use static resources with router.base #4544

loilo opened this issue Dec 13, 2018 · 19 comments

Comments

@loilo
Copy link

loilo commented Dec 13, 2018

What problem does this feature solve?

Currently, there's no (documented) way to properly use static assets in sites deployed by Nuxt's generate command when the router.base coption is set to something other than /. Resources requested as ~/path/to/resource are correctly rewritten to [router.base]/path/to/resource. Unfortunately, there's no equivalent to that for static resources requested as /resource.


The real-world situation is simple:

  • We develop a site locally under http://localhost:3000/.
  • We want to deploy it as a static site to https://our-site.com/demo, so in production it gets the router.base option set to /demo.

Therefore in local development all static resources should point to / whereas in production they should point to /demo/.

I have created a minimal repro that explains this by example, much better than I could do here in words.

To kickstart the repro, just run:

npx github:Loilo/repro-nuxt-static-base

I believe this is the same issue that has been brought up in #2753.
It has been addressed with the introduction of the render.static.prefix option in #2755 which is however completely undocumented and it's unclear to me how it may solve the issue.

What does the proposed changes look like?

If the render.static.prefix option is actually able to solve this (which I think it's meant to be), it should be documented.

Otherwise, an additional render.static.* option could be introduced to control rewriting requests to static resources.

This feature request is available on Nuxt community (#c8302)
@TheAlexLichter
Copy link
Member

TheAlexLichter commented Jan 5, 2019

added an issue in the docs repo to document the render.static.prefix property.

It is by default set to true to move the static contents directly to the router.base.

nuxt.config.js

export default {
 router: { base: '/t' }
}

Accessing routes

/favicon.ico => /t/favicon.ico


Rewriting static content

<img src="a.jpg"> will be properly loaded

Caveat: <img src="/a.jpg"> will not be rewritten to /t/a.jpg because of the leading /

@loilo
Copy link
Author

loilo commented Jan 5, 2019

Thanks for taking care. For the record (and for possible future folks with the same problem), here's how we solved this issue in our project:

Rewriting regular URLs

For CSS url()s or <img> tags in templates, we use the (undocumented) static alias:

<img src="~static/a.jpg">

Rewriting dynamically created URLs

For cases where webpack cannot rewrite URLs due to dynamic data (e.g. <img :src="filename">), we defined an additional global constant and use it like this:

<img :src="`${STATIC_PATH}/${filename}`">

Making STATIC_PATH available is a little more work. Part of it was adjusting our nuxt.config.js:

const PRODUCTION_BASE_PATH = '/demo';

module.exports = {

  // ...

  // Set the router's base path
  router: {
    base: process.env.NODE_ENV === 'production'
      ? PRODUCTION_BASE_PATH
      : '/'
  },

  // ...

  // Rewrite all occurrences of STATIC_PATH
  build: {
    extend(config, { isDev }) {
      config.plugins.push(new webpack.DefinePlugin({
        STATIC_PATH: JSON.stringify(isDev ? '' : PRODUCTION_BASE_PATH)
      }))
    }
  },

  // ...

  // Make STATIC_PATH available in Vue templates
  plugins: [ '~/plugins/static-mixin.js' ],

  // ...

};

This defines the global STATIC_PATH to equal /demo in production while being an empty string in development.

To make it available in Vue templates, we added the plugins/static-mixin.js, which defines a global mixin and looks like this:

import Vue from 'vue'

Vue.mixin({
    computed: {
        STATIC_PATH: () => STATIC_PATH
    }
})

@TheAlexLichter
Copy link
Member

@loilo Thanks for sharing! 👍

Small suggestion: You could use env to make the static path available in Vue components too so you don't have the "burden" of a global mixin ☺️

@JJCLane
Copy link

JJCLane commented Jul 31, 2019

Just for reference, I've solved this by accessing the base option through the router like so, which seems to achieve the same thing:

<img :src="$router.options.base + $t('footer.logo.src.desktop')" :alt="$t('footer.logo.alt')" />

@alecgerona
Copy link

Is there a way for dynamic routes to be cleanly handled by ~static? It's ugly to have to get the base path every time especially if we have to switch from "/" to "/something" back and forth.

@Kyserbyte
Copy link

Hi,
my solution for the "dynamics URL" was to create a plugin that inject an utility function on every components that is capable to solve the base path.
Like this:

@/plugins/utils.js

export default ({ app }, inject) => {
    inject('_r', (url) => {
        if (url.charAt(0) === '/') {
            return app.router.options.base + url.substr(1);
        }
        return url;
    });
}

adding this as a plugin in you nuxt.config.js like:

plugins: [
        ...
        { src: "@/plugins/utils.js" }
    ],

and using it in your page/components like:

:src="$_r('/img/bg-our-communities.png')"

Of course you can rename the injected function as you like.
It operate only with absolute URL, avoiding changes on relative URL.

@altusgerona it could be useful for you

@alecgerona
Copy link

Thanks @Kyserbyte. Will look into implementing this on future projects. I still hope that Nuxt can provide a cleaner solution for this.

@shainegordon
Copy link

added an issue in the docs repo to document the render.static.prefix property.

It is by default set to true to move the static contents directly to the router.base.

nuxt.config.js

export default {
 router: { base: '/t' }
}

Accessing routes

/favicon.ico => /t/favicon.ico

Rewriting static content

<img src="a.jpg"> will be properly loaded

Caveat: <img src="/a.jpg"> will not be rewritten to /t/a.jpg because of the leading /

This Caveat is extremely important and is not documented here: https://nuxtjs.org/guides/directory-structure/static/#static-asset-prefix

@cschweda
Copy link

cschweda commented Sep 15, 2020

Vue 3, as I understand it, won't have mixins -- so the mixin method above won't work. We're using it now -- and it works fine -- but it looks like it's not future-proof.

Is there a simple way to switch between the router base in prod and dev in Nuxt?

(I'm using a router base -- i.e., /example/ for prod -- but just localhost:3000 (just /) for dev.

@CroMarmot
Copy link

Any way use this base in command line? I have different base href in different platform

Angular has command ng build --prod --base-href=/foobar/. Is there a similar way ?

@jurieo
Copy link

jurieo commented Apr 6, 2021

added an issue in the docs repo to document the render.static.prefix property.
It is by default set to true to move the static contents directly to the router.base.
nuxt.config.js

export default {
 router: { base: '/t' }
}

Accessing routes
/favicon.ico => /t/favicon.ico
Rewriting static content
<img src="a.jpg"> will be properly loaded
Caveat: <img src="/a.jpg"> will not be rewritten to /t/a.jpg because of the leading /

This Caveat is extremely important and is not documented here: https://nuxtjs.org/guides/directory-structure/static/#static-asset-prefix

Hi ,I want to use it in CSS like background-image: url("/images/nuxt.png");, what should I do? And /favicon.ico still not work. Thanks!

config

// nuxt.config.js 
// version:2.15.3
router: {
    base: "/test-static",
  },

image

@filippodicostanzo
Copy link

added an issue in the docs repo to document the render.static.prefix property.
It is by default set to true to move the static contents directly to the router.base.
nuxt.config.js

export default {
 router: { base: '/t' }
}

Accessing routes
/favicon.ico => /t/favicon.ico
Rewriting static content
<img src="a.jpg"> will be properly loaded
Caveat: <img src="/a.jpg"> will not be rewritten to /t/a.jpg because of the leading /

This Caveat is extremely important and is not documented here: https://nuxtjs.org/guides/directory-structure/static/#static-asset-prefix

Hi ,I want to use it in CSS like background-image: url("/images/nuxt.png");, what should I do? And /favicon.ico still not work. Thanks!

config

// nuxt.config.js 
// version:2.15.3
router: {
    base: "/test-static",
  },

image

Same issue

@phiberber
Copy link

For some reason this error is only happening with css files... Any update on this?

@phiberber
Copy link

Seems that links inside the head() won't follow the router.base rule. Fixed by adding the path on them.

{ rel: "stylesheet", href: "/vendor/bootstrap/css/bootstrap.min.css" },

to

{ rel: "stylesheet", href: "app/vendor/bootstrap/css/bootstrap.min.css" },

@didacvm
Copy link

didacvm commented Oct 28, 2021

Any updates on this?

@kazomotos
Copy link

Same issue here. My hole app keeps loading because I get a 404 on the _nuxt folder. Is there any solution?

@yaeru
Copy link

yaeru commented Apr 4, 2022

Same problem

@mrleblanc101
Copy link
Contributor

mrleblanc101 commented Jun 13, 2022

@manniL I created a minimal CodeSandbox. https://codesandbox.io/s/stoic-borg-d8t7ck?file=/nuxt.config.js
Only 2 things I did in the nuxt.config.json.

  1. Added target: "static"
  2. Added router.base: "/t/" like in your exemple.

The link to the favicon doesn't get the router.base appended even if render.static.prefix is true by default.
Capture d’écran, le 2022-06-13 à 19 15 34

@Dtphelan1
Copy link

@manniL I created a minimal CodeSandbox. https://codesandbox.io/s/stoic-borg-d8t7ck?file=/nuxt.config.js Only 2 things I did in the nuxt.config.json.

1. Added `target: "static"`

2. Added `router.base: "/t/"` like in your exemple.

The link to the favicon doesn't get the router.base appended even if render.static.prefix is true by default. Capture d’écran, le 2022-06-13 à 19 15 34

I was encountering an identical issue, and was able to fix it by removing the leading slash from the favicon's href. That is, the head in nuxt.config.js should be:

  head: {
    title: "Nuxt.js starter for CSB",
    meta: [
      { charset: "utf-8" },
      { name: "viewport", content: "width=device-width, initial-scale=1" },
      {
        hid: "description",
        name: "description",
        content: "Official Nuxt.js starter for CodeSandBox"
      }
    ],
    link: [{ rel: "icon", type: "image/x-icon", href: "favicon.ico" }] // **Removed the leading slash here**
  },

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