Node.js unable to import ES6 module - javascript

I'm trying to separate my routes to a separate module in routes.js and then importing in app.js. I'm getting a lot of errors in the console.
internal/modules/esm/default_resolve.js:96
let url = moduleWrapResolve(specifier, parentURL);
^
Error: Cannot find module /Users/rhoxh/Desktop/24/routes imported from /Users/rhoxh/Desktop/24/app.js
at Loader.resolve [as _resolve] (internal/modules/esm/default_resolve.js:96:13)
at Loader.resolve (internal/modules/esm/loader.js:73:33)
at Loader.getModuleJob (internal/modules/esm/loader.js:147:40)
at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:41:40)
at link (internal/modules/esm/module_job.js:40:36) {
code: 'ERR_MODULE_NOT_FOUND'
}
routes.js
import express from 'express';
const router = express.Router();
router.get('/', (req, res) => {
res.send('home page');
});
export default router;
app.js
import express from 'express';
import { router } from './routes';
const app = express();
const PORT = 8080;
app.listen(PORT, () => {
console.log(`Server running at: http://localhost:${PORT}/`);
});
// Routes
app.use('/', router);
What am I doing wrong here?

You need to use the full file name:
import router from './routes.js';
From the documentation:
module-name
The module to import from. This is often a relative or
absolute path name to the .js file containing the module. Certain
bundlers may permit or require the use of the extension; check your
environment. Only single quoted and double quoted Strings are allowed.

You can check this link it could help you https://github.com/nodejs/node/issues/27408
You can try to use --es-module-specifier-resolution=node as it says.

For anyone looking for a typescript solution use the .js file extension of your transpiled files.
// index.ts file.
import router from './routes.js';

You are destructuring your import yet you are exporting as default.
When you import a default there is no need for destructuring
import router from './routes';
You can use destructuring when you are using either a named export
export const router = express.Router()
or you pull out a property from the default export
export default {
router: express.Router()
}

Related

Cannot import module: ERR_MODULE_NOT_FOUND

I'm trying to import a route.js file in my index.js file. I am exporting in the routes file and importing it in the index with .js extension. What am I missing here?
Folder structure:
Routes folder is in the server folder, same as index.js - accessible by a single . VsCode also highlights the location when typing, so that's not the issue.
routes.js:
import { registerUser } from '../controllers/userController'
const router = express.Router()
router.post("/", registerUser)
export default router;
index.js:
import mongoose from "mongoose";
import cors from "cors";
import dotenv from "dotenv";
import userRoutes from './routes/userRoutes.js'
dotenv.config();
const app = express();
app.use(cors());
app.use('/users', userRoutes)
const PORT = process.env.PORT;
mongoose
.connect(process.env.CONNECTION_URL)
.then(() => console.log("DB Connected"))
.then(() =>
app.listen(PORT, () => console.log(`Server is running on ${PORT}`))
)
.catch((error) => console.log(error.message));
On the fourth import in the index.js file try removing the ".js" so it looks like this:
import userRoutes from './routes/userRoutes'
...if that file exists.
try changing from
import userRoutes from './routes/userRoutes.js';
to
import userRoutes from './routes/routes.js';
If that doesn't work, can you share output of tree command or ls command in your root directory.
As far as I am concerned. the .js extension would not be an issue in the import statement. So, if the naming part is okay. It's better to share error code with folder and naming structure in the question as well.

Why is the Router() Express function returning undefined?

I'm using TypeScript and Express to create an API that follows the principles of Clean Architecture. I separated each route of my application in a folder, and then I import all of them into an index.ts file, merging each one inside an unique router and exporting the same. My problem is that the importation of this unique file is returning undefined.
I think that is isn't a problem of my code itself, since TypeScript can infer correctly the type of the imported file and doesn't report any error during development. The only error I get just happens when trying to run the code:
TypeError: app.use() requires a middleware function
This is the code snippet that causes the error:
// expressInstance.ts --> Imported by the "server.ts" file, where listening the server happens
import express from "express";
import cors from "cors";
import { router } from ".."; // File with all the routes
const expressInstance = express();
expressInstance.use(express.urlencoded({extended: false}));
expressInstance.use(express.json());
expressInstance.use(cors());
expressInstance.use(router); // Line where the error appears
export {
expressInstance
};
And this is the code of the imported router file:
// index.ts
import { Router } from "express";
import { userRouter } from "./user.routes";
import { postRouter } from "./post.routes";
const router = Router();
router.use("/user", userRouter);
router.use("/post", postRouter);
export {
router
};
I read in another question that the undefined return used to happen at Express version 3, but I use the 4.17.13 version, so I think this isn't the cause of the problem. In fact, I have no idea what could be. I tried to see the router content by using console.log(router) in the index.ts file (before being imported by expressInstance.ts), but it didn't work, because the code wasn't even executed.
Try adding a path to your .use()
e.g:
expressInstance.use('/users', router); // in the case you wanted the router to be for users

Node.js express.Router ERR_MODULE_NOT_FOUND when import the new routes

