Vue CLI 5 with Vuetify SCSS variables and CSS imports - vue.js

I work for an organization that try to migrate a project from Vue CLI 4 to Vue CLI 5.
The project uses Vuetify and we have SCSS files that are used in the styles/variables.scss file (required by Vuetify to customize style) and also used in Vue components files via #import (SCSS variables sometimes need to be in the <script> section).
Here some example that show how SCSS variables are used through the app:
// styles/variables.scss
#import "colors.scss";
$some-vuetify-sass-variable: $color // from (colors.scss)
// plugins/vuetify.js
import { primaryColor } from "#/style/colors.scss";
Vue.use(Vuetify);
const options = {
theme: {
dark: false,
themes: {
light: {
primary: primaryColor,
// ...
},
},
},
};
export default new Vuetify(options);
// Component.vue
<template>
<v-chip
:color="clearPrimaryColor"
text-color="primary"
/>
</template>
<script>
import { clearPrimaryColor } from "#/style/colors.scss";
export default {
name: "Component",
created() {
this.clearPrimaryColor = clearPrimaryColor;
}
}
</script>
<style lang="scss">
.some-class {
background-color: $clearPrimaryColor
}
</style>
During the Vue CLI migration, we also tried to upgrade some Vuetify dependencies (sass and vuetify-loader). Upgrading sass from 8 to 10 version triggers a compile sass error.
With this reproduction branch: https://github.com/KevinFabre/vue-cli-5-vuetify-scss-variables-in-js (sass 8.0.0), the project does compile.
And for this one: https://github.com/KevinFabre/vue-cli-5-vuetify-scss-variables-in -js/tree/error/sass-error (sass 10.0.0), it does not compile:
ERROR Failed to compile with 2 errors
error in ./src/styles/app.module.scss
Syntax Error: SassError: This file is already being loaded.
╷
2 │ #import "app.module.scss";
│ ^^^^^^^^^^^^^^^^^
╵
src/styles/variables.scss 2:9 #import
src/styles/app.module.scss 1:9 root stylesheet
Is there extra Vue CLI 5 configuration to allow CSS import in JS while using Vuetify sass override ?
We've submitted issues to vuetify-loader and Vue CLI but didn't receive any reply for now:
https://github.com/vuetifyjs/vuetify-loader/issues/234
https://github.com/vuejs/vue-cli/issues/7083
{
"devDependencies": {
"#babel/preset-env": "^7.11.0",
"#cypress/webpack-preprocessor": "^5.4.1",
"#mdi/font": "^6.5.95",
"#vue/cli-plugin-babel": "^4.4.5",
"#vue/cli-plugin-e2e-cypress": "^4.4.5",
"#vue/cli-plugin-eslint": "^4.4.5",
"#vue/cli-service": "^4.4.5",
"#vue/eslint-config-prettier": "^6.0.0",
"babel-eslint": "^10.0.1",
"core-js": "^3.6.5",
"eslint": "^7.3.1",
"eslint-plugin-mocha": "^9.0.0",
"eslint-plugin-prettier": "^3.1.0",
"eslint-plugin-unused-imports": "^1.1.5",
"eslint-plugin-vue": "^7.0.0",
"eslint-plugin-vuetify": "^1.1.0",
"lint-staged": "^10.2.11",
"sass": "~1.32.0",
"sass-loader": "^10.0.0",
"style-resources-loader": "^1.2.1",
"stylus": "^0.54.5",
"stylus-loader": "^3.0.1",
"vue-cli-plugin-style-resources-loader": "^0.1.3",
"vue-cli-plugin-vuetify": "^2.0.6",
"vue-svg-loader": "^0.16.0",
"vue-template-compiler": "^2.6.12",
"vuetify-loader": "^1.7.3",
}
}
Thank you for your time.

