Imported modules without server side rendering feature - next.js

I have an issue with Next.js. When I'm trying to import a node module,
the module uses the window object and Next.js is throwing an error: window is not defined.
The module is imported like this:
import * as widgets from 'survey-widgets';
widgets.autocomplete(Survey);
I guess Next.js dynamic imports will not work in my case. Is there any way of doing it?

Try deferring all the code that uses window or any other api that is restricted to the browser, in useEffect, because the code in useEffect only runs in the browser.
If you can't do that, then make an intermediary module which you will use to import survey-widgets and re-export what you need. So in the end, you import that intermediary module dynamically.
import * as widgets from 'survey-widgets
export default widgets

For anyone looking for the solution for this, I solved it with NextJs Dynamic imports with no SSR.
What I did instead is importing my top level component using dynamic import like this:
const MyComponent= dynamic(
() => import('../components/hello3'),
{ ssr: false }
)
So the hello3 component will no longer be used in server side rendering and instead it will render on client side.
Then just use it like this:
<MyComponent/>

Related

How do I use CSS Houdini in Next.js

I would like to use CSS Houdini in a Next.js project I am building. I have installed, via yarn, both the CSS Houdini package I want to use along with css-paint-polyfill. I am following the webpack instructions here https://houdini.how/usage
Here is my component:
import 'css-paint-polyfill';
import workletURL from 'url-loader!css-houdini-lines';
import styles from './Separator.module.css';
CSS.paintWorklet.addModule(workletURL);
export default function Separator() {
return <div className={styles.separator} />;
}
I am getting the dreaded
error - ReferenceError: window is not defined
at /home/tithos/code/web/new-tim/node_modules/css-paint-polyfill/dist/css-paint-polyfill.js:1:239
I tried putting the import for css-paint-polyfill in a useEffect, but the throw another error. I even tried const DynamicComponent = dynamic(() => import('../components/hello')) from https://nextjs.org/docs/advanced-features/dynamic-import, but I did not know how to reference the library.
Has any one solved this?
Seems like CSS Paint Polyfill eagerly accesses window, which means it will throw an error when in an environment which has no window, such as server phase of Next. There are multiple things you can do.
Modify your next.config.js to stub the aforementioned module when for Webpack when isServer is true. You can follow this page of the Next docs for this.
Create a dynamic component that's only imported on the client (I see you've tried this, but it should have worked, so maybe if you shared what you did in this regard, I could work out what's wrong with your approach).
Create an issue and send in a PR to the repository where the Polyfill is hosted to lazily access window depending on whether it's available or not.

Passing data to createApp (vue)

Using Webpack, I have this code:
import { createApp } from 'vue'
import Vue from 'vue'
import App from './components/ItemSearch/ItemSearch.vue'
createApp(App).mount('#search-app')
On my website, I have a page for the search app that contains the <div id="search-app" /> to mount the root of the application to.
What I would like to know is, whether it's possible to somehow insert (preferably) some of the data from the page that includes the javascript file? There are a few things items I would like to include from the database, such as settings and search categories, and I'd like to avoid making an AJAX request for them if it can be helped.
Can it be helped or is there some way I can include this data inline at load time?
With Webpack, I don't quite understand how I can get access to App from the page that loads the javascript file, so that I can modify data before somehow passing it in to createApp(), or if it's even possible. Can I use import statements on a page that's loaded by the browser, or is this stictly a Webpack only (or similar) feature?
Many thanks in advance.
You can use createApp's second parameter to pass props.
import { createApp } from 'vue'
import Vue from 'vue'
import App from './components/ItemSearch/ItemSearch.vue'
createApp(App, {myProp: "value"}).mount('#search-app')
docs

Is there a way to import Components into index.tsx from the same directory of index.tsx

Is it possible to import React components from inside the page's directory ?
I can successfully import from outside /pages/[...]/.
/components/[...]/ works just fine for instance. And that is cool for re-usable components.
But if I want to split a single page's components into separate files as follows :
/components
- SomeReusableComponent.tsx
/pages/[...]/
- index.tsx
- SomePageComponent.tsx
And import it into my main component :
// /pages/[...]/index.tsx
import SomeReusableComp from '../components/SomeReusableComponent'
import SomePageComp from './SomePageComponent'
export default function MyPage(){
// page code
}
My build fails : Build optimization failed: found pages without a React Component as default export in
pages/
Is there a trick to do that ? Some setting or else to tell nextjs that this file is a dependency and not a page ?
No, unfortunately that is not possible. All files within the pages directory for a Next.js project must be entry points (that subsequently get turned into routes) and cannot be imported from any other files in your project. Next "collects" all of these files in pages and processes them in a special way, so there is no way to avoid that currently.
Typically for reusable parts that I want to use in multiple pages, I create a component that accepts children as a prop.
For example:
components/layout.js
export default function Layout({children}) {
return (
<div className="some-styling-for-pages">
{children}
</div>
)
}
pages/index.js
import Layout from '../components/layout'
export default function IndexPage() {
return <Layout>my page content</Layout>
}

Using global custom style sheet in Next Js

According to the documentation found here
To import a css file I can do the following in 'pages/_app.js':
import '../styles.css'
// This default export is required in a new `pages/_app.js` file.
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
Easy enough.
From my understanding this over rides the App component with the global css.
The documentation says:
Next.js uses the App component to initialize pages. You can override it and control the page initialization. Which allows you to do amazing things like:
However when I first initialize an app with Next Js I get a root page of pages/index.js
This contains my start up page. There is no app.js file or App component anywhere here.
I'm confused as to how the App component is integrated into the regular index.js file.
My question is:
Is the pages/_app.js automatically some how wrapped around pages/index.js?
Or do I have to import the myApp component into the pages/index.js file?
My question is: Is the pages/_app.js automatically some how wrapped around pages/index.js? Or do I have to import the myApp component into the pages/index.js file?
Yes, next.js automatically wraps your application with the component defined in _app.js. If you don't have that file, next.js uses its default.
You need to follow a specific pattern when defining your App component in _app.js. You can check here to see how you should set a custom App component: https://nextjs.org/docs/advanced-features/custom-app

Best way to import modules with 'dynamic' and no SSR plus OnsenUI

people.
https://nextjs.org/docs#dynamic-import
It's nice and easy. But: what's the best way to import more than 1 module from the same library?
Specifically, I would like to work with Onsen UI (to build a PWA) with Next.js. Onsen just render with 'window' object, that doesn't exists on server-side. So, I'm thinking to import dynamically these components and render on client-side.
I have to import several modules from 'react-onsenui', like Page, Button, etc, etc.
const Page = dynamic(
() => import('react-onsenui').then(
mod => mod.Page
),
{
ssr: false,
}
);
I have the Page module available on this way. But I would like to import all I need one time. Is it possible?

Resources