I am experiencing a weird error. I was just creating a new folder to separate my routes.
Inside I created the routes using the express.Router API and I exported the router itself.
Here is how the code looks like inside post-routes.ts:
import express from 'express';
const router = express.Router();
router.get( '/', ( req, res ) =>
{
res.send( 'This is working' );
} );
export default router;
Ok. All I have to do now is to import it inside my index.ts and create a root route for my post-routes.ts file.
Please tell me if you see something wrong in my approach.
index.ts file:
import express from 'express';
import cors from 'cors';
import postRouter from './routes/post-routes';
const PORT = process.env.PORT || 5000;
app.use( '/posts', postRouter );
app.use( express.json( { limit: '30mb' } ) );
app.use( express.urlencoded( { limit: '30mb', extended: true } ) );
app.use( cors() );
app.listen( PORT, () => console.log( `listening at ${ PORT }` ) );
Good. Now to offer as much information as I possibly can, I will insert the following:
File structure inside my project:
package.json file configuration:
As you can see, I am using the "type": "module" to be able to use import inside my node application. As for the typescript, I am getting no compiling errors, so index.ts sees the post-routes.ts file so I would expect that index.js would see post-routes.js file as well. But the server throws the error below. How can this be?
Error [ERR_MODULE_NOT_FOUND]: Cannot find module 'E:\Github\hospytal-fasion\server\dist\routes\post-routes' imported from E:\Github\hospytal-fasion\server\dist\index.js
Apart from making sure that target and module are set to esnext in your tsconfig.json, make sure to include file extensions in your imports. i.e. try changing the following line:
import postRouter from './routes/post-routes';
to
import postRouter from './routes/post-routes.js';

Nodejs how can I add another main app.js and use both of them to make my code clean?

Hello I'm using nodejs and express framework and I wrote all my serverside code into my app.js file but it's little bit complicated for me cause cause I have almost 250 line code and I want to implement authentication now so I want to create another app.js to write my code only for auth so other code will not confuse me how can I do that????
UPDATED
as you se above I have 2 post requests from my app.js I asking that how I will get thoso request in my auth.js file cause as I understand exports import for static js field I want to take request and save that information my database and I want to that in my auth.js file
Here are a simplified structure for your project derived from my project at this link.
routes.js:
Create a file named route.js where you define all the routes for your application. In this case the routes will be only the register and the login routes that will be handled by the UserController module.
import { Router } from 'express';
import UserController from './UserController';
const router = Router();
router.post(
'/register',
UserController.register
);
router.post(
'/login',
UserController.login
);
export default router;
UserController.js:
This file/class that handle all the operations for the creation and login of an user
As you can see all the methods has no route url because they are called directly from our route.js file. We are dividing and structuring your application!
export default class UserController {
public static register(req, res) {
// Register operation
}
public static login(req, res) {
// Login operation
}
}
app.js
The entry point and where you are configuring your express application.
import express from 'express';
import routes from './routes';
const app = express();
// configure app ...
// Here we attach our routes url to the express app
app.use('/', routes)
Hope it helps :)
depending on your setup you can divide your files in per example:
app.js
authentication.js
and then either require or import functions from the authentication.js file into app.js like this:
import express from "express";
or this:
const express = require("express");
functions inside the authentication file should be exported like this:
//needs to be imported as this: import {authenticate} from "authenticate";
export function authenticate(){};
//needs to be imported as this: import authenticate from "authenticate";
function authenticate(){};
export default authenticate;
or this:
// needs to be imported as this: const authenticate = require("authenticate");
module.exports = function authenticate(){};
See this guide on enabling ES6 imports as shown above. this has the preference for it can save on memory when importing.

Express.js app entry point

It appears some route middleware is running before index.js, which is crashing my application because the order of execution prevents me from loading my dotenv file on time.
I would like to load my dotenv file before everything in order to make sure that all modules that require it will have access to it.
However, while debugging this issue, I noticed that a console.log at the top of the app entry point still doesn't log first.
Folder structure:
src
------index.js
middleware
------auth.js
routes
------auth.route.js
------index.js
.env
Code that logs first middleware/auth.js:
import { Strategy as JwtStrategy, ExtractJwt } from 'passport-jwt'
module.exports = function() {
console.log('this prints first with undefined', process.env.JWT_SECRET) <-------
which gets called in auth.route.js
import auth from '../middleware/auth'
const userRouter = express.Router()
userRouter.get('/dashboard', auth().authenticate(), function(req, res) {
res.send('Authenticated, user id is: ' + req.user.id)
})
index.js file:
console.log("this prints second"); <---------
(...)
import routes from './routes'
import express from 'express'
import auth from './middleware/auth'
require('dotenv').config({ silent: process.env.NODE_ENV === 'production' })
const app = express();
(...)
app.use('/api', routes);
It's not clear from the code fragments in your question where the problem, because I think you've omitted the place where you import the auth.route.js module.
The answer that follows assumes that you actually import auth.route.js in the index.js file, probably before importing middleware/auth (which isn't actually used in the code fragment you posted). So, based on that assumption, here's what's probably happening:
The thing to keep in mind is that code in a module is executed when it is imported. This doesn't affect middleware/auth at first, since all it does is declare a function. But it does affect auth.route.js - look at what that module does:
It imports the auth function from middleware/auth module, which calls the userRouter.get() function. One of the arguments to that function is a call to the auth() function.
If you're importing auth.route.js in your code (and I suspect you are), then that's where the auth function is getting called prematurely.
Now, how to fix this? It's actually pretty easy: the auth.route.js file should export a function which is called to initialize the routes when you're ready, like this:
auth.route.js
import auth from '../middleware/auth'
const userRouter = express.Router()
export default () => {
userRouter.get('/dashboard', auth().authenticate(), function(req, res) {
res.send('Authenticated, user id is: ' + req.user.id)
})
return userRouter;
}
And when you're ready to initialize the routes (ie. when everything else is set up).
import getRouter from './modules/auth.route.js';
app.use('/api', getRouter());

Categories

Resources