Components must avoid importing files that are already imported in the global variables stylesheet (src/styles/variables.scss). This was the case with app.module.scss (loaded in src/styles/variables.scss and in src/components/HelloWorld.vue), causing the error about the file being loaded twice.
One solution is to move the color definitions from app.module.scss into its own file, and import that in variables.scss instead of app.module.scss. Then, components could import app.mdoule.scss without running into the original problem.
/* src/styles/app.module.scss *
:export {
whitecolor: $white-color;
darkcolor: $dark-color;
lightcolor: $light-color;
mediumcolor: $medium-color;
alertcolor: $alert-color;
lightblackcolor: $light-black-color;
blackcolor: $black-color;
}
/* src/styles/colors.scss */
$white-color: #fcf5ed;
$dark-color: #402f2b;
$light-color: #e6d5c3;
$medium-color: #977978;
$alert-color: #cb492a;
$light-black-color: #706e72;
$black-color: #414042;
/* src/styles/variables.scss */
#import "~vuetify/src/styles/settings/_colors.scss";
#import "colors.scss";
$material-light: (
background: map-get($grey, "lighten-1")
);
demo

This basically pertains to duplicate parsing of the import files, declared in your vuejs app.
There are 2 ways to solve it:
Use #use instead of #import where you are getting the Sass import error. Like, #import "app.module.scss"; becomes #use "app.module.scss";
Other alternative is to downgrade the sass-loader library to "^8.0.2"
Let me know if the above solutions work for you, meanwhile i will update my answer if i find any new solution.

Related

Could not find a declaration file for module 'prismjs/components/prism-core' vue-prism-editor

