Multiple conflicting contents for sourcemap source error when using client-only - nuxtjs3

I have a component that uses windows so I rendered it with client-only like:
<template>
<h2>Testing Component2</h2>
<client-only>
<Component2></Component2>
</client-only>
</template>
<script lang="ts">
import Component2 from './component-2'
export default defineComponent({
components: {
Component2
},
setup() {}
})
</script>
this works locally, the problem is that when I try to build to deploy, it always returns the error:
Multiple conflicting contents for sourcemap source error ./src/pages/index.vue
Is there a way to fix this or am I doing something wrong?

I used
LazyClientOnly
and there add a lazy import for the component like: Component2: () => import('./component-2') and works perfectly

Related

Lazy loading fontawesome icons in vue3 + vite not working in DEV

In my vue3+vite project I'm using the official fontawesome vue3 package (see use with vue).
In order to enable tree-shaking you need to statically load the necessary icons (or possibly all of them) in advance using library.add. See for instance the following App.vue
<script setup>
import { ref, computed } from "vue";
import { library } from "#fortawesome/fontawesome-svg-core";
import { FontAwesomeIcon } from "#fortawesome/vue-fontawesome";
import { definition } from "#fortawesome/free-solid-svg-icons/faTruck";
library.add(definition);
const icon = ref("");
const showIcon = () => { icon.value = `fa-solid fa-truck`; };
</script>
<template>
<button #click="showIcon">Show Truck Icon</button>
<div v-if="icon">
<font-awesome-icon :icon="icon" />
</div>
</template>
here we statically load the truck icon and when you click the button the icon shows up.
What I was trying to do is loading the icons on demand (in this case, only when the button is clicked), using the following code:
<script setup>
import { ref, computed } from "vue";
import { library } from "#fortawesome/fontawesome-svg-core";
import { FontAwesomeIcon } from "#fortawesome/vue-fontawesome";
const modules = import.meta.glob(
"../node_modules/#fortawesome/free-solid-svg-icons/faTruck.js",
{ eager: false, import: "definition" }
);
const icon = ref("");
const showIcon = () => {
Object.values(modules)[0]().then((elem) => {
library.add(elem);
icon.value = `fa-solid fa-truck`;
});
};
</script>
<template>
<button #click="showIcon">Show Truck Icon</button>
<div v-if="icon">
<font-awesome-icon :icon="icon" />
</div>
</template>
But this doesn't work in "develpment" (npm run dev):
it makes a call to http://localhost:5173/node_modules/#fortawesome/free-solid-svg-icons/faTruck.js
then raises an error: Uncaught (in promise) ReferenceError: exports is not defined
while it works fine when the bundle is built (npm run build then for example serve the dist folder with http-server)
I suspect the problem is related to the fact that in development mode faTruck.js module is used "as is", while it is transpiled in the build phase.
Is there a solution?
NOTE:
The example contains only the "truck" because is over-simplified, but actually any icon should be loaded; i.e. the actual path in import.meta.glob should be ../node_modules/#fortawesome/free-solid-svg-icons/fa*.js
Full steps to reproduce the issue:
npm create vue#3 # accepts all defaults
cd vue-project
npm i #fortawesome/fontawesome-svg-core #fortawesome/free-solid-svg-icons #fortawesome/vue-fontawesome
# replace src/App.vue with the one indicated above
# run in dev with
npm run dev
# or build for prod and then expose using http-server
npm run build
npx http-server dist
Explaination
According to the Vite pre-bundling docs:
Vite's dev serves all code as native ESM. Therefore, Vite must convert dependencies that are shipped as CommonJS or UMD into ESM first
But when you use glob import with dynamic variables, your modules will not be pre-bundled. Since #fortawesome/free-solid-svg-icons/faTruck.js is a CommonJS file, it can not be used directly in ESM. And you are right that Vite does transform the module on production build, so it works well on production.
You may think about the optimizeDeps.include option but unfortunately, it does not help in this situation. Even if you add your module to the include list, Vite does pre-bundle your module but it will not use that pre-bundled file for your dynamic import. It still uses the file in node_modules/#fortawesome/free-solid-svg-icons/ folder.
I'm afraid that there is no straightforward solution to your problem. See this issue
Workaround
Just make it work differently on dev and prod.
const showIcon = async () => {
let x = 'faTruck'
let definition
if (import.meta.env.PROD) {
const iconModule = await import(
`../node_modules/#fortawesome/free-solid-svg-icons/${x}.js`
)
definition = iconModule.definition
} else {
const iconModule = await import(`#fortawesome/free-solid-svg-icons`)
definition = iconModule[x]
}
library.add(definition)
icon.value = `fa-solid fa-truck`
}
With this code, you still have the benefit of lazy loading on production and a smooth dev server to work
Another approach
Hard-coding your import list like so:
const showIcon = async (iconName) => {
const listImport = {
faTruck: () => import(`#fortawesome/free-solid-svg-icons/faTruck`),
faWarning: () => import(`#fortawesome/free-solid-svg-icons/faWarning`),
}
const iconModule = await listImport[iconName]()
console.log('iconModule', iconModule)
library.add(iconModule.definition)
}
But I bet you have hundreds of icons in your list so it hardly is an option

