Can I avoid duplicate styles with Vue.js components? - vue.js

I'm new to Vue (and the concept of single file components) and not sure how the CSS is compiled when my app is generated.
I have a pattern library where all the SCSS is compiled for my project so I want to pull this into my components. I know I can load in the mixins and variables globally, then I intend on handpicking other blocks of sass if they need to be used to style that component.
What I'm worried about is:
if I keep using the same style definitions in multiple components, will these be duplicated in the compiled css?
If so. how can that be avoided? Eg:
I import the 'headings.scss' in 10 components. Will there be 10 instances of that 'headings.scss' file in the compiled CSS?
I hope that makes sense! Just need some more clarity here.

Yup there will be duplication. But if you are using vuejs webpack template the production build's css is processed by cssnano which will discard duplicated css
note; only exact duplicates will be discarded.

Related

Page specific tailwind classes with SSG

Currently I'm developing a website using the following stack:
vue.js
#vue/server-renderer
vite
tailwind CSS
SSG was chosen as the rendering mode.
Tailwind, as described in the documentation, allows you to specify directories and file extensions (content property) , in which he will try to find the classes, in order to leave only those that are actually used in the project.
As a result, the 'main.css' file is formed, in which only those classes that are used remain.
Next, I just take this file and include it in every page that was rendered during the build phase of the project.
This results in:
index.html - main.css
about.html - main.css
blog.html - main.css
It turns out that main.css file may contain classes that are needed only for one of the pages and are not needed for others.
I would like to implement the following:
Take main.css which turned out
Render a page, for examle about.html
take only those styles that are needed for about.html page from the main.css file
create a new about.css file
link the resulting about.css styles to about.html
I’ve already tried to implement this using an awesome PurgeCSS tool as following:
render page content usind #vue/server-renderer's renderToString() method;
Pass an resulting css and html sources to PurgeCSS
here is an example
But there are too many corner cases around this solution, such as:
Dynamic classes which can be added to the html on the client side
Some components may be missing in rendered html and their content will be added later (for example, v-if directive was used on the component)
A few takeaways:
PurgeCSS is not needed anymore since Tailwind v2 (the latest being v3.x)
as far as I know, you cannot have code-splitting with Tailwind, not that it matters anyway since it will still perform okay with further optmizations
the classes that will be generated, will be only once for the whole app (hence no need to have a bg-red-500 for index or about page, both are referencing the same unique declaration)
if you want to have SSR/SSG, I recommend the usage of Nuxt (in it's v3 if you're using Vue3 or plan to have anything long-term)
dynamic classes are not possible with Tailwind, you can create things like bg-[#ccc] but it goes on the opposite side of what Tailwind is achieving and should be used exceptionally
for Tailwind's content, still the defaults on this page, section Configure your template paths, no need to do anything crazy or complicated
if you want to have some scoped/local style, style to using style scoped, you can still use Tailwind inside of those tags tho
if you want to write vanilla CSS into dedicated CSS files like index, about, blog etc, then Tailwind is probably not the best approach because this is not how it is supposed to work
stay simple, the performance will still be amazing. Only focus on not having too many screens, colors etc that you're not using
you could run some bundle size tests to see if the CSS is taking a huge chunk in terms of size. Will probably not, but if it still is: you can then start making complex configurations
JS will be far harder to reduce and be more impactful regarding the performance (because of how a browser works with it: parsing, executing is indeed blocking the main thread)

Vue - Webpack - Force scss #import to be chunked in to a shared file?

I'm currently experiencing a pattern where in Vue I have this in a number of different components. What I'm finding is that webpack is then going ahead and including the contents of src/assets/styles/icons across a number of my component style chunks instead of splitting it out.
I don’t really want to pull it in to main as it isn’t shared by all but I’d like to see if something like webpack magic comments is possible or a way to direct webpack to pull icons out in to it’s own chunk.
I've tried investigating magic comments and cacheGroups to no luck.
It seems to duplicate the contents across each of the 7/8 components it is referenced in.
<style lang="scss">
#import 'src/assets/styles/icons
.. more component styles here
</style>
I'd like to force webpack to pull the import out in to a common stylesheet it'll chunk in but haven't been able to get it there.
Is it even possible?

Does 'individual component importing' practice of a UI framework makes Vue js app perform better?

In case of using UI frameworks (like Bootstrap-Vue, ElementUI or Vuetify, etc.) in our Vuejs application, it's possible to import entire UI framework components & stylesheets from node_modeules in the App.vue(or in the application entry point), or importing a particular ui component in particular Vue file/Component as needed.
The demonstration of these two approches looks like:
For scenerio 1
in App.vue
import BootstrapVue from 'bootstrap-vue'
For scenerio 2
in any particular .vue file
import {BContainer} from 'bootstrap-vue'
So,In case of the first option, does it make the application slower or less performing as all components from UI framework is loading for each route change? Also, its's loading some components that are not needed.
On the other hand, it's quite inconvenient to import each ui component in every .vue file.
So what is the best practice for small or large scale web applications?
Does the practice is same for other JS frameworks/Libraries link React or Angular?
Thanks in advance.
Scenario 1 – register all components globally
All components from the library will be available to use everywhere.
If you change or update the library and some of the component names have changed, you won't get any errors at build time.
Scenario 2 – pick-and-choose specific components locally
Gets annoying to have to import each component when you want to use it.
Only components that are actually used (imported) will be included in the bundle (if using webpack or something similar). Results in a smaller bundle size.
It is clearer to look at the template and know where each component comes from. If you have lots of globally-defined components then there is no clear link between a component and where it came from.
If you change or update the library and some of the component names have changed, you will get build errors due to missing modules.
So,In case of the first option, does it make the application slower or less performing as all components from UI framework is loading for each route change? Also, its's loading some components that are not needed.
It does make a difference when you are importing the entire package globally. Also it won't reload the package for every route change as you have the import inside App.vue. It will be done once when your app is loaded for the first time.
I found this article very helpful on how to optimize loading 3rd party components into vue app.
On the other hand, it's quite inconvenient to import each ui component in every .vue file.
End of the day it all comes to how much of tradeoff your development team is willing to make between optimizing the app and adding multiple lines of import code into individual components.

How to access antd less variables when defining a css module for a component?

I'm using customize-cra as suggested by antd documentation to be able to customize the theme and it works fine.
I can access less variables from antd theme by importing the index in my less files and it works fine.
I can use the old fashioned css modules to style my components by defining files with .module.css and it works fine.
However, I would like to import and use the antd theme less variables in my css modules and I can't figure out how to make it work. Does anybody know how it can be achieved?
I am able to use the variables if I import antd.less at the top of the whatevercomponent.less file:
#import 'antd/dist/antd.less';

Vue template render without all the extra

I have a very, very simple set of Vue components that all work. These are a simple addition on top of an existing C# app.
At the moment, these are .html files (brought into the app inside <script> tags) and .js files loaded by reference.
These all work, are very light weight, and I love it.
Now I want to compile the HTML for each component into a Vue render function, and the .js into one minified .js file.
The .js to .min.js is pretty standard, but I cannot figure out how to get the HTML to compile into the Vue render function. Everything I've found involves a LOT of overhead and running a web server which seems a massive overkill for an html->script transform, and I don't need a full web application spun up. I only need my existing, simple templates transformed to something more friendly for production than my long-form html templates getting dumped to the page.
I'm not entirely opposed to turning the .html+.js into .vue files, but just doing that doesn't seem to overcome my issue.
I cannot figure out how to get the HTML to compile into the Vue render function
To generate a render function from a Vue template string (e.g., read from an HTML file), you could use vue-template-compiler like this:
const compiler = require('vue-template-compiler')
const output = compiler.compile('<div>{{msg}}</div>')
console.log(output) // => { render: "with(this){return _c('div',[_v(_s(msg))])}" }
Everything I've found involves a LOT of overhead and running a web server which seems a massive overkill for an html->script transform
The "web server" you mention is provided by Webpack CLI, and is intended to faciliate development. You don't need to use the dev server. The article indeed describes several steps in manually setting up a project to build Vue single-file-components, but a simpler method is to use Vue CLI to automatically scaffold such a project.