Webpack with Next.js bundles file it is not supposed to in client bundle - node.js

I have a Next.js app with mongoose to connect to my mongodb. The models import db.ts to make sure that there is an active connection to the database like so:
import { model, models, Schema } from "mongoose";
import "../../db";
This is the code that connects to my database:
import mongoose from "mongoose";
mongoose.connect("mongodb://admin:admin#localhost:27022/admin");
I have gone ahead and made some serverless functions in next.js and added some database fetching from the models in my getServerSideProps. All of which worked perfectly fine. I can interact with the models, create new Documents, delete them and update them. there are no issues.
The Problem
I recently added a new component: it is at /pages/flashcards/[id].tsx. Just like my other components, this one imports one of my mongoose models. However, for some reason, Webpack feels like it should bundle the model and its import of ../../db and send it and send it over to the client, which results in this error:
TypeError: mongoose__WEBPACK_IMPORTED_MODULE_0___default(...).connect
is not a function
Again: This does not happen with any of my other components which use the exact same models as the component which is having these problems.

The issue occurs because you have the following unused import in the /pages/flashcards/[id] page.
import question from "../../db/models/question";
Any code inside getServerSideProps or getStaticProps, and imports used exclusively by these methods, is removed by Next.js when building the client bundle.
However, since question is not explicitly being used in getServerSideProps, Next.js can't figure out the import is only meant to be used on the server. This means it will be included in both the server and client bundles.
You can use the Next.js Code Elimination tool to verify what Next.js eliminates from the client-side bundle. You'll see that if you run your page's code through it, the import is not removed. However, as soon as you reference and use it inside getServerSideProps, Next.js automatically eliminates it from the imports.
Make sure to always comment out/remove unused imports (there are linting rules to help you do that).

Have you tried upgrading the next npm package to the latest version? (12.0.8 as of this writing). I had a similar issue with Next giving inconsistent errors between different API routes, all configured the same way but some raising the same TypeError you shared. Upgrading the package resolved the issue for me.

Related

Nuxt3 - how to use vite-plugin-wasm

I'm building a Nuxt3 application where I need to import and use a 3rd party node package which internally is using webassembly.
In my case, the package I need is https://github.com/higumachan/lindera-js
Where do I import the package?
In one of my components, right at the beginning of the <script> tag.
And afterwards I'm using it in one of the methods.
(Note: I removed unnecessary code below)
<template>
...
</template>
<script>
import * as lindera from "lindera-js";
...
methods: {
doTranspile() {
const tokenized= lindera.tokenize(this.input);
console.log(tokenized);
},
},
...
</script>
What is the Problem?
After dev server compiles everything and I reload the page in the browser, I get the following error:
[vite] Internal server error: "ESM integration proposal for Wasm" is not supported currently.
Use vite-plugin-wasm or other community plugins to handle this.
Alternatively, you can use .wasm?init or .wasm?url.
See https://vitejs.dev/guide/features.html#webassembly for more details.
The Question
How can I use the package without problems in Nuxt3? Do I have to use vite-plugin-wasm and if so, how and where to use/import it?
Or is there any other way to use a package which is using webassembly?
I found some similar questions on SO, but not sure if they can be used like this in Nuxt3 as I'm fairly new to Nuxt in general.
How to use embedded Webassembly in Vite?
How to include an WASM npm module in svelte with vite?

Jest, NestJS, TypeORM End To End Testing

In the NestJS tutorial E2E tests are set up with their single example module imported.
This pattern does not seem to work in an application with more complex relations between the typeORM entities. After extensively checking that there were no inconsistencies in import statements and no missing TypeOrmModule.forFeature() in the relevant files, I gave up and simply imported my entire AppModule (root module for my application -- same as NestJS default).
In short if you are seeing of the form
Error: Entity metadata for EntityA#entityB was not found.
Check if you specified a correct entity object and if it's connected in the connection options.
You can try importing all the related modules or simply import your entire application.

React Native - Clear Async Storage Script

I'm currently building a react native app which uses async storage. I've got conditionals within the components to decide whether to make requests to the API or use the data stored in memory. So to test out these conditionals I regularly have to clear the AsyncStorage using AsyncStorage.clear().
This works if I have it in one of the components, however it would be more practical to have it in a seperate script - which brings me to my question:
I want to have a script as below:
import AsyncStorage from '#react-native-community/async-storage';
AsyncStorage.clear();
console.log('STORAGE CLEARED');
and then run it using a command like node clearStorage.js (and later an npm script).
However I'm getting an error saying 'Cannot use import statement outside a module'.
Am I missing anything glaringly obvious/trying to do something I shouldn't? I've tried changing the file type to .mjs with no luck.
If you need to do this, you can't use a nodejs script because the node script will never get to the native side, because async-storage is a native library and it connects directly to Android or IOS.
Another solution may be at the start of the application, you can run that code, or create a Button just for dev mode and when click clean the data.
and the error 'Cannot use import statement outside a module'. it's because nodeJs don't understand the syntax import AsyncStorage from '#react-native-community/async-storage'; they need a transpiler like babel.

TypeORM Share Entities Across Web and Node

I am using Webpack 4.7.0 to compile two entypoints - a server (node) and client (React), all in Typescript using ts-loader. I have a set of entity classes I would like them to share, however they are all written to be used by TypeORM (with #Entity decorators), thus requiring an import x from "typeorm".
This, of course, does not play nice when compiling the client bundle, as typeORM depends on many NodeJS libraries. I have tried adding externals: ["typeorm"] to my client entrypoint, but I then get a ReferenceError: "typeorm" not found in my browser.
Is there any way to share TypeORM entities across platforms?

Sharing TypeScript classes between client and server

I have a Node.js project written in TypeScript. In my project, I have a folder named "public" which contains the client side code & HTML and also a file named classes.ts which is supposed to be shared to the server side.
The problem is that I need to add "export" before the classes declaration in order to make them accessible in the server, but then in the browser I get this Error:
Uncaught ReferenceError: exports is not defined
I found these questions:
https://github.com/Microsoft/TypeScript/issues/5094,
Setup a Typescript project with classes shared between client and server apps?,
Share module between client and server with TypeScript,
which suggests using commonjs in the server but amd in the client. The problem with this solution is that they have 3 different projects (server, client and shared) whereas I only have one project in which I use commonjs.
Another suggestion is:
the other option, which is more convoluted and will require a post
build step to massage the code; if you can not use module loaders in
your client code, is to isolate all module dependencies in your server
code, then in the shared, they are just classes. Build the shared
files without --module, and no exports or imports, but all inside a
single namespace, say namespace MyApp { ... }; in your client code,
you include them directly, and emit using --out. in your server code,
you first emit the shared code to a single file, shared.js, and a
single .d.ts shared.d.ts, augment these with some code to export them
as a module, e.g. append exports = MyApp at the end of your shared.js
and shared.d.ts, then import them from your server code.
But I don't want to deal with updating .d.ts files all the time, and I'm also not sure it will work in one project.
Any suggestion how to make a TypeScript class accessible both in browser and server?
Any help will be profoundly appreciated!
This is absolutely possible.
I have a project containing both SPA client application that runs in browser and server running in node.js that both share common typescript classes. For all of this I have just one tsconfig.json file (I am still not sure that this is the best approach but for now it works just fine)
Here are parts of my setup:
Use modules (previously called external modules). No need for namespaces and d.ts files for your own modules.
module = "commonjs" in tsconfig.
On client side use System.js as module loader (this will solve your 'Uncaught ReferenceError: exports is not defined'). You can use angular2 5 min quickstart as reference how to setup system.js.
It works like a charm.

Resources