Difference between destructing export default and module.exports - javascript

I've been struggling to destruct my mongo object in another file, my object structure is like below.
const env = {
project: 'CRIBBBLE BACKEND',
url: 'localhost',
api: {
url: 'https://api.dribbble.com/v1/',
},
port: parseInt(process.env.PORT, 10) || 3000,
mongo: database,
};
export default env;
But when I'm trying to import the mongo object in another js file like this { mongo } from 'config' the returned value is undefined.
But if I change the export default value to module.exports it works as its expected.
So, I'm just wondering what is the difference between module.exports and export default?

While you export using export default foo the whole exported foo is available using {default: foo} after import. That's why you cannot access properties you want. Try to import as: import * as bar from './foo' and explore the bar using console.log(bar) to see what's happening underneath. Also for more info have a look: es6 module exports on 2ality.com

module.exports is a NodeJS (CommonJS) style of importing and exporting from different files. import/export is ES6 feature of doing the same thing.
If you export defualt you need to import it like import env from 'location'(Look I emit the {} part) and then access the mongo via env.mongo. You can't just get the mongo object directly.

Related

How to use .env variables in Nuxt 2 or 3?

I have .env file in the project root, and in my nuxt config I am using variables to configure ReCaptcha like this:
import dotenv from 'dotenv'
dotenv.config()
export default {
modules: [
['#nuxtjs/recaptcha', {
siteKey: process.env.RECAPTCHA_SITE_KEY,
version: 3,
size: 'compact'
}],
]
}
and in .env like this:
RECAPTCHA_SITE_KEY=6L....
but the application always failed with console log error:
ReCaptcha error: No key provided
When I hard-code ReCaptcha key directly like that: siteKey: 6L.... app start working, so I guess the problem is with reading .env props in nuxt.config
do you have any idea how to fix it?
EDIT:
I tried update my nuxt.config by #kissu recommendation and by example which I found here: https://www.npmjs.com/package/#nuxtjs/recaptcha
so there is new nuxt.config which also not working:
export default {
modules: [
'#nuxtjs/recaptcha',
],
publicRuntimeConfig: {
recaptcha: {
siteKey: process.env.RECAPTCHA_SITE_KEY,
version: 3,
size: 'compact'
}
}
}
If your Nuxt version is 2.13 or above, you don't need to use #nuxtjs/dotenv or anything alike because it is already backed into the framework.
To use some variables, you need to have an .env file at the root of your project. This one should be ignored by git. You can then input some keys there like
PUBLIC_VARIABLE="https://my-cool-website.com"
PRIVATE_TOKEN="1234qwer"
In your nuxt.config.js, you have to input those into 2 objects, depending of your use case, either publicRuntimeConfig or privateRuntimeConfig:
export default {
publicRuntimeConfig: {
myPublicVariable: process.env.PUBLIC_VARIABLE,
},
privateRuntimeConfig: {
myPrivateToken: process.env.PRIVATE_TOKEN
}
}
Differences: publicRuntimeConfig can basically be used anywhere, while privateRuntimeConfig can only be used during SSR (a key can only stay private if not shipped to the browser).
A popular use case for the privateRuntimeConfig is to use it for nuxtServerInit or during the build process (either yarn build or yarn generate) to populate the app with headless CMS' API calls.
More info can be found on this blog post: https://nuxtjs.org/blog/moving-from-nuxtjs-dotenv-to-runtime-config/
Then, you will be able to access it into any .vue file directly with
this.$config.myPublicVariable
You access it into Nuxt's /plugins too, with this syntax
export default ({ $axios, $config: { myPublicVariable } }) => {
$axios.defaults.baseURL = myPublicVariable
}
If you need this variable for a Nuxt module or in any key in your nuxt.config.js file, write it directly with
process.env.PRIVATE_TOKEN
Sometimes, the syntax may differ a bit, in this case refer to your Nuxt module documentation.
// for #nuxtjs/gtm
publicRuntimeConfig: {
gtm: {
id: process.env.GOOGLE_TAG_MANAGER_ID
}
},
PS: if you do use target: server (default value), you can yarn build and yarn start to deploy your app to production. Then, change any environment variables that you'd like and yarn start again. There will be no need for a rebuild. Hence the name RuntimeConfig!
Nuxt3 update
As mentioned here and in the docs, you can use the following for Nuxt3
nuxt.config.js
import { defineNuxtConfig } from 'nuxt3'
export default defineNuxtConfig({
runtimeConfig: {
public: {
secret: process.env.SECRET,
}
}
}
In any component
<script setup lang="ts">
const config = useRuntimeConfig()
config.secret
</script>
In a composable like /composables/test.js as shown in this comment
export default () => {
const config = useRuntimeConfig()
console.log(config.secret)
}
Here is the official doc for that part.
You can also use the env property with Nuxt
nuxt.config.js:
export default {
// Environment variables
env: {
myVariable: process.env.NUXT_ENV_MY_VAR
},
...
}
Then in your plugin:
const myVar = process.env.myVariable
It's very easy. Providing you an example with axios/nuxt
Define your variable in the .env file:
baseUrl=http://localhost:1337
Add the variable in the nuxt.config.js in an env-object (and use it in the axios config):
export default {env: {baseUrl: process.env.baseUrl},axios: {baseURL: process.env.baseUrl},}
Use the env variable in any file like so:
console.log(process.env.baseUrl)
Note that console.log(process.env) will output {} but console.log(process.env.baseUrl) will still output your value!
For nuxt3 rc11, in nuxt.conf.ts file:
export default defineNuxtConfig({
runtimeConfig: {
public: {
locale: {
defaultLocale: process.env.NUXT_I18N_LOCALE,
fallbackLocale: process.env.NUXT_I18N_FALLBACK_LOCALE,
}
}
},
...
and in .env file:
NUXT_I18N_LOCALE=tr
NUXT_I18N_FALLBACK_LOCALE=en
public: is very important otherwise it cannot read it and gives undefined error.
For v3 there is a precise description in the official docs
You define a runtimeConfig entry in your nuxt.config.[ts,js] which works as initial / default value:
export default defineNuxtConfig({
runtimeConfig: {
recaptchaSiteKey: 'default value' // This key is "private" and will only be available within server-side
}
}
You can also use env vars to init the runtimeConfig but its written static after build.
But you can override the value at runtime by using the following env var:
NUXT_RECAPTCHA_SITE_KEY=SOMETHING DYNAMIC
If you need to use the config on client-side, you need to use the public property.
export default defineNuxtConfig({
runtimeConfig: {
public: {
recaptchaSiteKey: 'default value' // will be also exposed to the client-side
}
}
}
Notice the PUBLIC part in the env var:
NUXT_PUBLIC_RECAPTCHA_SITE_KEY=SOMETHING DYNAMIC
This is very strange because we can't access process.env in Nuxt 3
In the Nuxt 3, we are invited to use the runtime config, but this is not always convenient, because the Nuxt application context is required.
But in a situation where we have some plain library, and we don’t want to wrap it in plugins nor composables functions, declaring global variables through vite / webpack is best:
// nuxt.config.ts
export default defineNuxtConfig({
vite: {
define: {
MY_API_URL: JSON.stringify(process.env.MY_API_URL)
}
}
})
And then you can use in any file without dancing with a tambourine:
// some-file.ts
console.log('global var:', MY_API_URL) // replaced by vite/webpack in real value

Exporting multiple functions with module.exports in ES6

I'm building a node.js application and I'm trying to put all my mongodb logic in a seperate file. At this time this file only has one function to initialize the mongodb connection. I want to export all the functions from this file using module.exports.
My mongo file looks as follows:
import { connect } from "mongoose";
const run = async (db: string): Promise<void> => {
await connect(db, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
};
module.exports = {
run
};
I want to use this run function in index.ts and im trying to import it as an ES6 module but I can't get it working with the above code.
How I'm importing:
index.ts:
import * as mongo from "./mongo";
Trying to call my run method:
mongo.run('dburl');
This throws following error: 'property run does not exist'
Now I have found a solution to this problem by adding an extra export before my run declaration:
export const run = async (db: string): Promise<void> => {...}
I don't understand why I have to do this as I'm already exporting this function inside module.exports, am I importing it wrong in my index file or is there a better way of doing this?
MDN: JavaScript Modules
There are different types of modules in JS.
ES6 Modules use the export keyword. You can import all the exports like this import * as ... from "..." or import individual exports via import { ... } from "..."
CommonJS modules use modules.exports which is equivalent to export default in ES6 modules. These you can import like this import ... from "...".
So when you use modules.exports you would either have to change your import to:
const mongo = require('./mongo');
Or you could change your export to:
export { run }

module.exports does not contain a default export

I am trying to export my theme in my react app using `module.exports =
module.exports = {
defaultFontColor: "#282828",
name: "Planswell",
primary: primary,
deemphasizedPrimary: "#e7f6ee",
secondary: "#E4A432",
danger: "#DF5F2B"...}`
in my file whatever.js, and i try to import it in another file using import whatever from "themes/whatever.js";
All was working well, but i updated Babel, and am now getting the error Attempted import error: 'themes/whatever.js' does not contain a default export (imported as 'whatever').
What changed with Babel that caused this error? And how do I fix it?
If the only export in your whatever.js is
module.exports = {mod1, mod2, ...}
Then, assuming whatever is actually a module in your file, you should have never been able to import it using
import whatever from "themes/whatever.js";
The only way that would be possible is if in your whatever.js you did:
export default whatever;
Otherwise, you will have to destructure the import like so:
import {whatever, mod1, mod2, ...} from "themes/whatever.js";
Again, all this assumes that whatever is actually a module inside your whatever.js file e.g const whatever = () => {.... You don't make that part clear.
The error you're getting should help you guide your way. When using module.exports = {...} syntax, the default export is the object.
You should try importing specific exported properties of the module such as import { someModule } from 'themes/whatever.js'. Optionally you can use
import * as whatever from 'themes/whatever.js'
// Use it
whatever.myFunction()
Babel is pretty complex tool so I would check from which version you upgraded to and then looked at the change log to see what has changed. Babel has plethora of presets and plugins so it could be any combination, sorry no simple answer here.
To me it seems like perhaps you're using some different type of module.
Maybe you are using #babel/preset-env with combination of browserslist settings and you transpile to ES6 modules?
in your whatever.js you have exporting the as an object that contain your component so you have to export it like this
import {whatever} from "themes/whatever.js";
for your example to work you have to export your component without brackets
export {whatever}

Exporting default from subdirectory [duplicate]

See question title. I found a great reference for the forms of export available, but I have not seen what I'm looking for.
Is it possible to do something like the following?
// file: constants.js
export const SomeConstant1 = 'yay';
export const SomeConstant2 = 'yayayaya';
// file: index.js
export * as Constants from './constants.js';
I.e. this would provide a named export Constants inside of index.js containing all of the named exports from constants.js.
This answer seems to indicate it's not possible in TypeScript; is the same true for pure JavaScript?
(This example is a bit contrived; in reality I'm trying to have a prop-types.js module that uses named exports for internal use within the React package, but also exports the prop type definitions under PropTypes for external consumption. I tried to simplify for the sake of the question.)
No, it's not allowed in JS either, however there is a proposal to add it. For now, just use the two-step process with importing into a local variable and exporting that:
// file: constants.js
export const SomeConstant1 = 'yay';
export const SomeConstant2 = 'yayayaya';
// file: index.js
import * as Constants from './constants.js';
export {Constants};
Today in 2019, it is now possible.
export * as name1 from …;
The proposal for this spec has merged to ecma262. If you're looking for this functionality in an environment that is running a previous JS, there's a babel plugin for it! After configuring the plugin (or if you're using ecma262 or later), you are able to run the JS in your question:
// file: constants.js
export const SomeConstant1 = 'yay';
export const SomeConstant2 = 'yayayaya';
// file: index.js
export * as Constants from './constants.js';
// file: component.js
import { Constants } from './index.js';
const newVar = Constants.SomeConstant1; // 'yay'
// file: index.js
// note, this doesn't have to be at the top, you can put it wherever you prefer
import * as AllExportsFromThisModule from "./index.js"; // point this at the SAME file
export default AllExportsFromThisModule;
export const SOME_CONSTANT = 'yay';
export const SOME_OTHER_CONSTANT = 'yayayaya';

Confusion about functional equivalency of `export` usage

Shouldn't
import * as convict from "convict";
const config = convict({ ... });
// Perform validation
config.validate({ "allowed": "strict" });
export = config;
be functionally equivalent to:
import * as convict from "convict";
export const config = convict({ ... });
// Perform validation
config.validate({ "allowed": "strict" });
The first snippet works, but the second snippet introduces type errors such as:
TypeError: config.get is not a function
When imported using:
import * as config from "./config";
(This question and Frequent issue with TypeScript and preferring import over require are different. This question is about exports and what should be two equivalent usages. The other question is about imports.)
export const config = ... is so called "named export", it adds config variable to the list of names exported by the module. You can look at various variants of es6 export statement here, this particular one corresponds to the 4th line of the first example (note 'also var, const' comment):
export let name1 = …, name2 = …, …, nameN; // also var, const
and can be used with "named import* like
import {config} from '...';
export = config is entirely different, it's typescript-only export assignment. The documentation says that is should be imported as import config = require(...) which is again typescript-only special syntax.
With current version of TypeScript, export assignment can also be imported as
import * as config from 'module';
but there is breaking change in the works, in the future (maybe as soon as 2.8) this import will stop working with export assingment and will have to be written as
import config from 'module';
The two are indeed different. Essentially, it all has to do with the fact that in the second case config is a named export.
The first snippet produces an export that is just the config. If you did require("./config"), you'd get that config object. This is because you set the exports object to the config. That's why you have to do * as config when importing, because the entire imported object is what you're looking to get.
The second snippet produces an object with a named config field that points to your config; this is equivalent (ish) to doing:
exports = {
config: convict({ ... })
};
In this example, config is a named export. To import it, you'd have to get the config field of the exported object:
import { config } from "./config";

Categories