How to use <audio/> in Nuxt-js project? - vue.js

I keep my mp3 files and image under static file. I can reach my images with below method but i can not reach my mp3 files. I did some settings on nuxt.config.js but still i cant reach mp3 files .
index.vue
<v-col v-for="i in 28" :key="i" >
<v-card active-class="active">
<v-img :src="require(`#/static/drawable/pic-${i}.png`)" />
<audio :src="music[i].src" controls/>
</v-card>
<v-col/>
<script>
import music from "~/constants/musics.js";
export default {
setup(){
return{
music
}
}
}
<script/>
*audio output => <audio data-v-14f3866a="" src="[object Module]" controls="controls"></audio>*
music.js
const listOfMusic = [
{
src: require("#/static/music/adele.mp3"),
}
........
];
export default listOfMusic;
nuxt.config.js
extend (config, { isDev, isClient }) {
config.module.rules.push({
test: /\.(ogg|mp3|wav|mpe?g)$/i,
loader: 'file-loader',
query: {
name: 'static/raw/[name].mp3'
}
})
},
if i import music files one by one , they will work but this method is expensive for me
import adele from '#/static/raw/adele.mp3'

You should reference your asset directly using /raw/adele.mp3 as explained in the docs: https://nuxtjs.org/docs/directory-structure/static/#static-assets
No need for a static in your path.

Related

Loading mermaid in a vue component (webpack)

I am migrating a vue project that uses mermaid from CDN to webpack. I'm total new with it. I did npm install save mermaid on project folder.
If i load mermaid cdn as static js (in /public/index.html), it crashes for some graphs (shows bomb icon, says syntax error)
If in webpack, it shows nothing as mermaid graphs, but seems to load empty (inspecting generated html with browser tools). No console errors
<svg id="mermaidChart0" width="100%" xmlns="http://www.w3.org/2000/svg"><g><g class="output"><g class="clusters"></g><g class="edgePaths"></g><g class="edgeLabels"></g><g class="nodes"></g></g></g></svg>
Tried:
//package.json
...
"dependencies": {
"axios": "^0.21.0",
"core-js": "^3.6.5",
"mermaid": "^8.8.2",
and in the component.vue
<template>
...
<div class="mermaid m-5">
graph LR
B(dsfgdsfgsd <br>) --> Bo(gdfshfghfdh <br>)
...
<script>
import mermaid from 'mermaid'
export default {
data: function() {
return {}
},
mounted() {
this.init();
},
methods: {
init: function() {
mermaid.initialize({
theme: 'forest',
htmlLabels: true,
//startOnLoad: true
});
console.log(mermaid);
mermaid.init(undefined, document.querySelectorAll('.mermaid'));
}
}
}
If you want a ready-to-use solution, you can use my component vue-mermaid-string. It does the internal work for you.
Install it via NPM, then add it to your project via CDN script or by adding the component, then use it like so:
<template>
<vue-mermaid-string :value="diagram" />
</template>
<script>
export default {
computed: {
diagram: () => 'graph TD\n A --> B',
},
}
</script>

Is there a way to use Hypenova with Nuxt and VueJs and make SSR?

I try to use Ara Framework to implement micro-frontend. I chose Nuxt framework as my main application which "concatanate" my micro-frontends. Micro-frontend are implemented with VueJs framework.
Here is one of my micro-frontend (in VueJs) which implement a pretty simple component :
ResumeFournisseur.vue:
<template>
<b-row>
<b-col cols="3">
<div>
LOGO
</div>
<div>
<label>Choisissez votre fournisseur :</label>
<select name="supplier" v-model="sellerSelectedValue">
<option v-for="fournisseur in fournisseurs"
:key="fournisseur.id"
v-bind:value="fournisseur.id">
{{ fournisseur.name }}
</option>
</select>
<button class="u-btn u-btn-primary">Voir les produits</button>
</div>
</b-col>
<b-col cols="9">
<h1>{{ sellerSelectedLabel }}</h1>
</b-col>
</b-row>
</template>
<script>
export default {
name: 'ResumeFournisseur',
props: {
supplierId: String
},
data() {
const fournisseurs = [
{
id: -1,
name: 'Aucun fournisseur'
},
{
id: 1,
name: 'Renault'
},
{
id: 2,
name: 'Acial'
}
];
return {
sellerSelectedValue: fournisseurs[0].id,
fournisseurs : fournisseurs,
sellerSelectedLabel: fournisseurs[0].name,
}
},
mounted() {
if (typeof this.supplierId != 'undefined'){
this.sellerSelectedValue = this.supplierId;
}
},
watch: {
sellerSelectedValue: function () {
const recup = this.fournisseurs.filter(four => four.id == this.sellerSelectedValue);
this.sellerSelectedLabel = recup[0].name;
}
}
}
</script>
And here my index.js file :
import hypernova from 'hypernova/server'
import {renderVuex, renderVue, Vue} from 'hypernova-vue/server'
import express from 'express'
import path from 'path'
import BootstrapVue from 'bootstrap-vue/dist/bootstrap-vue.esm';
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap-vue/dist/bootstrap-vue.css';
//import createStore from './store/modules/listComponent'
import ResumeFournisseur from './components/ResumeFournisseur';
Vue.use(BootstrapVue)
hypernova({
devMode: process.env.NODE_ENV !== 'production',
getComponent(name) {
switch (name) {
case 'ResumeFournisseur' :
return renderVue(name, Vue.extend(ResumeFournisseur));
}
},
port: process.env.PORT || 3001,
createApplication() {
const app = express()
app.use('/public', express.static(path.join(process.cwd(), 'dist')))
return app
}
})
Then in my Nuxt application I do :
<template>
<b-container fluid>
<div>
<nova name="ResumeFournisseur" :data="{}"/>
</div>
</b-container>
</template>
<script>
import Nova from "nova-vue-bridge";
import NovaClusterService from "../middleware/novaClusterService";
export default {
components: {
Nova
},
head () {
return {
title: 'Accueil',
script: [
{ src:
'http://localhost:3001/public/client.js'
}
]
}
}
}
</script>
It works pretty good.
But when I tried to use Nova Cluster aggregator combined with Nova Proxy, I don't know how to render my micro-fontend in my Nuxt application without using the http://localhost:3001/public/client.js.
Here my views.json file :
{
"ResumeFournisseur": {
"server": "http://localhost:3001/batch"
}
}
And here my nova-proxy.json file :
{
"locations": [
{
"path": "/",
"host": "http://localhost:3000",
"modifyResponse": true
}
]
}
(for remember, Nuxt is running on 3000 port).
I run ara run cluster --config ./views.json (as the documentation said). Then I run
set HYPERNOVA_BATCH=htpp://localhost:8000/batch
ara run:proxy --config nova-proxy.json
As I'm on Windows environnement I do a set.
When I make a post on nova cluster like :
{
"ResumeFournisseur": {
"name": "ResumeFournisseur",
"data": {
}
}
}
It makes a good response. Pretty good !! But nova proxy doesn't do anythning :(. Documentation said that if it's bound to nova cluster (thanks to HYPERNOVA_BATCH variable) it will able to render the views rendered by nova cluster.
Of course, if I embed the cluster reponse in a v-html directive (in my NuxtJs main application), the micro-frontend is embeded but is not doing anything (not interactive).
Am I missing something ?? I read a lot of documentation of this subject, and I'm doubting on my choices/understanding.
If there's anyone who could help me, it's could really great :) !!!
Finally, I found my missunderstanding. I have to go to http://localhost:8080 on my browser and it will call the nova proxy which calls himself the nova cluster.
In fact, you can't remove the client.js use, because thanks to that you got your business side.
I found an article on stackoverflow about this subject.

