google/model-viewer with nuxt - vue.js

I'm a bit clueless with integrating the #google/model-viewer into a nuxtjs project:
This is my model-viewer.js in the plugins folder
import Vue from "vue";
import modelViewer from "#google/model-viewer";
Vue.use(modelViewer);
The part in my nuxt.config.js
plugins: [
"#/plugins/hooks",
{ src: "#/plugins/gsap", mode: "client" },
{ src: "#/plugins/model-viewer", mode: "client" },
],
... and the component so far
<template>
<model-viewer
:src="src"
bounds="tight"
enable-pan
camera-controls
environment-image="neutral"
poster="poster.webp"
shadow-intensity="1"
autoplay
></model-viewer>
</template>
<script lang="ts">
export default {
ssr: false,
name: "Viewer3d",
props: {
src: {
type: String,
required: true,
},
},
setup() {
return {};
},
};
</script>
When called I get the Error
Failed to compile with 1 errors friendly-errors 13:36:36
ERROR in
./node_modules/#google/model-viewer/dist/model-viewer.min.js
friendly-errors 13:36:36
Module parse failed: Unexpected token (999:5963)
friendly-errors 13:36:36 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 | * limitations
under the License. | */
and a
window is not defined
from my browser.
What am I missing? I am not familiar with loaders in nuxt and wasn't able to find something helping me with my problem.

I had the same issue but with NuxtJS. Try to use an older version of the model-viewer, everything until version 1.10.1 is working for me.

Related

Is it possible to configure Vite to build for use inside Android app (CORS error)

Scenario
I'm using Vue2 with Vue CLI as the bundling tool, now I want to migrate Vue CLI to Vite to enhance the development experience, and the migration process is somewhat successful (thanks to this guide).
Problem
Due to a specific reason, I need to keep the production build accessible statically, without any local server required (the web app should run simply by opening up the index.html file on my machine). And with this, I encounter the problem due to the fact that Vite bundles my code in ESM format that has to be served through some server to resolve CORS policy (error screenshot below). And hence the question: Is it possible to configure Vite to build in plain JS rather than ESM?
Any help is appreciated. Thank you.
Attachments
My vite.config.js as below if it helps:
import path from "path";
import { defineConfig } from "vite";
import { createVuePlugin } from "vite-plugin-vue2";
export default defineConfig({
base: "",
css: {
preprocessorOptions: {
scss: {
additionalData: `
#use "sass:math";
#import "#/scss/utils.scss";`,
},
},
},
plugins: [createVuePlugin()],
resolve: {
extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"]
alias: {
"#": path.resolve(__dirname, "./src"),
},
},
});

Unable to load stencil components lib with Vue3 using Vite