I am just trying to use this package (vue-prism-editor) in my vuejs 3 application, but I am always getting an error as preceding.
TS7016: Could not find a declaration file for module 'prismjs/components/prism-core'. 'C:/Sibeesh/GitHub/vue-resume/node_modules/prismjs/components/prism-core.js' implicitly has an 'any' type.
Try `npm i --save-dev #types/prismjs` if it exists or add a new declaration (.d.ts) file containing `declare module 'prismjs/components/prism-core';`
I did install #types/prismjs but no luck there. I followed the steps mentioned in the readme and trying exactly the same.
Below is my package.json file.
{
"name": "vue-resume",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"core-js": "^3.6.5",
"jsoneditor": "^9.2.0",
"vue": "^3.0.0",
"vue-class-component": "^8.0.0-0",
"vue-prism-editor": "^2.0.0-alpha.2",
"vue-router": "^4.0.0-0",
"vuex": "^4.0.0-0"
},
"devDependencies": {
"#types/prismjs": "^1.16.3",
"#typescript-eslint/eslint-plugin": "^4.18.0",
"#typescript-eslint/parser": "^4.18.0",
"#vue/cli-plugin-babel": "~4.5.0",
"#vue/cli-plugin-eslint": "~4.5.0",
"#vue/cli-plugin-router": "~4.5.0",
"#vue/cli-plugin-typescript": "~4.5.0",
"#vue/cli-plugin-vuex": "~4.5.0",
"#vue/cli-service": "~4.5.0",
"#vue/compiler-sfc": "^3.0.0",
"#vue/eslint-config-prettier": "^6.0.0",
"#vue/eslint-config-typescript": "^7.0.0",
"eslint": "^6.7.2",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-vue": "^7.0.0",
"prettier": "^2.2.1",
"prismjs": "^1.23.0",
"sass": "^1.26.5",
"sass-loader": "^8.0.2",
"typescript": "~4.1.5"
}
}
Here is my vue component.
<template>
<div class="hello">
<prism-editor
class="code-editor"
v-model="code"
:highlight="highlighter"
line-numbers
></prism-editor>
</div>
</template>
<script lang="ts">
// import Prism Editor
import { PrismEditor } from 'vue-prism-editor';
import 'vue-prism-editor/dist/prismeditor.min.css'; // import the styles somewhere
// import highlighting library (you can use any library you want just return html string)
import { highlight, languages } from 'prismjs/components/prism-core';
import 'prismjs/components/prism-javascript';
export default {
components: {
PrismEditor,
},
data: () => ({ code: 'console.log("Hello World")' }),
methods: {
highlighter(code: string) {
return highlight(code, languages.js); // languages.<insert language> to return html with markup
},
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
/* required class */
.code-editor {
/* we dont use `language-` classes anymore so thats why we need to add background and text color manually */
background: #2d2d2d;
color: #ccc;
/* you must provide font-family font-size line-height. Example: */
font-family: Fira code, Fira Mono, Consolas, Menlo, Courier, monospace;
font-size: 14px;
line-height: 1.5;
padding: 5px;
}
/* optional class for removing the outline */
.prism-editor__textarea:focus {
outline: none;
}
</style>
Have you ever been able to use this plugin in vue 3 application?
I try some ways with typescript, found that this is the easiest way
first
yarn add #types/prismjs
then
import { highlight, languages, highlightElement } from 'prismjs';
After spending some time on this issue, I could find out what mistake I am doing. Did you notice the lang="ts" in my script? Well, that is the root cause of this issue. After removing that from <script>, the error was gone. This issue in GitHub helped me find the solution for this. One drawback of this approach is that we no longer be able to use the Type annotations as this will be supported only with TypeScript files.
The other mistake was that I was not including the reference to import 'prismjs/components/prism-clike';. We will get the preceding error if we don't include that file.
Uncaught TypeError: Cannot read property 'class-name' of undefined
at eval (prism-javascript.js?416b:3)
The other approach:
As mentioned in the error, you can also create a .d.ts file and add the declare module 'prismjs/components/prism-core'. I created this file inside my components directory.
And then you can rewrite your script in the preceding way.
<script lang="ts">
import { PrismEditor } from "vue-prism-editor";
import { highlight, languages } from "prismjs/components/prism-core";
import "vue-prism-editor/dist/prismeditor.min.css";
import "prismjs/components/prism-clike";
import "prismjs/components/prism-json";
import "prismjs/themes/prism-tomorrow.css";
import sampleData from "../assets/resume-template.json";
import { Options, Vue } from "vue-class-component";
#Options({
components: {
PrismEditor,
},
data: () => ({
code: JSON.stringify(sampleData),
}),
methods: {
submit() {
console.log(this.code);
},
highlighter(code: string) {
return highlight(code, languages.json);
},
},
})
export default class CodeEditor extends Vue {}
</script>
Just sharing as it might be helpful to someone else.
If anyone is struggling with this too, heres my solution:
PrismEditor.vue
<template>
<prism-editor
class="my-editor"
v-model="code"
:highlight="highlighter"
line-numbers
readonly
></prism-editor>
</template>
<script>
import { PrismEditor } from "vue-prism-editor";
import "vue-prism-editor/dist/prismeditor.min.css";
import { highlight, languages } from "prismjs/components/prism-core";
import "prismjs/components/prism-clike";
import "prismjs/components/prism-javascript";
import "prismjs/themes/prism-tomorrow.css";
export default {
components: {
PrismEditor,
},
props: {
code: {
type: String,
default: "console.log('default value')",
},
lang: {
type: String,
default: "js",
},
},
methods: {
highlighter() {
return highlight(this.code, languages[this.lang]);
},
},
};
</script>
<style>
/* required class */
.my-editor {
/* we dont use `language-` classes anymore so thats why we need to add background and text color manually */
background: #2d2d2d;
color: #ccc;
/* you must provide font-family font-size line-height. Example: */
font-family: Fira code, Fira Mono, Consolas, Menlo, Courier, monospace;
font-size: 14px;
line-height: 1.5;
padding: 5px;
}
/* optional class for removing the outline */
.prism-editor__textarea:focus {
outline: none;
}
</style>
CodeBlock.vue
<template>
<prism-editor :code="code" :lang="lang"></prism-editor>
</template>
<script setup lang="ts">
import { ref } from "vue";
import PrismEditor from "../components/PrismEditor.vue";
const code = ref("console.log(It's working)");
const lang = ref("js");
</script>
<style></style>

Vue 3 Web Components do not build and instead throw error

