Vue-svg-loader with Vue 3 - vue.js

Tell me, please, why vue-svg-loader works incorrectly with Vue 3 ore what i doing wrong?
I add settings to vue.config.js
const {defineConfig} = require('#vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
chainWebpack: config => {
const svgRule = config.module.rule('svg')
svgRule.uses.clear()
svgRule
.use('vue-loader')
.loader('vue-loader')
.end()
.use('vue-svg-loader')
.loader('vue-svg-loader')
}
})
Then i import svg and try add him as component to template
<template>
<YoutubeIcon />
</template>
<script setup>
import YoutubeIcon from '#/assets/Icons/youtube.svg'
</script>
And after these steps i get error in console
Failed to execute 'createElement' on 'Document': The tag name provided
('/img/youtube.9fd81e7d.svg') is not a valid name.
Versions:
vue: "^3.2.13"
vue-loader: "17.0.0"
vue-svg-loader: "^0.17.0-beta.2" // stable version doesn't work either

I found solution in issues on github page of vue-svg-loader plugin
chainWebpack: config => {
config.module.rules.delete('svg')
config.module
.rule('svg')
.test(/\.(svg)(\?.*)?$/)
.use('vue-loader')
.loader('vue-loader')
.end()
.use('vue-svg-loader')
.loader('vue-svg-loader')
}
Now svg loads correctly

After several hours of searching and trying, I found a solution.
package.json
"vue": "^3.2.13",
"vue-loader": "^17.0.1",
"svg-vue3-loader": "^1.0.2"
vue.config.js
chainWebpack: (config) => {
const svgRule = config.module.rule('svg');
svgRule.uses.clear();
svgRule.delete('type');
svgRule.delete('generator');
svgRule
.use('babel-loader')
.loader('babel-loader')
.end()
.use('svg-vue3-loader')
.loader('svg-vue3-loader');
},

Related

Vuetify icons gives an error with storybook