I created a sample project to reproduce this issue: https://github.com/splanard/vue3-vite-web-components
I initialized a vue3 project using npm init vue#latest, as recommanded in the official documentation.
Then I installed Scale, a stencil-built web components library. (I have the exact same issue with the internal design system of my company, so I searched for public stencil-built libraries to reproduce the issue.)
I configured the following in main.ts:
import '#telekom/scale-components-neutral/dist/scale-components/scale-components.css';
import { applyPolyfills, defineCustomElements } from '#telekom/scale-components-neutral/loader';
const app = createApp(App);
app.config.compilerOptions.isCustomElement = (tag) => tag.startsWith('scale-')
applyPolyfills().then(() => {
defineCustomElements(window);
});
And the same isCustomElement function in vite.config.js:
export default defineConfig({
plugins: [vue({
template: {
compilerOptions: {
isCustomElement: (tag) => tag.startsWith('scale-')
}
}
})]
// ...
})
I inserted a simple button in my view (TestView.vue), then run npm run dev.
When opening my test page (/test) containing the web component, I have an error in my web browser's console:
failed to load module "http://localhost:3000/node_modules/.vite/deps/scale-button_14.entry.js?import" because of disallowed MIME type " "
As it's the case with both Scale and my company's design system, I'm pretty sure it's reproducible with any stencil-based components library.
Edit
It appears that node_modules/.vite is the directory where Vite's dependency pre-bundling feature caches things. And the script scale-button_14.entry.js the browser fails to load doesn't exist at all in node_modules/.vite/deps. So the issue might be linked to this "dependency pre-bundling" feature: somehow, could it not detect the components from the library loader?
Edit 2
I just found out there is an issue in Stencil repository mentioning that dynamic imports do not work with modern built tools like Vite. This issue has been closed 7 days ago (lucky me!), and version 2.16.0 of Stencil is supposed to fix this. We shall see.
For the time being, dropping the lazy loading and loading all the components at once through a plain old script tag in the HTML template seems to be an acceptable workaround.
<link rel="stylesheet" href="node_modules/#telekom/scale-components/dist/scale-components/scale-components.css">
<script type="module" src="node_modules/#telekom/scale-components/dist/scale-components/scale-components.esm.js"></script>
However, I can't get vite pre-bundling feature to ignore these imports. I configured optimizeDeps.exclude in vite.config.js but I still get massive warnings from vite when I run npm run dev:
export default defineConfig({
optimizeDeps: {
exclude: [
// I tried pretty much everything here: no way to force vite pre-bundling to ignore it...
'scale-components-neutral'
'#telekom/scale-components-neutral'
'#telekom/scale-components-neutral/**/*'
'#telekom/scale-components-neutral/**/*.js'
'node_modules/#telekom/scale-components-neutral/**/*.js'
],
},
// ...
});
This issue has been fixed by Stencil in version 2.16.
Upgrading Stencil to 2.16.1 in the components library dependency and rebuilding it with the experimentalImportInjection flag solved the problem.
Then, I can import it following the official documentation:
main.ts
import '#telekom/scale-components-neutral/dist/scale-components/scale-components.css';
import { applyPolyfills, defineCustomElements } from '#telekom/scale-components-neutral/loader';
const app = createApp(App);
applyPolyfills().then(() => {
defineCustomElements(window);
});
And configure the custom elements in vite config:
vite.config.js
export default defineConfig({
plugins: [vue({
template: {
compilerOptions: {
isCustomElement: (tag) => tag.startsWith('scale-')
}
}
})]
// ...
})
I did not configure main.ts
stencil.js version is 2.12.1,tsconfig.json add new config option in stencil:
{
"compilerOptions": {
...
"skipLibCheck": true,
...
}
}
add new config option in webpack.config.js :
vue 3 document
...
module: {
rules:[
...
{
test: /\.vue$/,
use: {
loader: "vue-loader",
options: {
compilerOptions: {
isCustomElement: tag => tag.includes("-")
}
}
}
}
...
]
}
...

Nuxt.js returns undefined for custom plugin

I wanted to create a custom plugin for a local databaase in Nuxt.js, after I was done with the code I registered it in nuxt.config.js and it didn't work. So I've tried the example code on docs to see what I was doing wrong, and the thing is, example code didn't work too. Here is how I registered it:
plugins/hello.js
export default ({ app }, inject) => {
inject("hello", msg => console.log(`Hello ${msg}!`));
};
nuxt.config.js
module.exports = {
ssr: false,
target: "static",
head: {
title: "project-title",
meta: [{ charset: "utf-8" }],
},
loading: false,
plugins: [{ ssr: true, src: "#/plugins/icons.js" }, "#/plugins/hello.js"],
modules: ["#nuxtjs/axios", "#nuxtjs/auth-next"],
}
Whenever I try to use this.$hello("something"), Nuxt returns this.$hello is not a function
Hmm, got it. After deleting and reinstalling node_modules it's resolved, then I tried changing the name of the plugin file, after then build failed from ./node_modules/#nuxt/webpack/node_modules/babel-loader/lib/index.js. After reinstalling packages again (deleted .nuxt, node_modules and lock file) issue is resolved.