I created a new vue project with the vue cli and then adjusted main.js to support web-components:
import Vue from 'vue';
import wrap from '#vue/web-component-wrapper';
import HelloWorld from "./components/HelloWorld";
const CustomElement = wrap(Vue, HelloWorld);
window.customElements.define('my-custom-element', CustomElement);
When running vue-cli-service build --target wc I get the following error:
ERROR Vue 3 support of the web component target is still under development.
I can not figure out why this error occurs and what i can do to fix it.
package.json:
...
"dependencies": {
"#vue/web-component-wrapper": "^1.2.0",
"core-js": "^3.6.5",
"vue": "^3.0.2"
},
"devDependencies": {
"#vue/cli-plugin-babel": "~4.5.0",
"#vue/cli-plugin-eslint": "~4.5.0",
"#vue/cli-service": "^4.5.4",
"#vue/compiler-sfc": "^3.0.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^7.0.0-0"
},
...
I use #vue/cli version 4.5.9.
Hello there is a update in this. Topic see
issue on github and comment on twitter looks like with vue 3.2.0 we have this feature back i created a small stackblitz but as you can see styles are not applied
Vue-CLI does not currently support web components for Vue 3, but you can do it by hand. This worked for me.
src/MyLib.js
export { default as TheFoo } from '#/components/TheFoo.vue';
export { default as TheBar } from '#/components/TheBar.vue';
src/MyLib-WC.js
import { defineCustomElement } from 'vue';
import TheFoo from '#/components/TheFoo.vue';
import TheBar from '#/components/TheBar.vue';
const TheFooWC = defineCustomElement(TheFoo);
const TheBarWC = defineCustomElement(TheBar);
export {
TheFooWC,
TheBarWC
};
export function register () {
customElements.define('the-foo', TheFooWC);
customElements.define('the-bar', TheBarWC);
}
package.json
{
"scripts": {
"build": "npm run build-lib && npm run build-wc",
"build-lib": "vue-cli-service build --name=MyLib --modern --dest=dist/lib --target=lib src/MyLib.js",
"build-wc": "vue-cli-service build --name=MyLib --modern --dest=dist/wc --target=lib --inline-vue src/MyLib-WC.js"
}
}
Then npm run build.
As #tony19 pointed out the solution is to not use Vue3, as it cureently does not support web components.
The problem for me was the misleading error message, as "still under developement" did not signal to me, that web components were completly unsupported. I understood it, as a "not everything will work perfectly".

How to Import Apollo Client 3 for Vue Apollo?