Vue - using props on custom elements fails using createApp and mount?

We would like to pass props to custom elements that uses createApp
// index.html
<div id="my-root">
<my-element prop1="abc"></my-element>
</div>
// my-element.vue
<script lang="ts" setup>
const props = defineProps<{ prop1: number }>();
</script>
<template>
{{props.prop1}}
</template>
This works fine, but as our custome element get bigger we would like to register components and use e.g pinia and other tools. Do use those we need to add createApp and mount it. But then prop1 is always undefined
// main.ts
import ...<lots of imports>
import AppCe from "./AppWebComponent.ce.vue";
import { createPinia } from "pinia";
// Adding code below is causing prop1 to be undefined - if we skip this part, prop1 works fine
const pinia = createPinia();
const app = createApp(App);
app.use(pinia).use(ConfirmDialog);
app.component(...<lots of components>);
app.mount("#my-root");
const ceApp = defineCustomElement(AppCe);
customElements.define("my-element", ceApp);
update:
Here's a sample without: https://stackblitz.com/edit/vue3-script-setup-with-vite-56rizn?file=src/my-element/my-element-main.js
And here's a sample with the createApp: https://stackblitz.com/edit/vue3-script-setup-with-vite-gtkbaq?file=index.html
Any idea on how we could solve this?
We have a fallback, that is to do a getElementById and read the attribute value in the mounted callback - but that is not an optimal solution.
Thanks for any ideas!
update2:
Here's an attempt using #duannex suggestion. We're getting closer, the app is availible, components registered, but still no sigar. : https://stackblitz.com/edit/vue3-script-setup-with-vite-ofwcjt?file=src/my-element/defineCustomElementWrapped.js
Based on update2 with the wrapped defineCustomElement; Just pass the props to the render function:
render() {
return h(component, this.$props)
},
https://stackblitz.com/edit/vue3-script-setup-with-vite-vfdnvg?file=src/my-element/defineCustomElementWrapped.js

Why is Vercel failing to build my Next.js tsx app?

When I run npm run build and npm start on my local machine it deploys perfectly to localhost but when I try to deploy the very same code to Vercel I get the following error:
08:28:16 Failed to compile.
08:28:16 ./pages/index.tsx:5:20
08:28:16 Type error: Cannot find module '../components/layout' or its corresponding type declarations.
It definitely seems like an issue with the Layout component, I switched around the order of the important and it always fails when trying to load the Layout component. Here's the code for the component:
import Alert from "./alert";
import Footer from "./footer";
import Meta from "./meta";
type Props = {
preview?: boolean;
children: React.ReactNode;
};
const Layout = ({ preview, children }: Props) => {
return (
<>
<Meta />
<div className="min-h-screen">
<Alert preview={preview} />
<main>{children}</main>
</div>
<Footer />
</>
);
};
export default Layout;
index.tsx line 5 looks like this import Layout from "../components/layout"; and I've confirmed that that is the correct path for the Layout component.
are you sure the file name is layout.tsx not Layout.tsx :-)
I went through the same thing.
Fix layout.tsx to Layout.tsx
The file name and component name must be the same.

Next.js Global CSS cannot be imported from files other than your Custom <App>