Cant import JS library to my Nuxt project

I have weird problem.
I want use this hover-effect library (https://github.com/robin-dela/hover-effect) in my nuxt project.
This i have in my contact.vue in script tags
import hoverEffect from 'hover-effect'
export default {
mounted() {
const effect = new hoverEffect({
parent: document.querySelector('.right-section'),
intensity: 0.3,
image1: require('#/assets/images/1.jpg'),
image2: require('#/assets/images/2.jpg'),
displacementImage: require('#/assets/images/dist2.jpg'),
})
},
}
And that effect works perfectly.. BUT when i refresh the page i got this error:
SyntaxError Cannot use import statement outside a module
So i tried add this plugin into plugins/hover-effect.js
import Vue from 'vue'
import hoverEffect from 'hover-effect'
Vue.use(hoverEffect)
then in nuxt.config.js
plugins: [{ src: '~/plugins/hover-effect', mode: 'client' }],
But nothing works.. its always error: hoverEffect is not defined. I tried another 20 ways with no success. I tried this effect in normal Vue project and it works but not in nuxt.js. Can somebody help me with this?
You can configure it in the head of the page:
Page.vue
export default {
head() {
return {
script: [
{src: '../dist/hover-effect.umd.js'}
]
}
},
...
mounted() {
const effect = new hoverEffect({
parent: document.querySelector('.right-section'),
intensity: 0.3,
image1: require('#/assets/images/1.jpg'),
image2: require('#/assets/images/2.jpg'),
displacementImage: require('#/assets/images/dist2.jpg'),
})
},
modules: [
// Doc: https://axios.nuxtjs.org/usage
'#nuxtjs/axios',
// Doc: https://github.com/nuxt/content
'#nuxt/content',
'hover-effect'
],
Have you tried to add hover-effect library to modules in nuxt.config.js file? All I did was install the package and add it to the module and then have the same code as your script tag. Hope it helped you!

plugin is not defined in instance.vue

I struggle to add a plugin in Nuxt.js. I have been looking to the doc and all kind of similar problems, but I got the same error: simpleParallax is not defined.
I tried different approach on all files
nuxt.config.js:
plugins: [
{src: '~/plugins/simple-parallax.js', mode:'client', ssr: false}
],
plugins/simple-parallax.js:
import Vue from 'vue';
import simpleParallax from 'simple-parallax-js';
Vue.use(new simpleParallax);
index.vue:
Export default {
plugins: ['#/plugins/simple-parallax.js'],
mounted() {
var image = document.getElementsByClassName('hero');
new simpleParallax(image, {
scale: 1.8
});
}
}
Error message:
ReferenceError: simpleParallax is not defined.
The best solution I found out so far is to register simpleParallax on the Vue prototype like so in a plugin nuxt file with the name simple-parallax.client.js:
import Vue from 'vue';
import simpleParallax from 'simple-parallax-js';
Vue.prototype.$simpleParallax = simpleParallax;
Also my nuxt.config.js file if anyone would like to verify that as well:
plugins: [
{src: '~/plugins/simple-parallax.client.js', mode: 'client', ssr: false}
],
I then have access to the plugin before instantiation in my case in the mounted life cycle of the primary or root component to grab the desired HTML elements and instantiate their individual parallax with the newly added global method this.$simpleParallax
For example I can then intiate a certain HTML element to have its parallax like so:
const someHTMLElement = document.querySelectorAll('.my-html-element');
const options = {...} // your desired parallax options
new this.$simpleParallax(someHTMLElement, options);
Actually you don't need to use plugin here.
Just import simpleParallax from 'simple-parallax-js' in your component and init it with your image in mounted hook.
index.vue:
import simpleParallax from 'simple-parallax-js'
export default {
...
mounted() {
// make sure this runs on client-side only
if (process.client) {
var image = document.getElementsByClassName('thumbnail')
new simpleParallax(image)
}
},
...
}
And don't forget to remove previously created plugin, it's redundant here.