Can't generate Nuxt website with #googlemaps/js-api-loader - javascript

I am using #googlemaps/js-api-loader in my Nuxt 3 website. Everything works fine in local development, but when I try to build the project with nuxt generate (no matter if locally or on Vercel) I'm getting following error:
[nuxt] [request error] Named export 'Loader' not found. The requested module 'file:///path/to/website/node_modules/#googlemaps/js-api-loader/dist/index.umd.js' is a CommonJS module, which may not support all module.exports as named exports. CommonJS modules can always be imported via the default export, for example using:
The important part of loading script looks like this:
import { Loader } from '#googlemaps/js-api-loader';
const loader = new Loader({
apiKey: config.googleMapsApiKey,
version: 'weekly',
});
onMounted(async() => {
await loader
.load()
...
so I tried to import this package differently, e.g.:
import * as gmaps from '#googlemaps/js-api-loader';
const { Loader } = gmaps;
and the previous error disappeared, but now I'm getting
[Vue warn]: Unhandled error during execution of setup function
at <DynamicLocations class="contact__map" locations= [
{
id: 1,
...
[nuxt] [request error] gmaps.Loader is not a constructor
at setup (./.nuxt/prerender/chunks/app/server.mjs:5536:20)
at _sfc_main$t.setup (./.nuxt/prerender/chunks/app/server.mjs:5582:25)
at callWithErrorHandling (./.nuxt/prerender/chunks/renderer.mjs:2654:23)
at setupStatefulComponent (./.nuxt/prerender/chunks/renderer.mjs:9548:30)
at setupComponent (./.nuxt/prerender/chunks/renderer.mjs:9503:12)
at renderComponentVNode (./.nuxt/prerender/chunks/renderer.mjs:12068:17)
at Object.ssrRenderComponent (./.nuxt/prerender/chunks/renderer.mjs:12504:12)
at ./.nuxt/prerender/chunks/app/server.mjs:5628:36
at renderComponentSubTree (./.nuxt/prerender/chunks/renderer.mjs:12149:13)
at renderComponentVNode (./.nuxt/prerender/chunks/renderer.mjs:12084:16)
I also can't import package by default export. Do you have any ideas what's going on and how can I fix this?

I found a documentation page related to this problem and there is the following information:
If you encounter these errors, the issue is almost certainly with the upstream library. They need to fix their library to support being imported by Node.
Although they provide a solution to get rid of errors by adding the package to build.transpile:
build: {
transpile: ['#googlemaps/js-api-loader'],
},
It worked for me

Related

Can't import Vonage Client SDK into my preact (vite) project

I have a Preact project using Vite. I want to use the nexmo-client SDK from vonage but when I import using the ES method it breaks my project.
// app.tsx
import NexmoClient from 'nexmo-client';
I get the following error in the console.
index.js:19 Uncaught ReferenceError: global is not defined
at index.js:19:19
at index.js:12:22
at node_modules/nexmo-client/dist/index.js (index.js:16:1)
at __require (chunk-J43GMYXM.js?v=f3505250:11:50)
at dep:nexmo-client:1:16
However if I import it using via a script tag it works just fine.
// index.html
<script src="node_modules/nexmo-client/dist/nexmoClient.js"></script>
// app.tsx
const NexmoClient = window.NexmoClient;
OK, there are two problems here.
Firstly, NexmoClient tries to use global which is not available on the browser.
Secondly, NexmoClient has a dependency on socket.io-client, for some reason Vite imports a Node version of the socket.io-client that again tries to use modules that are not available on the browser, namely 'child_process'.
To fix both issues you can provide the following config to Vite, this should make sure the resulting build is compatible with the brother.
// vite.config.js or vite.config.ts
import { defineConfig } from 'vite'
import preact from '#preact/preset-vite'
export default defineConfig({
plugins: [preact()],
define: {
global: {},
},
resolve: {
alias: {
"xmlhttprequest-ssl": "./node_modules/engine.io-client/lib/xmlhttprequest.js"
}
}
})

Client-only Nuxt 3 Vue plugin

I am new to Nuxt and Vue, so go easy on me. I am trying to create a video player component in my Nuxt 3 app using vue3-video-player, which doesn't seem to support SSR based on the following error I get when I import it in my video component:
ReferenceError: navigator is not defined
This error persists even if the component is wrapped with <ClientOnly>. So, based on what I saw in the Nuxt 3 Documentation I thought I would create a client-only plugin located at plugins/vue3-video-player.client.js with the following contents:
import Vue3VideoPlayer from '#cloudgeek/vue3-video-player'
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(Vue3VideoPlayer)
})
But when I try to use it in my component as <vue3-video-player>, I get the following error:
[Vue warn]: Failed to resolve component: vue3-video-player
So I guess my question is how do I create a client-only Vue component using Nuxt 3 plugins? Or is there an entirely different approach that would work better?
Solution for nuxt 3:
Nuxt will automatically read the files in your plugins directory and load them. You can use .server or .client suffix in the file name to load a plugin only on the server or client side.
For example:
plugins/apexcharts.client.ts
Everything is so simple! And that is why we love nuxt ❤️
Solution for nuxt 2 (to show the difference):
nuxt.config.ts
plugins: [
{src: '~/plugins/apexcharts', mode: 'client'}
],
This is only for nuxt 2 because All plugins in your nuxt 3 plugins/ directory are auto-registered, so you should not add them to your nuxt.config separately.
you could try to provide a helper function. As mentioned in the docs.
import Vue3VideoPlayer from '#cloudgeek/vue3-video-player'
export default defineNuxtPlugin((nuxtApp) => {
return {
provide: {
Vue3VideoPlayer
}
}
})
To tag along with the given correct answer here,
If you're trying to install and use a third party NPM package, and running into "window is not defined" type errors, you can load the package as a plugin as follows (eg WAD)
npm install web-audio-daw
// plugins/wad.client.ts
import Wad from "web-audio-daw"
export default defineNuxtPlugin(nuxtApp => {
return {
provide: {
Wad,
}
}
})
// pages/whatever.vue
<script lang="ts" setup>
const { $Wad } = useNuxtApp();
// Can use $Wad normally from here on out
</script>

Apollo Client "Named export 'remove' not found"

I'm attempting to create an apollo client plugin for a Nuxt 3 application. It's currently throwing an error regarding a package called ts-invariant:
file:///Users/[my name]/Repositories/[project]/node_modules/#apollo/client/utilities/globals/fix-graphql.js:1
import { remove } from "ts-invariant/process/index.js";
^^^^^^
SyntaxError: Named export 'remove' not found. The requested module 'ts-invariant/process/index.js' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:
import pkg from 'ts-invariant/process/index.js';
const { remove } = pkg;
at ModuleJob._instantiate (node:internal/modules/esm/module_job:124:21)
at async ModuleJob.run (node:internal/modules/esm/module_job:181:5)
at async Promise.all (index 0)
at async ESMLoader.import (node:internal/modules/esm/loader:281:24)
at async __instantiateModule__ (file:///Users/[my name]/Repositories/[project]/.nuxt/dist/server/server.mjs:4550:3)
[vite dev] Error loading external "/Users/[my name]/Repositories/[project]/node_modules/#apollo/client/core/index.js".
at file://./.nuxt/dist/server/server.mjs:3170:289
at async __instantiateModule__ (file://./.nuxt/dist/server/server.mjs:4550:3)
I feel like I know enough about this error to know it has something to do with how Nuxt 3 deals with ESM, but I can't be for certain.
Here's the nuxt plugin:
plugins/apollo-client.js
import { defineNuxtPlugin } from "#app"
import { ApolloClient, InMemoryCache } from "#apollo/client/core"
import { DefaultApolloClient } from "#vue/apollo-composable"
export default defineNuxtPlugin((nuxtApp) => {
const config = useRuntimeConfig()
const apolloClient = new ApolloClient({
uri: config.PUBLIC_API_ENDPOINT,
cache: new InMemoryCache(),
})
nuxtApp.vueApp.provide(DefaultApolloClient, apolloClient)
})
In a normal scenario, I might use the nuxt-apollo community module, but it is currently afk regarding a nuxt 3 port, so a plugin it is.
Here's some documentation I relied on for my plugin:
https://v4.apollo.vuejs.org/guide-composable/setup.html#vue-3
https://v3.nuxtjs.org/docs/directory-structure/plugins
Solved by including #apollo/client and ts-invariant/process into the nuxt build transpile like so:
// nuxt.config.js
// ...
build: {
postcss: {
postcssOptions: require('./postcss.config.js')
},
transpile: [
'#apollo/client',
'ts-invariant/process',
],
},
// ...
I think I've pinpointed the underlying issue. Apollo Client (3.5.10 at the time of writing early 2022) is using "module":"index.js" to declare the path of the ESM exports.
However it seems that Webpack 5 based bundlers do not support this. Using exports in the package.json fixes it for good for me.
You should upvote this feature request.
And here is my palliative until then, using a small script to alter the package.json.

Storybook - Cannot Mock a Nested React-Router-Dom Link without throwing endless NPM errors

I am trying to implement StorybookJS into a SSR React app. Basic components work fine (button, headers etc). But anything that nests using dependencies like react-router-dom breaks.
Example:
We have a custom built <Link /> component that manages external links with a ternary. The external links flip to <a href= while internals use react-router-dom's <Link> imported as <ReactLink />. That code is like this:
// src/client/components/link/Link.js
import { Link as ReactLink } from "react-router-dom";
import { isLinkExternal } from "services/utils";
export const Link = ({ href, children = null, ...props }) => {
return isLinkExternal(href) ? (
<a href={href} {...props}>
{children}
</a>
) : (
<ReactLink to={href} {...props}>
{children}
</ReactLink>
);
};
The StorybookJS file for it looks like this:-
// link.stories.js
import React from "react";
import { Link } from "./Link"; // importing my component
export default {
title: "My Components/Link",
component: Link, // assigning my component
};
export const MyStoryBookLink = () => <Link href="/foo">I am a link</Link>;
Now, when i run Storybook it throws a load of errors, here are the recurring/main ones:-
ERROR in ./node_modules/redis-parser/lib/hiredis.js
Module not found: Error: Can't resolve 'hiredis' in '/Users/me/Documents/my-proj/node_modules/redis-parser/lib'
...
...
# ./.storybook/generated-stories-entry.js
I haven't touched anything redis / hiredis related and there is no such file as generated-stories-entry.js. The app works perfectly in Dev and Production so this is exclusively a Storybook env issue.
Next error down:
ERROR in ./node_modules/cache-manager-ioredis/node_modules/ioredis/lib/connectors/connector.js
Module not found: Error: Can't resolve 'net' in '/Users/me/Documents/myProject/node_modules/cache-manager-ioredis/node_modules/ioredis/lib/connectors'
Again, Though we are using cache-manager-ioredis, no idea why this is suddenly missing a module if it works fine on the app itself and all i'm trying to do is render a .
Next one:
Module not found: Error: Can't resolve 'tls' in cache-manager-ioredis
Same thing again^^
Then i get a load of these:
/Users/me/Documents/myProj/__mocks__/hiredis doesn't exist
.mjs
/Users/me/Documents/myProj/__mocks__/hiredis.mjs doesn't exist
.js
/Users/me/Documents/myProj/__mocks__/hiredis.js doesn't exist
.jsx
/Users/me/Documents/myProj/__mocks__/hiredis.jsx doesn't exist
.ts
/Users/me/Documents/myProj/__mocks__/hiredis.ts doesn't exist
.tsx
/Users/me/Documents/myProj/__mocks__/hiredis.tsx doesn't exist
.json
/Users/me/Documents/myProj/__mocks__/hiredis.json doesn't exist
.cjs
/Users/me/Documents/myProj/__mocks__/hiredis.cjs doesn't exist
Suggests it's looking for mocks to cover these sub sub sub dependencies, wherever they're needed.
I get the same for net and tls.
Finally, I get some:
Field 'browser' doesn't contain a valid alias configuration
I'm thinking somewhere in the depths of using react-router-dom/Link it is trying to find these, and they would only be there if webpack dev server / hot reloading made them accessible, OR if they were transpiled to be accessible from the production bundle.
But how do I mock these out? And is there an easy way to do it rather than manually mocking every sub dependency?
I have tried:
adding __mocks__/react-router-dom.js with an export const Link = ({props}) => <div>{children}</div> but it doesnt seem to kick in.
adding alias logic to .storybook/main.js:
webpackFinal: (config) => {
config.resolve.alias['react-router-dom'] = require.resolve('../__mocks__/react-router-dom.js');
return config;
},
Again, nothing seems to change.
using the storybook-react-router pkg but this seems quite old now, it configs to an old config.js file rather than main.js and uses the older storiesOf syntax. Also couldn't get to do anything.
manually installed tls, hiredis etc as --save-dev dependencies. But this seems hack. Why are these modules missing?
I cannot believe Storybook is this hard to use, more likely I'm overlooking something. I just want to mock something as common and basic as a from RRD.
What am I doing wrong? What am I missing?
I think I found the reason. It is because of node.js packages. To make it work, there are 2 solutions.
avoid importing node.js packages (usually related to SSR) for storybook related code. I use NX to structure my code, so I can easily move those part to its own library and only reference it from the top. (No storybook for the top App either in this solution)
skip those packages in the config.
something like
config.resolve.fallback = { http: false, net: false, tls: false, fs: false, dns: false, path: false };

Stats is not exported by node_modules error - Rollup

I'm trying to add stats.js ( a little fps counter ) to my three.js scene. The project uses rollup to bundle everything and I keep getting this error after trying to import Stats like so:
import { Stats } from 'stats.js'
The error reads:
[!] Error: 'Stats' is
not exported by node_modules\stats.js\build\stats.min.js, imported by src\main.js
My rollup config looks like this:
import resolve from '#rollup/plugin-node-resolve'; // locate and bundle dependencies in node_modules (mandatory)
import { terser } from "rollup-plugin-terser"; // code minification (optional)
export default {
input: 'src/main.js',
output: [
{
format: 'umd',
name: 'LIB',
file: 'build/main.js'
}
],
plugins: [ resolve(), terser() ]
};
Stats is exported in stats.js like this:
export { Stats as default };
I keep scrolling through bug reports on github and i'm unsure if they relate or not - getting confused - does anyone have a clue?
EDIT: based in the initial answer, I tried using:
import * as Stats from 'stats.js'
i get the error message:
Uncaught TypeError: Cannot set property 'Stats' of undefined
referencing this line:
(function(f,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"===typeof define&&define.amd?define(e):f.Stats=e();})(undefined,function(){var f=function(){function e(a){c.appendChild(a.dom);return a}function u(a){for(var d=0;d<c.children.length;d++)c.children[d].style.display=d===a?"block":"none";l=a;}var l=0,c=document.createElement("div");c.style.cssText="position:fixed;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000";c.addEventListener("click",function(a){a.preventDefault();
__
I tried:
const Stats = require('stats-js');
and got the error message:
Uncaught ReferenceError: require is not defined
__
I tried:
import Stats from 'stats-js'
and got this:
(!) Unresolved dependencies
https://rollupjs.org/guide/en/#warning-treating-module-as-external-dependency
stats-js (imported by src\main.js)(!) Missing global variable name
Use output.globals to specify browser global variable names corresponding to external modules
stats-js (guessing 'Stats')
I sounds like this last error is the most useful? I followed the link in the error message but still can't fix it.
That library doesn’t provide an es6 default export.
import * as Stats from 'stats-js'
// or
const Stats = require('stats-js')
// or
import Stats from 'stats-js'
I had a similar error to yours, but I found the reason and used the following code when importing
import {} from 'Stats.js'
(sorry for using a translator)

Categories