I'm trying to use a Bootstrap theme in my Vue application. Unfortunately the Bootstrap theme has no reference implementation for Vue. So I need to configure everything on my own.
What I want to do is, I want use the scss-files provided by the theme in Vue. So my App.vue component is pretty simple:
<template>
<div id="app">
</div>
</template>
<style lang="scss">
#import "#/assets/base.scss";
</style>
The "base.scss" file contains imports all dependencies. So, when I run my Vue application using "npm run serve", I get the following error:
ERROR Failed to compile with 10 errors
This dependency was not found:
-!../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!typicons.font/src/font/typicons.css
in ./node_modules/cs
s-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist /cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=style&index=1&lang=scss&
To install it, you can run: npm install --save
-!../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!typicons.fo
nt/src/font/typicons.css
These relative modules were not found:
./components/icons/linearicons/Linearicons-Free.eot in ./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/
sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=style&index=1&lang=scss&
./components/icons/linearicons/Linearicons-Free.eot?w118d in ./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_mo
dules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=style&index=1&lang=scss&
./components/icons/linearicons/Linearicons-Free.svg?w118d in ./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_mo
dules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=style&index=1&lang=scss&
./components/icons/linearicons/Linearicons-Free.ttf?w118d in ./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_mo
dules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=style&index=1&lang=scss&
./components/icons/linearicons/Linearicons-Free.woff2?w118d in ./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_
modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=style&index=1&lang=scss&
./components/icons/linearicons/Linearicons-Free.woff?w118d in ./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_m
odules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=style&index=1&lang=scss&
./components/slick-carousel/slick/ajax-loader.gif in ./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sa
ss-loader/dist/cjs.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=style&index=1&lang=scss&
./utils/images/logo-inverse.png in ./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs
.js??ref--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=style&index=1&lang=scss&
./utils/images/logo.png in ./node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--8-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref
--8-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=style&index=1&lang=scss&
Error from chokidar (C:): Error: EBUSY: resource busy or locked,
lstat 'C:\hiberfil.sys'
The referenced files are exist in the "#/assets/components/..." directory. But my problem is that I've no idea how I can set a relative path (e.g. "#/assets") searchs for the components. Furthermore there's no variable in the "base.scss" file I can adjust to set the relativ path. I also don't want modify the "base.scss" file because it comes from the theme.
I've no idea how to fix it this. I already tried to set the corresponding webpack-chain in vue.config.js without any success:
module.exports = {
chainWebpack: config => {
config.module
.rule('fonts')
.test(/\.(ttf|otf|eot|woff|woff2)$/)
.use('file-loader')
.loader('file-loader')
.tap(options => {
options = {
name: '#/assets/[path][name].[ext]'
}
return options
})
.end()
}
I hope anyone can help solving this problem :-)
I finally solved the issue by simply importing the "base.scss" in the "main.js" file and use it:
import theme from '#/assets/base.scss'
Vue.use(theme)
Related
Update:
Changing: if(data.aliases?.[name2] !== void 0)
to: if(data.aliases != null && data.aliases[name2] !== void 0)
in the iconify .mjs file fixes the error, however this check occurs a lot of places, and is not viable. Any idea why I cant parse this type of null operator?
in ./node_modules/#iconify/vue/dist/iconify.mjs
Module parse failed: Unexpected token (99:21)You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
My code:
<template>
<div>
<Icon icon="mdi-light:home" />
</div>
</template>
<script setup lang="ts">
import { Icon } from "#iconify/vue";
</script>
Iconify version:
"#iconify/vue": "^3.2.0"
using standard vue cli babel:
presets: ["#vue/cli-plugin-babel/preset"]
I have tried: in babel.config.js
module.exports = function override(config) {
config.module.rules.push({
test: /\.mjs$/,
include: /node_modules/,
type: "javascript/auto"
});
return config;
}
same error
I tried to remove the .mjs file, forcing it to use regular .js file, this resulted in same error but with missing .js loader.
I have tried to use Iconify SVG framework but i get the same type of error where loader is missing for .js files.
Thanks for any feedback :)
Solution:
Downgrading to this version of Iconify "#iconify/vue": "^3.1.1" fixed the problem. This resulted however in a error regarding type declaration. This was fixed by changing VS code's typescript version to: Use workspace version
This is done by selecting a .ts file then pressing "shift+ctrl+p" and select the prompt of select typescript version.
Having the same error cloning from the repository and install dependencies for Vue 2 https://github.com/iconify/iconify
Solution:
Downgrading to this version of Iconify "#iconify/vue": "^3.1.1" fixed the problem. This resulted however in a error regarding type declaration. This was fixed by changing VS code's typescript version to: Use workspace version
This is done by selecting a .ts file then pressing "shift+ctrl+p" and select the prompt of select typescript version.
In one of my projects, I build a nice vue3 component that could be useful to several other projects. So I decided to publish it as an NPM package and share it with everyone.
I wrote the isolate component, build it and publish BUT I use Tailwind css to make the style.
When I publish and install the component everything is working BUT without the beauty of the css part.
I tried several configurations and alternative tools to generate the package that automatically add the tailwind as an inner dependency to my package.
Does someone have experience with this? how can build/bundle my component by adding the tailwind CSS instructions into it?
You're almost there
Since you've got your component working, the majority of the part has been done.
For configuring the styling of the component you need to identify the Tailwind CSS classes being used by your Vue component package and retain them in the final CSS that is generated by the Tailwind engine in your project.
Follow below steps in the project where you want to use your tailwind vue component package.
For Tailwind CSS V3
// tailwind.config.js
module.exports = [
//...
content: [
"./index.html",
"./src/**/*.{vue,js,ts,jsx,tsx}",
"./node_modules/package-name/**/*.{vue,js,ts,jsx,tsx}" // Add this line
// Replace "package-name" with the name of the dependency package
],
//...
]
For Tailwind CSS V2
// tailwind.config.js
module.exports = [
//...
purge: {
//...
content: [
"./index.html",
"./src/**/*.{vue,js,ts,jsx,tsx}",
"./node_modules/package-name/**/*.{vue,js,ts,jsx,tsx}" // Add this line
// Replace "package-name" with the name of the dependency package
],
//...
//...
}
]
The content property in the tailwind.config.js file defines file path pattern that the tailwind engine should look into, for generating the final CSS file.
For Pro users
You may also try to automate the above setup by writing an install script for your npm package to add this configuration to the tailwind.config.js file
References
Tailwind Docs - 3rd party integration
It's a bit difficult for someone to answer your question as you've not really shared the source code, but thankfully (and a bit incorrectly), you've published the src directory to npm.
The core issue here is that when you're building a component library, you are running npm run build:npm which translates to vue-cli-service build --target lib --name getjvNumPad src/index.js.
The index.js reads as follows:
import component from './components/numeric-pad.vue'
// Declare install function executed by Vue.use()
export function install (Vue) {
if (install.installed) return
install.installed = true
Vue.component('getjv-num-pad', component)
}
// Create module definition for Vue.use()
const plugin = {
install
}
// Auto-install when vue is found (eg. in browser via <script> tag)
let GlobalVue = null
if (typeof window !== 'undefined') {
GlobalVue = window.Vue
} else if (typeof global !== 'undefined') {
GlobalVue = global.Vue
}
if (GlobalVue) {
GlobalVue.use(plugin)
}
// To allow use as module (npm/webpack/etc.) export component
export default component
There is no mention of importing any CSS, hence no CSS included in the built version.
The simplest solution would be to include the index.css import in your index.js or the src/components/numeric-pad.vue file under the <style> section.
Lastly, I'm a bit rusty on how components are built, but you might find that Vue outputs the CSS as a separate file. In that case, you would also need to update your package.json to include an exports field.
When building a Vue library (component), according to Vue docs, you can set css.extract: false in vue.config.js to avoid the users having to import the CSS manually when they import the library into an app:
vue.config.js
module.exports = {
css: {
extract: false
}
}
However, when you do that, the icons are not displayed in the production build.
In this case I'm using #mdi/font and weather-icons. Neither of them load:
To reproduce
You can reproduce this with this Vue library (component):
Create new Vue project with vue create test
Clone the repo and put in the same directory as the Vue test project
In vue-open-weather-widget set css.extract: false in vue.config.js;
And comment out CSS import:
import 'vue-open-weather-widget/dist/vue-open-weather-widget.css'
Build vue-open-weather-widget with yarn build
Import it into the test Vue app with yarn add "../vue-open-weather-widget";
Serve the test app yarn serve
I have looked at your lib (nice component BTW). I created a build with css: { extract: false } and first looked at the behavior when importing vue-open-weather-widget.umd.js directly into an HTML file. And that worked without any problems.
The thing is that the fonts remain external in the dist after the build. And it seems that there is a problem to find the fonts when your component is loaded in a Webpack project (in our case Vue CLI project). I don't know why the fonts are not referenced correctly. But I have found another, and possibly a better solution.
As it is stated in the MDI docs, the use of the web fonts can negatively affect the page performance. When importing only one icon, all of them are imported, which in turn increases the bundle size. In such a small component this is more than suboptimal, especially for the component users. Therefore here is the alternative solution, also suggested by MDI:
Use #mdi/js instead of #mdi/font
Remove all #mdi/font references in your code and install deps:
npm install #mdi/js #jamescoyle/vue-icon
Replace all icons with SVG(e.g. in MainView.vue). Note that on this way only icons are included in the bundle that are used in your components:
...
<span #click="state.settings.view = 'settings'">
<svg-icon type="mdi" :path="mdiCogOutline"></svg-icon>
</span>
...
import SvgIcon from '#jamescoyle/vue-icon'
import { mdiCogOutline } from '#mdi/js'
...
components: {
SvgIcon
},
data () {
return {
mdiCogOutline: mdiCogOutline
}
},
Adjust vue.config.js:
module.exports = {
css: {
extract: false
}
}
Build component:
# i would also include --formats umd-min
vue-cli-service build --target lib --formats umd-min --name vue-open-weather-widget src/main.js
Now your dist contains only 192.68 KiB vue-open-weather-widget.umd.min.js and the component is ready to use over CDN or in a Vue CLI Project, without importing any CSS or fonts. I have tested both cases. Here is how it looks like:
Hope it helps you! Feel free to ask if you have further questions.
Any help with the following problem would be greatly appreciated!
Situation:
My project contains two packages:
child-component-lib
contains a single view About.vue written in composition-API-style (with vue2 helper libraries #vue/composition-api and vuex-composition-helpers)
exports a single RouteConfig
build as a lib
views/About.vue (child)
<template>
<div class="about">
<h1>This is an about page (as component lib)</h1>
</div>
</template>
<script>
import { defineComponent } from "#vue/composition-api";
import { createNamespacedHelpers } from "vuex-composition-helpers";
export default defineComponent({
components: {},
setup(_, { root }) {
const { useGetters, useActions } = createNamespacedHelpers("account"); // error thrown here!
}
});
</script>
router/index.ts (child)
export const routes: Array<RouteConfig> = [{
path: "/",
name: "About",
component: () => import(/* webpackChunkName: "about" */ "../views/About.vue")
}];
lib.ts (child)
export const routes = require("#/router").routes;
package.json (child)
"scripts": {
"build": "vue-cli-service build --target lib --name child-component-lib src/lib.ts"
...
parent-app
imports the route from child-component-lib into its router
contains a simple view that displays one line of text and a <router-view />
package.json (parent)
"dependencies": {
"#tholst/child-component-lib": "file:../child-component-lib",
router/index.ts (parent)
import { routes as childComponentRoutes } from "#tholst/child-component-lib";
const routes: Array<RouteConfig> = [...childComponentRoutes];
const router = new VueRouter({routes});
export default router;
App.vue (parent)
<template>
<div id="app">
<Home />
<router-view />
</div>
</template>
<script>
import { defineComponent } from "#vue/composition-api";
import Home from "#/views/Home.vue";
export default defineComponent({
components: {
Home
},
setup(_, { root }) {
...
}
});
</script>
Expected behavior
It works without problems.
Actual behavior
I see an error output in the console. [Vue warn]: Error in data(): "Error: You must use this function within the "setup()" method, or insert the store as first argument." The error message is misleading, because the error is actually thrown inside setup() method. It can be traced back to getCurrentInstance() returning undefined (inside #vue/composition-api).
Investigation:
It turns out that the error disappears when I include the same About.vue in the parent-app itself (just switch the route, to try it out), i.e., it works when we avoid the import from the built library.
So it looks like it's a problem with the build setup
(one of vue.config.js, webpack, babel, typescript, ...)
Reproduce the error:
1. Clone, install, run
git clone git#github.com:tholst/vue-composition-api-comp-lib.git && cd vue-composition-api-comp-lib/child-component-lib && npm install && npm run build && cd ../parent-app/ && npm install && npm run serve
or one by one
git clone git#github.com:tholst/vue-composition-api-comp-lib.git
cd vue-composition-api-comp-lib/child-component-lib
npm install
npm run build
cd ../parent-app/
npm install
npm run serve
2. Open Browser
Go to http://localhost:8080/
3. Open Dev Tools to See Error
[Vue warn]: Error in data(): "Error: You must use this function within the "setup()" method, or insert the store as first argument."
found in
---> <Anonymous>
<App> at src/App.vue
<Root>
Error Screenshot
Environment Info:
Node: 14.2.0
npm: 6.14.8
Chrome: 86.0.4240.198
npmPackages:
#vue/babel-sugar-composition-api-inject-h: 1.2.1
#vue/babel-sugar-composition-api-render-instance: 1.2.4
...
#vue/cli-overlay: 4.5.8
#vue/cli-plugin-babel: 4.5.8
#vue/cli-plugin-router: 4.5.8
#vue/cli-plugin-typescript: 4.5.8
#vue/cli-plugin-vuex:4.5.8
#vue/cli-service: 4.5.8
#vue/cli-shared-utils: 4.5.8
#vue/component-compiler-utils: 3.2.0
#vue/composition-api: 1.0.0-beta.19
#vue/preload-webpack-plugin: 1.1.2
typescript: 3.9.7
vue: 2.6.12
vue-loader: 15.9.5 (16.0.0-rc.1)
vue-router: 3.4.9
vue-template-compiler: 2.6.12
vue-template-es2015-compiler: 1.9.1
vuex: 3.5.1
vuex-composition-helpers: 1.0.21
npmGlobalPackages:
#vue/cli: 4.5.8
I finally understood what the problems were. First, there was the actual problem. Second, there was a problem in the local development setup that made solutions to the actual problem look like they were not working.
The Actual Problem + Solution
The child-component-lib was bundling their own versions of the npm packages #vue/composition-api and vuex-composition-helpers. This had the following effect: When I was running the parent-app there were actually two instances of those libraries and the vue component from the child-component-lib was accessing the wrong object that had not been properly initialized.
The solution was to prevent the bundling of those libraries in the child-component-lib, by
making them devDependencies and peerDependencies.
instructing webpack not to bundle them on npm run build.
package.json
"dependencies": {
...
},
"devDependencies": {
"#vue/composition-api": "^1.0.0-beta.19",
"vuex-composition-helpers": "^1.0.21",
...
},
"peerDependencies": {
"#vue/composition-api": "^1.0.0-beta.19",
"vuex-composition-helpers": "^1.0.21"
},
vue.config.js
configureWebpack: {
externals: {
"#vue/composition-api": "#vue/composition-api",
"vuex-composition-helpers": "vuex-composition-helpers"
},
...
}
The Tricky Problem that Made Things Difficult
I was trying to fix this problem locally, without actually publishing the package. And it seemed to work, because I was seeing the same problem locally that I also saw in the published packages.
I did local development by directly linking the parent-app and child-component-libs. I tried both
a direct folder dependency
package.json
"dependencies": {
"#tholst/child-component-lib": "file:../child-component-lib",
},
npm link
cd child-component-lib
npm link
cd ../parent-app
npm link #tholst/child-component-lib
Both approaches have the effect that they actually import (=symlink to) the child-component-lib's folder with all files and folders (instead of only the files that would be published in the npm package).
And that meant the following: Even though I had excluded the two composition-API libs from the bundle and made them dev/peer dependencies (see solution to actual problem), they were still installed and present in the child-component-lib's node_modules. And that node_modules folder was symlinked into the parent-app package. And in this way the child-component-lib still had access to their own copy of the libraries that we wanted to exclude from the build (see actual problem). And I was still seeing the error as before.
And this way my local development approach obscured the fact that the solution to the actual problem was actually working.
I started creating a project in vue.js based on this one:
https://github.com/creativetimofficial/vuetify-material-dashboard
When trying to integrate TableList.vue component, I get an error:
Unknown custom element: <material-card> - did you register the component correctly?
Vue.js project was created using webstorm. I copied over styles folder and enabled watcher to compile scss files into css. I run project using npm serve command in WebStorm.
My App.vue looks a little different like this:
<template>
<v-app>
<TheBar />
<TheNavigationDrawer />
<TheView />
</v-app>
</template>
<script>
import TheBar from '#/components/core/TheBar.vue'
import TheNavigationDrawer from "#/components/core/TheNavigationDrawer";
import TheView from '#/components/core/TheView.vue'
export default {
name: 'app',
components: {
TheBar,
TheNavigationDrawer,
TheView
},
data: () => ({
}),
};
</script>
<style lang="scss">
#import './styles/index.scss';
</style>
As you can see I am importing the full file, which in turn imports _cards.scss file which should have definition of material-card component. Is this how it works?
I tried registering component manually by adding material-card to components property but it fails to parse kebab-case properly because of '-' sign.
What also intrigues me is that the original creator NEVER registers material-card component so how the hell does his TableList.vue component know it?
I also found this guide - https://medium.com/#mahesh.ks/using-sass-scss-in-vue-js-2-d472af0facf9. However I don't see a webpack.config.js file anywhere, where is this?
Any help is greatly appreciated. :D
There are multiple ways of importing components into your Vue instance. For the case of the project you're working from, the vuetify library is imported at the root instance which allows all components to be available globally. This means you don't need to import the desired components within specific .vue files.
It's likely that you haven't installed all of the dependencies correctly. Or you have not properly imported these dependencies within main.js. Check that these dependecies (found in package.json) have been installed by running npm list.