My React App was working fine, using global CSS also.
I ran npm i next-images, added an image, edited the next.config.js, ran npm run dev, and now I'm getting this message
Global CSS cannot be imported from files other than your Custom <App>. Please move all global CSS imports to pages/_app.js.
Read more: https://err.sh/next.js/css-global
I've checked the docs, but I find the instructions a little confusing as I am new to React.
Also, why would this error happen now? Do you think it has anything to do with the npm install?
I've tried to remove new files I've added along with their code, but this doesn't fix the problem. I've also tried what the Read more: suggests.
My highest tier component.
import Navbar from './Navbar';
import Head from 'next/head';
import '../global-styles/main.scss';
const Layout = (props) => (
<div>
<Head>
<title>Bitcoin Watcher</title>
</Head>
<Navbar />
<div className="marginsContainer">
{props.children}
</div>
</div>
);
export default Layout;
My next.config.js
// next.config.js
const withSass = require('#zeit/next-sass')
module.exports = withSass({
cssModules: true
})
My main.scss file
#import './fonts.scss';
#import './variables.scss';
#import './global.scss';
my global.scss
body {
margin: 0;
}
:global {
.marginsContainer {
width: 90%;
margin: auto;
}
}
The thing I find the weirdest is that this error came without changing anything to do with CSS, or Layout.js, and it was previously working?
I've moved my main.scss import to the pages/_app.js page, but the styles still aren't coming through. This is what the _app.js page looks like
import '../global-styles/main.scss'
export default function MyApp({ Component, props }) {
return <Component {...props} />
}
Use the built-in Next.js CSS loader (see here)
instead of legacy #zeit/next-sass.
Replace #zeit/next-sass package with sass.
Remove next.config.js. Or do not change CSS loading in it.
Move the global CSS as suggested in the error message.
Since Next.js 9.2 global CSS must be imported in Custom <App> component.
// pages/_app.js
import '../global-styles/main.scss'
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
To add styles only to a specific component or page you can use built-in support of CSS modules. (see here)
For example, if you have a component Button.js you can create a Sass file button.module.scss and include it in the component.
Next.js stops complaining when your file has module in naming, e.g., changing import '../global-styles/main.scss'; to import '../global-styles/main.module.scss'; would fix the warning and you could have your styles in the global-styles, or for example, in your component.
No extra dependencies/configurations in next.config.js is required.
You can replace the opinionated (and overly-complex?) NextJs CSS loaders with your own. Here's a simple one for global css:
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
reactStrictMode: true,
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
// Find and remove NextJS css rules.
const cssRulesIdx = config.module.rules.findIndex(r => r.oneOf)
if (cssRulesIdx === -1) {
throw new Error('Could not find NextJS CSS rule to overwrite.')
}
config.module.rules.splice(cssRulesIdx, 1)
// Add a simpler rule for global css anywhere.
config.plugins.push(
new MiniCssExtractPlugin({
experimentalUseImportModule: true,
filename: 'static/css/[contenthash].css',
chunkFilename: 'static/css/[contenthash].css',
})
)
config.module.rules.push({
test: /\.css$/i,
use: !isServer ? ['style-loader', 'css-loader'] : [MiniCssExtractPlugin.loader, 'css-loader'],
})
return config
},
}
Add this to your _app.js
import '../styles/globals.css'
For me the problem was because I had used two module.exports in my next.config.js file like this
const withPlugins = require('next-compose-plugins')
const sass = require('#zeit/next-sass')
const css = require('#zeit/next-css')
const nextConfig = {
webpack: function(config){
config.module.rules.push({
test: /\.(eot|woff|woff2|ttf|svg|png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
limit: 100000,
name: '[name].[ext]'
}}
})
return config
}
}
module.exports = withPlugins([
[css],
[sass, {
cssModules: true
}]
], nextConfig)
module.exports = {
env: {
MONGO_URI = 'your uri'
}
}
. 1I modified it to change the export module like this.
const nextConfig = {
webpack: function(config){
config.module.rules.push({
test: /\.(eot|woff|woff2|ttf|svg|png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
limit: 100000,
name: '[name].[ext]'
}}
})
return config
},
env: {
MONGO_URI: "your uri"
}
}
2then I deleted the second module.exports
This node package provides a perfect solution for it. You can find it here
Steps to fix it:
1. Add package:
npm install next-remove-imports
or
yarn add next-remove-imports
2. Add this wrapper variable inside your next.config.js
const removeImports = require('next-remove-imports')({
test: /node_modules([\s\S]*?)\.(tsx|ts|js|mjs|jsx)$/,
matchImports: "\\.(less|css|scss|sass|styl)$"
});
All it is doing is re-enabling global styling import rule for tsx|ts|js|mjs|jsx files
3. Wrap your next config export with this next-remove-imports wrapper. Something like this:
module.exports = removeImports((nextConfig)
4. Now restart your react app and you will be able to import CSS files inside any ts|js|js|jsx|mjs file or component.
Try to include ".module" in your scss file name.
Change main.scss to main.module.scss
Example:
import styles from './todolist-profile-info.module.scss'
You did not need to do anything inside of next.config.js.
Let's assume you are using a global css like Bootstrap, meaning it contains css that is meant to be applied to your entire application and all the different pages inside of it.
Global css files have to be wired up to NextJS in a very particular fashion.
So inside of the pages/ directory you need to create _app.js.
It's critical that the file be named _app.js.
Then at the top of that file you would import Bootstrap css in the following manner:
import 'bootstrap/dist/css/bootstrap.css';
Then you would add the following:
export default ({ Component, pageProps }) => {
return <Component {...pageProps} />;
};
So what is going on in that code?
Well, behind the scenes, whenever you try to navigate to some distinct page with NextJS, NextJS will import your component from one of the different files inside your pages/ directory.
NextJS does not just take your component and show it on the screen.
Instead it wraps it up inside of its own custom default component and that is referred to inside of NextJS as the App.
What you are doing by defining the _app.js is to define your own custom app component.
So whenever you try to visit a route inside a browser or your root route, NextJS is going to import that given component and pass it into the AppComponent as the Component prop.
So Component there is equal to whatever components you have in the pages/ directory. And then pageProps is going to be the set of components that you are intending to pass to your files inside of pages/.
So long story short, this thing is like thin wrapper around the component that you are trying to show on the screen.
Why do you have to define this at all?
Well, if you ever want to include some global css to the project, Bootstrap being a global css for example, you can only import global css into the _app.js file.
It turns out that if you try to visit other components or other pages, NextJS does not load up or even parse those files.
So any css you may have imported inside there will not be included in the final HTML file.
So you have a global css that must be included on every single page, it has to be imported into the app file because it's the only file that is guaranteed to be loaded up every single time a user goes to your application.
Don't forget that in addition to importing the css inside of _app.js, you also have to run an npm install bootstrap in your terminal.
You can read more on this here:
https://nextjs.org/docs/messages/css-global
For me, i got this error because I had used improper naming for my project's parent folder, had used special characters in it,
like project#1,
after removing special chars, and changing the folder name to like project-1, the error got away.
In my case there was typo in navbar.module.css
I've written navbar.moduile.css
you must for every component css/scss write navbar.module.css/scss/sass.Next js doesnt compile navbar.css/scss/sass. If hope my answer helps you !.

problem with react-quill library with next.js project

I'm running into a weird problem. I'm using NextJS for its server-side rendering capabilities and I am using ReactQuill as my rich-text editor. To get around ReactQuill's tie to the DOM, I'm dynamically importing it. However, that presents another problem which is that when I try to access the component where I'm importing ReactQuill via a anchor link is not working but I can access it via manually hit the route. Here is my directories overview,
components/
crud/
BlogCreate.js
pages/
admin/
crud/
blog.js
index.js
blogs/
index.js
In my pages/admin/index.js
...
<li className="list-group-item">
<Link href="/admin/crud/blog">
<a>Create Blog</a>
</Link>
</li>
...
In my pages/admin/crud/blog.js
import BlogCreate from "../../../components/crud/BlogCreate";
...
<div className="col-md-12">
<BlogCreate />
</div>
In my components/crud/BlogCreate.js
import dynamic from "next/dynamic";
const ReactQuill = dynamic(() => import("react-quill"), { ssr: false });
import "../../node_modules/react-quill/dist/quill.snow.css";
...
<div className="form-group">
<ReactQuill
value={body}
placeholder="Write something amazing..."
onChange={handleBody}
/>
</div>
in order to use import "../../node_modules/react-quill/dist/quill.snow.css" in components/crud/BlogCreate.js I use #zeit/next-css and here is my next.config.js
const withCSS = require("#zeit/next-css");
module.exports = withCSS({
publicRuntimeConfig: {
...
}
});
Problem
when I click the Create Blog it should be redirect me http://localhost:3000/admin/crud/blog but it just freeze.
But if I manually hit http://localhost:3000/admin/crud/blog then it go to the desire page and work perfect.
And as soon as I manually load that page then Create Blog works. Now I really don't understand where is the problem? Because it show no error that's why I haven't no term to describe my problem that's why I give all the nasty code and directories which I suspect the reason of this error.
It's hard to give you any solution without seeing the entire project(As you mentioned that it shows no error).
You may remove the #zeit/next-css plugin because Next.js 9.3 is Built-in Sass Support for Global Stylesheets. You can use it for css also.
Create a pages/_app.js file if not already present. Then, import the quill.snow.css file:
import "../../node_modules/react-quill/dist/quill.snow.css";
// This default export is required in a new `pages/_app.js` file.
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />;
}
If it gives any error then you can create a directory/file to copy-paste the quill.snow.css code in that file.
pages/
_app.js
styles/
quill_style.css
Then import the file in _app.js like,
import "../styles/styles_quill.css";
// This default export is required in a new `pages/_app.js` file.
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />;
}
Eventually you can import your custom gobal css here also.
If although the problem remains then provide your git repository. happy coding ✌️
First: remove your #zeit/next-css setup not needed anymore since next.js version 10.
Second: update nex.js to version 10 you could then use regular import on your modules.
import "../../node_modules/react-quill/dist/quill.snow.css";
By the way, I had the same issue with your Nextjs course. ;)

Resources