Client-side initialization in Next.js with Static HTML Export - next.js

We're developing a Next.js app using react-i18next for localization. We're using next export (Static HTML Export). The react-i18next library requires initialization code, and I'm not sure where to call that.
(We're not using next-i18next, as that does not work with next export.)
Right now I have the initialization in a separate module (outside of pages/). If I import that module into pages/_app.tsx and run the build script (next build && next export), the build hangs. When I hit Ctrl-C, I get:
Error: setRawMode EIO
The same thing happens if I try to import it from a custom Document.
My current workaround is to import the initialization module in pages/index.tsx - that works, but feels wrong.
The project uses TypeScript and yarn v1, and was scaffolded with create-next-app (in case any of that is relevant).

A Custom App import does appear to be the correct place for client-side initialization code (inferred based on Custom Polyfills).
The issue is that an _app module will execute when next build && next export is called. Asynchronous calls (i18next-http-backend in my case) can cause the build script to hang.
The fix is to wrap the initialization code in:
if (typeof window !== 'undefined') {
// initialization code - will only run on client side
}
Based on https://flaviocopes.com/nextjs-server-client-code/
This does mean that the initialization code won't run for Jest tests either, but react-i18next can be mocked.

Related

How to call function when nextjs application start

I am trying to add a guardian process for my NextJS application. it will start with the launch of my nextjs application, and then perform some jobs regularly(like backup data).
But I didn't find some "callback" or "eventListener" to let me call my startup function.
I tried to execute the startup function in pages/_app.tsx, but it was called every time when user accessed it, not only once when the nextjs application started.
The following is my expectation:
Call only once when the entire nextjs application is started.
No need to use a custom backend.(There are already a lot of code accumulated on the default server of Next)
Can use the ability provided by Next, such as TypeScript, Babel, export / import, etc.
The code in the nextjs application can directly Import related its function and use.
Can anyone provide some inspiration?

ReferenceError: AudioBuffer is not defined

I'm trying to use tone.js in a next.js react project.
When I run or build i get this error "ReferenceError: AudioBuffer is not defined"
I have isolated the tone.js code in codesandbox and it's working perfectly.
https://codesandbox.io/s/tonejs-react-pink-noise-generator-pfnl0?file=/src/App.js
But not in the next.js app
ReferenceError: AudioBuffer is not defined
at ki (/node_modules/tone/build/Tone.js:1:117922)```
AudioBuffer is a web browser thing, it does not exist in node.js. The error you are getting is because the code that uses AudioBuffer can't run on the server. You need to instantiate that part of the code only in the browser. That is usually done in useEffect hook, or on the server, you can first check if window object is defined.

Next.js - import server-side package in a file contains both server-side and client-side functionality?

Let's say I have a file named utils.js, containing two functions s and c.
s is a server-side function (Being called on an /api endpoint handler), and uses mongodb package.
c is a client-side function (will be bundled and sent to the browser).
When compiling the app using next build, will it cause any issues?
Does webpack know to bundle only part of a file/module? (considering server-side functions and imports as a "dead code" since they only being called from a server-side code)
Thanks
If you need to know which functions get bundled to the client & which ones to the server, there's an easy way to know this → https://next-code-elimination.now.sh/
Just copy & paste the contents of your file into it & you'll see which code gets bundled to the client & which code is bundled to the server. If you have imports then make sure to put all the imports in one file so you can see how it works.
The thumb rule is:
Anything like getServerSideProps, getStaticProps & getStaticPaths will be removed from the bundled code. If you import anything from a file that uses server-side code like fs but doesn't use it in any of the above 3 functions, then it won't be removed (check at Next Code Elimination Tool) & will give you an error.
The tool is the answer. I copy-pasted my file in it & found the answer in an instant.
I think there will be errors but not in the build time. It is likely issues will happen in the run time. You won't be able to access file systems on the client side just like how you can't access the window object on the server-side.
In my current project, we have utility functions for both the server-side, client-side, or universal. All server-side functions are called in getServerSideProps to make sure they work as expected. All your server-side code in getServerSideProps will not be imported as part of the client-side bundle if that's what you mean by "dead code". According to the Next.js
Note: You can import modules in top-level scope for use in
getServerSideProps. Imports used in getServerSideProps will not be
bundled for the client-side.
This means you can write server-side code directly in
getServerSideProps. This includes reading from the filesystem or a
database.
I'm not aware of a way you can ask webpack to bundle part of the file or execute a subset of import statements.
I hope that provides some help.
Reference:
Docs - getServerSideProps
Custom Webpack Config

Deno - Importing TypeScript into a JS file

In Deno, to import a TypeScript module, does your own code file have to be TypeScript? Or does Deno auto convert TypeScript to javascript before the module gets imported?
I want all my code files to be EcmaScript modules (js or mjs, but not ts).
Unlike everyone else these days, I want to avoid using TypeScript in my own code. I dislike the rigidity of static types and Typescript is not part of the EcmaScript standard. EcmaScript alone has all I need to manage big projects. To me, TypeScript is an antiquated technology that has not been necessary since the advent of ES6 modules. The types of problems TypeScript addresses are problems I do not have.
You can write your own code with JavaScript.
Suppose you have or are using a TypeScript file/module numbers.ts:
export function isEven(n: number): boolean {
if (n % 2 != 0) {
return false
}
return true;
}
You can import and run it with an app.js JavaScript script:
import { isEven } from "./module.ts";
const one = isEven(1)
const two = isEven(2)
console.log(one)
console.log(two)
Deno does the TypeScript convertion to JavaScript internally. The process is the same when using standard or 3rd party libraries. The folks at the Deno project went even further by adding it as a goal:
https://deno.land/manual/introduction
Browser compatible: The subset of Deno programs which are written
completely in JavaScript and do not use the global Deno namespace (or
feature test for it), ought to also be able to be run in a modern web
browser without change.
Name resolution must be fully qualified. There's a whole lot more about referencing type definitions in this dedicated page for using TypeScript:
https://deno.land/manual/getting_started/typescript
Deno supports both JavaScript and TypeScript as first class languages
at runtime. This means it requires fully qualified module names,
including the extension (or a server providing the correct media type)
Example:
import { config } from "https://deno.land/x/dotenv/mod.ts";
Following my example above you can use the bundle command to generate a single JavaScript file with all the dependencies. Bundling it will take my app.js and module.ts files and create a new file app.bundle.js which is JavaScript.
https://deno.land/manual/tools/bundler
$ deno bundle app.js app.bundle.js
Bundling file:///home/pomatti/projects/deno-sandbox/app.js
Emitting bundle to "app.bundle.js"
3111 bytes emmited.
$ deno run app.bundle.js
false
true
It can even be loaded in the browser:
Bundles can also be loaded in the web browser. The bundle is a
self-contained ES module, and so the attribute of type must be set to
"module". For example:
<script type="module" src="website.bundle.js"></script>
As for ECMAScript modules I would like to point out that TypeScript implements it as well.
https://github.com/microsoft/TypeScript/issues/2242
https://www.staging-typescript.org/docs/handbook/modules.html
Starting with ECMAScript 2015, JavaScript has a concept of modules.
TypeScript shares this concept.
Now, the "static type" discussion falls out of scope of this forum so I won't touch it here, but I believe I covered everything else.

HTML.Raw is undefined in Meteor+Blaze+React app after meteor/npm update

My app uses the latest Meteor 1.4.1.1 with React for UI and use Blaze only for accounts-ui. It ran fine until I 'meteor update' and 'npm update' yesterday. Now the app show blank page because of the exception (TypeError: HTML.Raw is not a function) in template.main.js (below) which Blaze compiled from the simple main.html that provide the root for React.
Template.body.addContent((function() {
var view = this;
return HTML.Raw('<div id="app-root"></div>');
}));
Meteor.startup(Template.body.renderToDocument);
When I looked at the HTML object in console:-
I'm new to Meteor and have no idea what's happening. I guess the Blaze's global HTML object must have the .raw method for use here. But why it is missing?

Resources