How to fix 'Cannot find module' in a vuejs module with npm link

I've created a vuejs library with some components that could be used in many project.
In that library, I've got a component which can load svg files to be used inline in html (svg-icon).
It work great.
But in this same library, I've got another component which use svg-icon with a svg image stored in the library.
An import point, I'd like to use this library (node module) with an npm link
Which is the good way to give the path of the svg image, or where to store it?
I've tried a lot of different paths, but none of them is working...
This is my svg-icon component:
<template>
<component :is="component"></component>
</template>
<script>
export default {
name: 'SvgIcon',
props: {
icon: {
type: String,
required: true
}
},
data () {
return {
component: null
}
},
watch: {
icon: () => {
this.load()
}
},
computed: {
loader () {
return () => import(this.icon)
}
},
methods: {
load () {
this.loader().then(() => {
this.component = () => this.loader()
})
}
},
mounted () {
this.load()
}
}
</script>
And this is the component which use svg-icon (the svg image is in the same folder actually) :
<template>
<svg-icon icon="~my-module/components/media/no-image.svg"></svg-icon>
<svg-icon icon="./no-image.svg"></svg-icon>
</template>
<script>
import SvgIcon from '../svg-icon/SvgIcon'
export default {
components: {
SvgIcon
}
}
</script>
I always got this errors:
Cannot find module '~my-module/components/media/no-image.svg'
Cannot find module './no-image.svg'
Which is the good path in that situation? Or should I put the svg file somewhere else? (I'd like to keep it in the library)
I've created a CodeSandbox here
SvgIcon.vue
<template>
<span v-html="icon"></span>
</template>
<script>
export default {
name: "SvgIcon",
props: {
icon: {
type: String,
required: true
}
}
};
</script>
HelloWorld.vue
//Usage
<template>
<svg-icon :icon="AlertIcon"></svg-icon>
</template>
<script>
import AlertIcon from "../assets/alert.svg";
import SvgIcon from "./SvgIcon";
export default {
data() {
return { AlertIcon };
},
components: {
SvgIcon
}
};
</script>
I've made some changes to your components.
You need to import the image and pass it to your component because dynamic import causes complications when it comes to the absolute paths.
I've removed some unnecessary fields from your SvgIcon code.
Hope this helps.

window is not defined Nuxt for vue-slick

Hello I am having an issue with Nuxts ssr. I a trying to add 'vue-slick' to my web app and no matter what I do it continues to show "window is not defined".
As you can see I have tried multiple ways to allow vue-slick to be loaded on client side. Using plugins didn't help, using process.client in my component did not work as well.
Components/Carousel/Carousel.vue
<template>
<div class="carousel">
<Slick ref="slick" :options="slickOptions">
<a href="http://placehold.it/320x120">
<img src="http://placehold.it/320x120" alt="">
</a>
...
<a href="http://placehold.it/420x220">
<img src="http://placehold.it/420x220" alt="">
</a>
</Slick>
</div>
</template>
<script>
if (process.client) {
require('vue-slick')
}
import Slick from 'vue-slick'
export default {
components: {
Slick
},
data() {
return {
slickOptions: {
slidesToShow: 4
},
isMounted: false
}
},
methods: {
}
}
</script>
nuxt.config.js
plugins: [
{ src: '~/plugins/vue-slick', ssr: false }
],
plugins/vue-slick
import Vue from 'vue'
import VueSlick from 'vue-slick'
Vue.use(VueSlick);
Thanks for any help you can give!
So this is due to nuxt trying to render the slick component on the server side, even though you have set ssr: false in nuxt.config.
I have had this issue in other nuxt plugins and these steps should fix it.
in nuxt.config.js add this to your build object:
build: {
extend(config, ctx) {
if (ctx.isServer) {
config.externals = [
nodeExternals({
whitelist: [/^vue-slick/]
})
]
}
}
}
and in the page where you are trying to serve it you have to not mount the component until the page is fully mounted. So in your Components/Carousel/Carousel.vue set it up like this:
<template>
<div class="carousel">
<component
:is="slickComp"
ref="slick"
:options="slickOptions"
>
<a href="http://placehold.it/320x120">
<img src="http://placehold.it/320x120" alt="">
</a>
...
<a href="http://placehold.it/420x220">
<img src="http://placehold.it/420x220" alt="">
</a>
</component>
</div>
</template>
Then in your script section import your component and declare it like this:
<script>
export default {
data: () => ({
'slickComp': '',
}),
components: {
Slick: () => import('vue-slick')
},
mounted: function () {
this.$nextTick(function () {
this.slickComp = 'Slick'
})
},
}
</script>
Bascially this means the component isn't declared until the mounted function is called which is after all the server side rendering. And that should do it. Good luck.
I found another simple solution.
simply install "vue-slick" package to your nuxt project.
$ yarn add vue-slick
then component markup like below.
<template>
<component :is="slick" :options="slickOptions">
<div>Test1</div>
<div>Test2</div>
<div>Test3</div>
</component>
</template>
Finally set data and computed properties like this.
data() {
return {
slickOptions: {
slidesToShow: 1,
slidesToScroll: 1,
infinite: true,
centerMode: true,
},
};
},
computed: {
slick() {
return () => {
if (process.client) {
return import("vue-slick");
}
};
},
},
This solution prevents slick component importing globally as a plugin in nuxt config.

relative module was not found: vue-lottie

After a fresh build with vue-cli (3.0.0-rc.5) the path to the lottie module can't be reached. Should I play with the configs?
./lottie.vue in ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/HelloWorld.vue?vue&type=script&lang=js&
<template>
<div id="app">
<lottie :options="defaultOptions" :height="400" :width="400" v-on:animCreated="handleAnimation"/>
<div>
<p>Speed: x{{animationSpeed}}</p>
<input type="range" value="1" min="0" max="3" step="0.5"
v-on:change="onSpeedChange" v-model="animationSpeed">
</div>
<button v-on:click="stop">stop</button>
<button v-on:click="pause">pause</button>
<button v-on:click="play">play</button>
</div>
<script>
import Lottie from './lottie.vue';
import * as animationData from './assets/data.json';
export default {
name: 'app',
components: {
'lottie': Lottie
},
data() {
return {
defaultOptions: {animationData: animationData},
animationSpeed: 1
}
},
methods: {
handleAnimation: function (anim) {
this.anim = anim;
},
stop: function () {
this.anim.stop();
},
play: function () {
this.anim.play();
},
pause: function () {
this.anim.pause();
},
onSpeedChange: function () {
this.anim.setSpeed(this.animationSpeed);
}
}
}
</script>
If it still doesn't work change animationData to animationData.default in defaultOptions
defaultOptions: { animationData: animationData.default }
If you are using vue-lottie package then the import should be
import Lottie from 'vue-lottie';
This is because lottie package is located in the node_modules folder and you have to provide the right path or use direct package name import.
On a side note, I believe the current version of Vue cli is v3.1.1 so you should definitely upgrade.