Hi,
I found a behaviour, that I think could be a bug of some sorts. I'm building quite a large site using Nuxt, and using different CSS frameworks for the client frontend and admin backend: Foundation in the front, Bootstrap in the back. Sort of a CSS framework mullet :) All the frontend pages are using "frontend" layout, everything in the backend is using "admin" layout. When performing standard navigation from the frontend to admin (or reveresed) everything works just fine.
However, if you navigate _programatically_ to a page using another template (using either $router.push or $router.replace), styles imported by the previous template are note being removed.
To make illustrating the issue easier I created a very minimalistic repo with fresh install of Vuex 1.0.0:
https://github.com/mmieluch/nuxt-templates-styles-issue
yarnyarn devhttp://localhost:3000.There are two templates in this repository: one is setting main's background colour (and nothing else), the other one is setting main's border (again - and nothing else). However, when you start visiting links, you can see that both styles are being applied; and they shouldn't be.
You can use scoped css in style, then CSS will apply to elements of the current layout.
<style scoped>
main {
background-color: hotpink;
}
</style>
If you want to import external css lib, you can also:
<style src="~/assets/demo.css" scoped></style>
@clarkdo Firstly, with all due respect, I still think that is a bug. A component should not leak any of its assets. If I unmount a component, I expect it to clean up after itself. Yes, sometimes we help it a bit in the beforeDestroy handler, but stuff like CSS should be handled automatically.
Secondly, with the approach you're proposing, we'd be left with two very large chunks of CSS code in browsers memory. That's not good for optimisation.
Hi @mmieluch
Thank you for this good bug report, sadly @clarkdo solution is the only one at the moment.
Vue does not support removal of CSS when the component is unmounted injected into the page, see https://forum.vuejs.org/t/help-imported-css-styles-conflict-between-components/5687/8
What you can do is to use normal link between these two part of you applications (it's not such a pain and avoid a lot of conflicts for CSS).
@Atinux @clarkdo Ah, I see. So the "problem" lies with vue-loader. Well, I somewhat disagree with Linus' reasoning in the post you linked, Sébastien, but I guess we'll all have to live with it. Thanks for your time, both of you!
@mmieluch If I was able to find an easy solution, I would have implemented, trust me, I had this issue and it bothered me as well :/
@Atinux Just as a follow-up to this discussion, I took a somewhat different approach to solving this issue :) Unfortunately the proposed solution doesn't really work with CSS frameworks, as the framework styles (when scoped) won't affect child components with scoped styles without >>> modifier. And let's face it, applying that everywhere would be a gigantic mess. Plus, I'm not really comfortable with using that strange structure on a regular basis.
What I did was a bit hacky, but works for our application. In our case everything under /admin should use Bootstrap, Foundation otherwise. So I wrote a middleware that performs a two-way check of previous and current routes. If one starts with /admin, and the other does not, I order the browser to do a full page reload, therefore fetching stylesheets only for that particular area.
I think it could also be somehow done as a layout middleware, but I applied it globally. Works like a charm ;)
This is awesome! I like this solution :)
How did you perform full page reload to the browser?
On Wed 17 Jan 2018 at 23:21, Michał Mieluch notifications@github.com
wrote:
@Atinux https://github.com/atinux Just as a follow-up to this
discussion, I took a somewhat different approach to solving this issue :)
Unfortunately the proposed solution doesn't really work with CSS
frameworks, as the framework styles (when scoped) won't affect child
components with scoped styles without >>> modifier. And let's face it,
applying that everywhere would be a gigantic mess. Plus, I'm not really
comfortable with using that strange structure on a regular basis.What I did was a bit hacky, but works for our application. In our case
everything under /admin should use Bootstrap, Foundation otherwise. So I
wrote a middleware that performs a two-way check of previous and current
routes. If one starts with /admin, and the other does not, I order the
browser to do a full page reload, therefore fetching stylesheets only for
that particular area.I think it could also be somehow done as a layout middleware, but I
applied it globally. Works like a charm ;)—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/nuxt/nuxt.js/issues/2561#issuecomment-358468588, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AA3OFDFdddIoA1XpgaemltZA2UV8Ynz2ks5tLnJngaJpZM4RavaA
.
So here's my solution, but I recon it could be done in a more elegant way.
~/middleware/force-reload-on-scope-change.js
export default function (context) {
if (typeof window === 'undefined') return
// Copy path strings to new strings (without referencing them).
const prev = context.from.fullPath.slice(0)
const current = context.route.fullPath.slice(0)
const prefix = '/admin'
if (
(prev.startsWith(prefix) && !current.startsWith(prefix)) ||
(!prev.startsWith(prefix) && current.startsWith(prefix))
) {
window.location.href = context.route.fullPath
}
}
nuxt.config.js
module.exports = {
router: {
middleware: [
'force-reload-on-scope-change',
],
},
}
That's all there is to it, really :)
Actually I like this solution and it's in just a few lines of code, there is always a more elegant way, but for the problem here, this one is at the moment, the most elegant one :)
My thoughts exactly. Glad I could throw an idea in the bucket of solutions :)
Did anybody try to link the '/frontend' and '/admin' pages with ' tag? So nuxt is doing a hard reload?
@jfcmoeller Yes it dose. And that's what Atinux suggested in his first comment. But IMHO @mmieluch 's solution is better in this specific case.
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment
So here's my solution, but I recon it could be done in a more elegant way.
~/middleware/force-reload-on-scope-change.jsnuxt.config.jsThat's all there is to it, really :)