Hello everyone I'm facing an issue When I use the storybook with vuetify framework and when I run the project it gives the following error multiple times.
Cannot read properties of undefined (reading 'component')
TypeError: Cannot read properties of undefined (reading 'component')
at remapInternalIcon (http://localhost:6006/vendors~main.f3adcb00877b75c26c76.bundle.js:267378:37)
at VueComponent.getIcon
and here is I'm using storybook v6.1.11 npm packages
"#storybook/addon-essentials": "^6.5.16",
"#storybook/addon-actions": "^6.1.11",
"#storybook/addon-controls": "^6.5.16",
"#storybook/addon-docs": "^6.1.11",
"#storybook/addon-links": "^6.1.11",
"#storybook/addons": "^6.1.11",
"#storybook/preset-scss": "^1.0.3",
"#storybook/vue": "^6.1.11",
"vuetify-loader": "^1.7.0",
"vuetify": "^2.6.0"
knowing that the my project is working fine and all of the components renders correctly even v-icon
main.js
const path = require('path');
module.exports = {
addons: [
'#storybook/addon-controls',
'#storybook/addon-docs',
'#storybook/addon-actions',
'#storybook/preset-scss',
],
webpackFinal: async (config, { configType }) => {
config.module.rules.push({
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
include: path.resolve(__dirname, '../'),
});
config.module.rules.push({
resolve: {
alias: {
'#': path.resolve(__dirname, '../src'),
vue: 'vue/dist/vue.js',
'vue$': 'vue/dist/vue.esm.js',
},
},
});
// Return the altered config
return config;
},
};
preview.js
import { configure, addDecorator } from "#storybook/vue";
import "!style-loader!css-loader!sass-loader!./scss-loader.scss";
import "vuetify/dist/vuetify.css";
import "#mdi/font/css/materialdesignicons.css";
import i18n from '../src/plugins/i18n';
import Vue from "vue";
import Vuetify from "vuetify";
Vue.use(Vuetify);
Vue.prototype.$t = function(...args){
return i18n.t(...args);
}
addDecorator(() => ({
i18n,
vuetify: new Vuetify({
rtl: true,
icons: {
iconfont: "mdi",
}
}),
template:
'<v-app style="background-color: white"><v-main><story/></v-main></v-app>',
}));
// automatically import all files ending in *.stories.js
configure(require.context("../stories", true, /\.stories\.js$/), module);
manager.js
import "#storybook/addon-actions/register";
import "#storybook/addon-links/register";
Here is an example of my stories
import Calendar from "../src/components/Calendar/calendar.vue";
export default {
title: "Components/Calendar",
component: Calendar,
};
const Template = (args, { argTypes }) => ({
components: { Calendar },
props: Object.keys(argTypes),
template: `<Calendar v-bind="$props" />`,
});
export const WithLabel = Template.bind({});
WithLabel.args = {
label: "Pick a date",
};
I don't know What is the issue.
Thanks in advance.

Inertia.js ssr: ReferenceError: document is not defined

I am using Laravel 8 with Inertia.js version 0.5.4. Can anyone help solve this problem? The app works fine without the ssr. I think the problem is in the Webpack config file.
ReferenceError: document is not defined
package.json
"#inertiajs/inertia": "^0.11.0",
"#inertiajs/inertia-vue": "^0.8.0",
"laravel-mix": "^6.0",
"sass": "~1.32",
"sass-loader": "^12.2.0",
"vue-cli-plugin-vuetify": "~2.3.1",
"vue-loader": "^15.9.6",
"vue-template-compiler": "^2.6.10",
"vuetify-loader": "^1.7.0",
"webpack": "^5.59.1",
"vue": "^2.6.14",
"vue-server-renderer": "^2.6.14",
"vuetify": "^2.5.5",
"vuetifyjs-mix-extension": "0.0.20",
"vuex": "^3.4.0",
"webpack-node-externals": "^3.0.0"
webpack.ssr.mix.js
const path = require('path')
const mix = require('laravel-mix')
const webpackNodeExternals = require('webpack-node-externals');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
mix
.options({ manifest: false, processCssUrls: false })
.js('resources/js/ssr.js', 'public/js')
.vue({
version: 2, options: { optimizeSSR: true }
})
.webpackConfig({
resolve: {
alias: {
'#resources': path.resolve('resources'),
'{Template}': path.resolve('resources/js/Themes/default'),
'#themeConfig': path.resolve('themeConfig.js'),
'#core': path.resolve('resources/#core'),
'#axios': path.resolve('resources/js/plugins/axios.js'),
'#user-variables': path.resolve('resources/sass/variables.scss'),
'#sass': path.resolve('resources/sass/'),
'apexcharts': path.resolve(__dirname, 'node_modules/apexcharts-clevision'),
'#': path.resolve('resources/js'),
},
},
plugins: [new MiniCssExtractPlugin(
{
filename: "[name].css",
chunkFilename: "[id].css",
linkType: false,
}
)],
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
// enable CSS extraction
extractCSS: true
}
}
// ...
]
},
target: 'node',
devtool: 'source-map',
externals: [webpackNodeExternals({
// this WILL include `jquery` and `webpack/hot/dev-server` in the bundle, as well as `lodash/*`
allowlist: [/^vuetify/, /^lodash/, 'vue-tel-input-vuetify/lib', /^vue-tel-input-vuetify^/, /^apexcharts^/, /^vue-apexcharts/, /apexcharts/, /apexcharts-clevision/, /^apexcharts-clevision/, /^apexcharts-clevision^/, /^vue-country-flag/, /\.css$/]
})],
})
ssr.js
import Vue from 'vue'
import {createRenderer} from 'vue-server-renderer'
import {createInertiaApp} from '#inertiajs/inertia-vue'
import createServer from '#inertiajs/server'
import PortalVue from 'portal-vue';
import store from './store'
import './plugins/acl'
import VueCompositionAPI from '#vue/composition-api'
import VueMeta from 'vue-meta'
import vuetify from '#/plugins/vuetify'
import Layout from '#/Layouts/AdminLayout.vue'
import AppLayout from "#/Layouts/AppLayout.vue"
import UserLayout from "#/Layouts/UserLayout.vue"
import ClientOnly from 'vue-client-only'
const moment = require('moment');
createServer((page) => createInertiaApp({
page,
render: createRenderer().renderToString,
// resolve: name => require(`./Pages/${name}`),
resolve: (name) => {
// const page = (await import(`./Pages/${name}`)).default
const page = require(`./Pages/${name}`);
if (page.layout === undefined && name.startsWith('Admin/')) {
page.layout = Layout
}
if (page.layout === undefined && name.startsWith('Dashboard/')) {
page.layout = Layout
}
if (page.layout === undefined && name.startsWith('UserDashboard/')) {
page.layout = UserLayout
}
if (page.layout === undefined && !name.startsWith('Admin/') && !name.startsWith('Dashboard/')) {
page.layout = AppLayout
}
return page
},
setup({app, props, plugin}) {
Vue.use(plugin);
Vue.use(VueCompositionAPI);
Vue.use(PortalVue);
Vue.component('client-only', ClientOnly)
Vue.use(VueMeta, {
// optional pluginOptions
refreshOnceOnNavigation: true
})
Vue.mixin({methods: {route}});
return new Vue({
vuetify: vuetify,
store,
render: h => h(app, props),
})
},
}))
npx mix --mix-config=webpack.ssr.mix.js
result : webpack compiled successfully
node public/js/ssr.js
error :
var style = document.createElement('style');
^
ReferenceError: document is not defined
at insertStyleElement (C:\laragon\www\test2\public\js\ssr.js:44989:15)
at addStyle (C:\laragon\www\test2\public\js\ssr.js:45104:13)
at modulesToDom (C:\laragon\www\test2\public\js\ssr.js:44977:18)
at module.exports (C:\laragon\www\test2\public\js\ssr.js:45135:25)
at Module../resources/sass/overrides.scss (C:\laragon\www\gooreo2\public\js\ssr.js:41942:145)
at webpack_require (C:\laragon\www\test2\public\js\ssr.js:130966:42)
at Module../resources/js/plugins/vuetify/default-preset/preset/index.js
(C:\laragon\www\test2\public\js\ssr.js:38073:1)
at webpack_require (C:\laragon\www\test2\public\js\ssr.js:130966:42)
at Module../resources/js/plugins/vuetify/index.js (C:\laragon\www\test2\public\js\ssr.js:38099:80)
at webpack_require
(C:\laragon\www\test2\public\js\ssr.js:130966:42)
public/js/ssr.js
You can fix it is by adding one line to your webpack.mix.js to opt in to using the vue-style-loader
mix
.js('resources/js/ssr.js', 'public/js')
.vue({
version: 3,
useVueStyleLoader: true // This should fix it!
});
Ref: https://aaronfrancis.com/2021/vue-referenceerror-document-is-not-defined-at-insertstyleelement