The release note of Vue-Apollo 3.04 stated that there is now a Apollo Client 3 support. As the Docs of Apollo Client 3 declare ApolloClient, InMemoryCache, HttpLink, are now all in one #apollo/client package - not like previous in single packages.
https://github.com/vuejs/vue-apollo/releases/tag/v3.0.4
https://www.apollographql.com/docs/react/migrating/apollo-client-3-migration/
However there is no change in the doc´s of Vue-Apollo (apollo-client -> #apollo/client ?) on how to apply the new changes. Also the Apollo Client 3 Doc´s stated that for Vue you have to import the ApolloClient from #apollo/client/core
So i tried it my own way, but my imports seems to fail. I got these Error Message from npmm run serve. Seems he wants to import some reactstuff.
ERROR Failed to compile with 8 errors 20:25:20
This dependency was not found:
* react in ./node_modules/#apollo/client/react/context/ApolloConsumer.js, ./node_modules/#apollo/client/react/context/ApolloContext.js and 6 others
To install it, you can run: npm install --save react
vue-apollo.js (from old project that worked)
import Vue from 'vue'
import { ApolloClient } from 'apollo-client'
import { HttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'
import VueApollo from 'vue-apollo'
vue-apollo.js (with new apollo client 3)
import Vue from 'vue'
import { ApolloClient } from '#apollo/client/core'
import { InMemoryCache } from '#apollo/client/cache'
import { HttpLink } from '#apollo/client'
import VueApollo from 'vue-apollo'
package.json
"dependencies": {
"#apollo/client": "^3.1.3",
"core-js": "^3.6.5",
"graphql": "^15.3.0",
"js-cookie": "^2.2.1",
"subscriptions-transport-ws": "^0.9.18",
"vue": "^2.6.11",
"vue-apollo": "^3.0.4"
},
"devDependencies": {
"#vue/cli-plugin-babel": "~4.5.0",
"#vue/cli-plugin-eslint": "~4.5.0",
"#vue/cli-service": "~4.5.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"vue-template-compiler": "^2.6.11",
"webpack-bundle-tracker": "^1.0.0-alpha.1"
},
Question
How to correct import the new apollo client 3 with vue apollo?
Alright after a break i tried this and it worked.
vue-apollo.js
import Vue from 'vue'
import { ApolloClient, InMemoryCache, HttpLink } from '#apollo/client/core';
import VueApollo from 'vue-apollo'
Now the compiler finds everything. Although in the Apollo Client 3 Doc i could only find one reference with the new Client 3 and Vue, it seems all react stuff comes from #apollo/client while Vue and other from #apollo/client/core.

free-regular-svg-icons of vue-fontawesome not working

I am using Webpack + Vue + vue-fontawesome.
The code below works fine and display icons.
import #fortawesome/free-solid-svg-icons
But this one doesn't display icons.
import faCalendarCheck component in #fortawesome/free-regular-svg-icons
Similary, other components in #fortawesome/free-regular-svg-icons are not working.
Component do render comment line of HTML <\!---->.
Why #fortawesome/free-regular-svg-icons is not working?
main.js
// Font Awesome
import { library } from '#fortawesome/fontawesome-svg-core';
import {
faThLarge,
// faCalendarCheck,
faBell,
faAddressBook,
faCalculator,
faSitemap,
faEnvelope,
faWindowMaximize,
faFileAlt,
faNewspaper,
} from '#fortawesome/free-solid-svg-icons';
import {
faCalendarCheck,
} from '#fortawesome/free-regular-svg-icons';
library.add(faThLarge);
library.add(faCalendarCheck);
library.add(faBell);
library.add(faAddressBook);
library.add(faCalculator);
library.add(faSitemap);
library.add(faEnvelope);
library.add(faWindowMaximize);
library.add(faFileAlt);
library.add(faNewspaper);
import { FontAwesomeIcon } from '#fortawesome/vue-fontawesome';
Vue.component('font-awesome-icon', FontAwesomeIcon);
app.vue
<template>
<font-awesome-icon icon="calendar-check" />
</template>
package.json
"dependencies": {
"#fortawesome/fontawesome-svg-core": "^1.2.2",
"#fortawesome/free-brands-svg-icons": "^5.2.0",
"#fortawesome/free-regular-svg-icons": "^5.2.0",
"#fortawesome/free-solid-svg-icons": "^5.2.0",
"#fortawesome/vue-fontawesome": "^0.1.1"
}
You need to specify a prefix for using non solid icons.
In your example this should work:
<font-awesome-icon :icon="['far', 'calendar-check']" />
More info can be found here.
One more tip - Instead of writing this:
library.add(faThLarge);
library.add(faCalendarCheck);
library.add(faBell);
etc...
you can simplify it to:
library.add(faThLarge, faCalendarCheck, faBell);

vue-katex not rendering math and displaying large black box

I've just tried to use the vue-katex module https://www.npmjs.com/package/vue-katex.
I set up a simple example using vue-cli
$ vue init webpack-simple my-project
And then I added the vue-katex package, added the few lines of code to put some KaTeX mathematical stuff on the page and started my dev server. However, the mathematical notation is not displaying properly, and I'm getting a big black box displayed on my page.
Here's the relevant part of my package.json:
"dependencies": {
"vue": "^2.5.11",
"vue-katex": "^0.1.2"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
],
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.0",
"babel-preset-stage-3": "^6.24.1",
"cross-env": "^5.0.5",
"css-loader": "^0.28.7",
"file-loader": "^1.1.4",
"vue-loader": "^13.0.5",
"vue-template-compiler": "^2.4.4",
"webpack": "^3.6.0",
"webpack-dev-server": "^2.9.1"
}
Here's my app code (I've tried to take the code directly from the vue-katex npm page above):
<template>
<div id="app">
<div v-katex:display="'\\frac{a_i}{1+x}'"></div>
<img src="./assets/logo.png">
...
</div>
</template>
<script>
import Vue from 'vue';
import VueKatex from 'vue-katex';
Vue.use(VueKatex);
export default {
name: 'app',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
}
}
</script>
And a screenshot of the result:
You can see the math doesn't render and I get this weird big black box. I've included the dev tools inspection to try to make it easier to diagnose.
I've tried to keep everything as simple as possible - if anyone could tell me what I'm doing wrong, I'd really appreciate it!
Many thanks in advance,
One step is missing from the vue-katex docs. If you go to the parent project, https://github.com/Khan/KaTeX you'll find that in their walk through they include a link to an external css file. You'll need to include this too:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.9.0-alpha2/katex.min.css" integrity="sha384-exe4Ak6B0EoJI0ogGxjJ8rn+RN3ftPnEQrGwX59KTCl5ybGzvHGKjhPKk/KC3abb" crossorigin="anonymous">