I am working on a static website that uses NextJS. And, I want to embed Github Gist into this website. I tried several npm packages which were created for React. But, those packages seem to use browser features that are not available when my NextJS website generates on the server side. As an example, I used the ReactEmbedGist package. And, it gives these errors: "regeneratorRuntime is not defined" and "ReferenceError: self is not defined". So, What is the most efficient way to embed a Github Gist in a NextJS static application?
This could be achieved using Dynamic imports in NextJS. I used the same npm package (react-embed-gist) which I mentioned in the question.
Step 1
Import the react-embed-gist using NextJs dynamic imports. The "ssr" option should be set to false to disable the server-rendering. More details: https://nextjs.org/docs/advanced-features/dynamic-import
const ReactEmbedGist = dynamic(() => import("react-embed-gist"), {
ssr: false,
});
Step 2
Using the "react-embed-gist" package. More details: https://github.com/msaracevic/react-embed-gist#readme
<ReactEmbedGist gist="DevLaka/2e99090627052bd300b21aa09089366e" />
Update
After a while, "react-embed-gist" package didn't work for me. After about two hours of trying to troubleshoot it, I switched to another package called "react-gist" which works fine for my requirements. More details: https://www.npmjs.com/package/react-gist. The process was the same as the earlier one. Only the import statement should be changed.
Extention of the solution
Step 1
Even though the above solution works fine, according to docs, the way I used the dynamic import is used to import components that we wrote, not 3rd party libraries ( https://nextjs.org/docs/advanced-features/dynamic-import ). So, I have created a new component that can be reused as well.
import Gist from "react-gist";
export default function CodeBlock() {
return (
<div>
<Gist id="c88ac8ea9a43e3379acdc7a1fec3538a" />
</div>
);
}
Step 2
Importing my CodeBlock component using NextJS dynamic import and using it.
import dynamic from "next/dynamic";
const CodeBlock = dynamic(() => import("../components/CodeBlock"), {
ssr: false,
loading: () => <p>Loading</p>
});
export default function Home() {
return (
<div>
<CodeBlock id="c88ac8ea9a43e3379acdc7a1fec3538a" />
</div>
);
}
Related
Would really appreciate some help with this, have been trying to figure it out for a while.
I'm getting the below error. After some research, I figured out that you need to use "next/dynamic" with { ssr: false } to load modules dependent on window (since it's only avail in browser and not on server).
I added the below import to my app, but still getting the same error. Is there something wrong with the below and/or is there other configuration needed to make the dynamic loads function properly?
const Chart = dynamic(() => import("react-apexcharts"), { ssr: false });
Server Error
ReferenceError: window is not defined
This error happened while generating the page. Any console logs will be displayed in the terminal window.
Call Stack
Object.<anonymous>
...
UPDATE
So, it looks like I had to dynamic import the component where I was trying to use the component made with this import ... which seems redundant / i feel like I'm still doing something wrong.
So, now it's working, but I'm -
using const Chart = dynamic(() => import("react-apexcharts"), { ssr: false }); to build a component in ../barChart2.js
i'm again dynamic importing the component in barChart2.js when trying to use it (e.g., with const BarChart2 = dynamic(() => import('page-sections/charts/barChart2'), { ssr: false });
Is this actually how you are supposed to do it? Or is there a better way?
Didn't want to submit this as an answer, as I don't believe this is really the "correct" way even though it technically works.
Barrel/index files seem to create issues when used with next.js. It doesn't seem established if it's purely a webpack issue or both webpack and next.js
According to this issue tree shaking stops working if we use barrel files. I also created a small repo where I have an issue with an index file. Not sure if it's a tree shaking issue.
Steps to reproduce the issue:
npm install
npm run dev
in browser, visit http://localhost:3000/about-pro, expect to see blank page with errors or warnings in browser's console
go to server's console(where you run npm run dev)
see an error of sort "Module not found: Can't resolve 'fs'" (1) (2) (3)
1- this comes from the await serialize in getAboutPageData file. Which itself is only called within getStaticProps
2 - googling for this issue, you'll find solutions such as modifying next.config.js file. It still doesn't work. Feel free to uncomment the next.config.js file and see for yourself
3 - to "solve" the issue, go to about-pro.tsx, in the imports, import AboutPage from its own file instead of from the barrel/index file
If I only import getAboutPageData from the barrel/index file, then it works fine. But as soon as I import e.g. AboutPage from it, it starts throwing unrelated issues.
Can I continue using barrel/index files with next.js and if yes, is there a simple and intuitive way to do that?
The issue is not in the barrel files themselves but in the library that you're using combined with barrel files.
If you take a look at the readme file https://github.com/hashicorp/next-mdx-remote#examples you can find a warning:
IMPORTANT: Be very careful about putting any mdx-remote code into a separate "utilities" file. Doing so will likely cause issues with nextjs' code splitting abilities - it must be able to cleanly determine what is used only on the server side and what should be left in the client bundle. If you put mdx-remote code into an external utilities file and something is broken, remove it and start from the simple example above before filing an issue.
So in order to make your code work you need to remove the export of getAboutPageData from your barrel file, like this:
export { default as AboutPage } from './AboutPage';
// export { default as getAboutPageData } from './getAboutPageData';
and move the code that uses the library inside the about-pro.tsx file.
import { AboutPage } from '../modules/about';
import { serialize } from 'next-mdx-remote/serialize';
const AboutPro = (props) => {
return <AboutPage {...props} />;
};
export const getStaticProps = async () => {
const serializedContent = await serialize(`# Header1`);
const data = serializedContent;
return { props: {} };
};
export default AboutPro;
I think the issue is that the modules imported in barrel files are executed both client and server side. Probably removing side effects from the barrel file could solve the issue, but I don't know enough about Next.js to be able to do it correctly.
I am having big problems with Storybook at the moment with respect to modules loading correctly.
I can't really provide a self contained example, because the problems seem so erractic and hard to predict.
Basically storybook is being run and it is trying to import files, however something is going wrong in this step. I am guessing there is some error in one of the dependencies down the line, or that there is a circular dependency somewhere.
I am getting this error in all kinds of places :
ReferenceError: Cannot access 'SOMETHING' before initialization
Basically my storybook file looks something like this :
storiesOf('storybook test', module)
.addDecorator(withKnobs)
.add('a story ', () => {
return (
<div>
<Provider store={store}>
<HashRouter pathname={"asdf"}>
<CSVImportFlow
step={"edit"}
entitySchemas={{}}
/>
</HashRouter>
</Provider>
</div>
)
})
And these Reference Errors appear based on something being imported.
In my case, I was using propTypes instead of PropTypes, small p was an issue.
I am using Laravel 5.6.12 and vue.js
I am implementtrying to implement Google Maps with the help of this github link
I following the guidelines mentioned in above link as below.
Installation
npm install vue2-google-maps
Then wrote below code in app.js
import * as VueGoogleMaps from 'vue2-google-maps'
Vue.component('vue2-google-maps', VueGoogleMaps);
Finally below code in the template
<GmapMap
:center="{lat:10, lng:10}"
:zoom="7"
map-type-id="terrain"
style="width: 500px; height: 300px"
></GmapMap>
I got the below error.
- did you register the component correctly? For recursive
components, make sure to provide the "name" option.
I have already added below script in the html head.
<script src="https://maps.googleapis.com/maps/api/js?key=apikey&libraries=places"></script>
Am I missing anything in above code?
Short answer: You haven't used plugin correctly.
Long answer: By default vue2-google-maps didn't expose components directly but instead it exposes plugin that registers all google maps components (e.g. <GmapMap/>). You should read Quickstart before using the library.
> Basic approach - Register plugin
You should use plugin which will register all the desired components.
Correct usage:
import Vue from 'vue'
import * as VueGoogleMaps from 'vue2-google-maps'
Vue.use(VueGoogleMaps, {
load: {
key: 'YOUR_API_TOKEN',
libraries: 'places',
})
Your usage:
import * as VueGoogleMaps from 'vue2-google-maps'
Vue.component('vue2-google-maps', VueGoogleMaps);
BTW: when using this approach you can remove <script src="https://maps.googleapis.com/..."></script> from you head with no issue:
> Alternative approach - Import only required components. The idea here is to import components directly. I'm not sure how it works with google maps api but in any case you can try
Correct usage:
import GmapMap from 'vue2-google-maps/dist/components/map.vue'
Vue.component('GmapMap', GmapMap)
Your usage:
import * as VueGoogleMaps from 'vue2-google-maps'
Vue.component('vue2-google-maps', VueGoogleMaps);
I was trying to port the euroscipy2014 tutorial (which is also the base for the ipython cookbook) to the newer ipywidget API. I succesfully converted 3 of the 4 notebooks following the directions I found on the relative ipython documentation but i'm having troubles in porting the 3rd notebook (03_custom.ipynb).
I changed the js code from:
%%javascript
// We import the WidgetManager.
require(["widgets/js/widget"], function(WidgetManager){
// We define the NumberSelector view here.
var NumberSelector = widget.DOMWidgetView.extend({
// Function for rendering the view.
render: function(){
to:
%%javascript
// We import the WidgetManager.
require(["widget"], function(WidgetManager){
// We define the NumberSelector view here.
var NumberSelector = widget.DOMWidgetView.extend({
// Function for rendering the view.
render: function(){
using require(["widget”] … instead of require(["widgets/js/widget … and widget.DOMWidgetView.extend instead of IPython.DOMWidgetView.extend
but when testing the widget at the code cell 4 I have (log from the js console):
Couldn't create a view for model id '8727d6f51f804c7aa582b3d95b3c630d' -- Error: Class NumberSelector not found in registry (…)
I guess the last line in the js code:
WidgetManager.register_widget_view('NumberSelector', NumberSelector);
didn’t worked. (maybe .register_widget_view is no more a valid call).
Have you any idea on how to fix this? thanks!
I opened an issue here but i thought the proting of such API can be a topic of general interest, so i'm posting a question here as well.
https://github.com/rossant/euroscipy2014/issues/2