vite build rollupOptions.external error: when i try to make vue and vuetify external and run vite,the vite doesnt work?

My devDependencies
"sass": "^1.33.0",
"vite": "^2.1.2",
"vite-plugin-html": "^2.0.7",
"vite-plugin-vue2": "^1.4.2",
"vue-template-compiler": "^2.6.12",
My vite.config.js
const { defineConfig } = require('vite')
const path = require('path')
const { createVuePlugin } = require('vite-plugin-vue2')
const dayjs = require('dayjs')
const { injectHtml } = require('vite-plugin-html')
const package = require('./package.json')
const resolve = (dir) => path.join(__dirname, dir)
// https://vitejs.dev/config/
module.exports = defineConfig({
build: {
cssCodeSplit: false,
rollupOptions: {
external: ['vue', 'vuetify']
}
},
plugins: [
createVuePlugin(),
injectHtml({
injectData: {
title: package.title
}
})
],
resolve: {
alias: {
'#': resolve('src')
}
},
server: {
port: 3000,
}
})
and I import the vue and vuetify in index.html
<script type="module" src="/webapp/main.js"></script>
<script src="/lib/vue.min.js"></script>
<script src="/lib/vuetify.min.js"></script>
But it return error .
...
node_modules\vuetify\src\styles\settings\_variables.scss 64:11 #import
...
Try this:
the main scss file with: mixing, vars and other scss
/src/styles/my-app-style.scss
<style lang="scss">
#import "./src/styles/my-app-style.scss";
</style>

Wrong import path after building vue proect as a "Library"

I am currently coding a small vue component library for company's internal use. However, I faced some difficulties on building and deploy the project. This component library contains several components inside. And it will finally build by vue-cli-service build --target lib. The problem I am facing right now is that I have a component (i.e. called Audio.vue), and it will import a .mp3 file inside the component. The component is look like this
<template>
<audio controls :src="soundSrc" />
</template>
<script>
import { defineComponent } from 'vue';
import sound from './assets/sound.mp3';
export default defineComponent({
name: 'Audio',
props: {},
setup() {
return { soundSrc: sound };
},
});
</script>
<style scoped></style>
However, I use this component by serving (vue-cli-service serve") my project is fine. But if I build this project by running vue-cli-service build --target lib --name project-name-here. And I use this built version as a git submodule of my library in another vue project by importing project-name-here.common built before. The sound.mp3 import from './assets/sound.mp3' could not be found. It seems it is using a relative path of my another vue project (i.e. localhost:8080) instead of the library project
Here is my vue.config.js
const path = require('path');
module.exports = {
css: {
extract: false,
},
lintOnSave: false,
productionSourceMap: false,
configureWebpack: {
resolve: {
alias: {
mediaAsset: path.resolve(__dirname, './src/components/Audio/assets'),
},
},
},
chainWebpack: (config) => {
const imgRule = config.module.rule('images');
imgRule
.use('url-loader')
.loader('url-loader')
.tap((options) => Object.assign(options, { limit: Infinity }));
const svgRule = config.module.rule('svg');
svgRule.uses.clear();
svgRule
.test(/\.svg$/)
.use('svg-url-loader') // npm install --save-dev svg-url-loader
.loader('svg-url-loader');
config.module
.rule('raw')
.test(/\.txt$/)
.use('raw-loader')
.loader('raw-loader');
config.module
.rule('media')
.test(/\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/)
.use('url-loader')
.loader('url-loader')
.tap((options) =>
Object.assign(options, {
limit: 4096,
fallback: {
loader: 'file-loader',
options: {
name: 'media/[name].[hash:8].[ext]',
},
},
})
);
},
};
Appreciated for answering this question. Thanks.

How do I load environment variables in Vue.js without webpack?

The question has it all, but basically, I set up a new vue app without webpack. When I try to do:
handleSubmit() {
axios
.post(`${process.env.VUE_APP_API_URL}`)
.then(response => (this.info = response));
this.$router.push({ name: "ConversationsList" });
}
It's undefined. In my .env file, I have:
VUE_APP_API_URL=http://localhost:3000
What do I have to do now?
Easy fix. Created a file called vue.config.js:
const webpack = require('webpack')
module.exports = {
configureWebpack: {
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV)
}
})
]
}
}