How does the JavaScript Import work under the hood? - javascript

How does the import statement actually work in JavaScript? I read the documentation and it says that it places exported code within the scope of the file. Does that mean that the code is copied over into the file where I type import?
For example - in library.js I have:
export {export function getUsefulContents(url, callback) {
getJSON(url, data => callback(JSON.parse(data)));
}
In main.js I have:
import { getUsefulContents} from 'library.js';
getUsefulContents('http://www.example.com',
data => { doSomethingUseful(data); });
This allows me to call getUsefulContents() in main.js. My question is, does main.js now have the contents that I exported from library.js?
Is using import the same as just having physically defined getUsefulContents() in main.js?
function getUsefulContents(url, callback) {
getJSON(url, data => callback(JSON.parse(data)));
}
getUsefulContents('http://www.example.com',
data => { doSomethingUseful(data); });
The main reason why I ask is because I want to know if using import will have an effect on main.js file size? Or is something else going on under the hood?
Thank you!

Depends on how you are using main.js. If you run it through a bundler, then the bundler will probably include library.js into main.js to pack it up into one file. In that case, the only advantage would be maintainability and ease of development because you are focused on the file you are working on. If you are simply running the import statement and deploying your application, the import statement won't affect the file size of main.js.

It just namespacing it within the file that you are importing it to so
any code from useful-library.js is included in the file, I visualize it this way
import { usefulCodeFromLibrary } from './useful-library.js';
((usefulCodeFromLibrary)=>{
// My excellent code
// Imported code doing it's job
usefulCodeFromLibrary.someHelperFunction()
}()

Related

importing modules from other folders nodejs

This is kind of a silly question, but I want to be able to write code in different files, and then import the code and use it all, like have it written in different files and it all work together.
like this:
routes
login.js
register.js
views
index.ejs
login.ejs
register.ejs
app.js
so if I create a function inside register.js, how do I say, hey, call that function in login.js now, and have it work? do I have to import the files all in app.js? I have only done small projects where this hasn't been necessary, but now I need to :)
Thanks for the help
You can use module.exports object to make your function accessible in another file.
let's say you have defined 2 functions in register.js as follows
const registerfunction1=()=>{
console.log("console registerfunction1")
}
const registerfunction2=()=>{
console.log("console registerfunction2")
}
module.exports={
registerfunction1,
registerfunction2
}
Now you can call these functions any file by using the node require as follows.
for example
//importing register module
const register=require('./register');
const loginFunction=()=>{
// calling function defined in register
register.registerfunction1();
console.log("loginFunction");
};
//calling function
loginFunction();

Exporting one set of functions from multiple files

I've just finished writing a big quickbooks wrapper in JavaScript with a lot of parts in different files, e.g. a file for tax, a file for accounts, a file for auth, etc. I'd like to make it so that developers using this wrapper will only have to do one import that will contain all the functions I've written.
Hierarchy is something like this:
QbTax.js
QbAccounts.js
QbAuth.js
I'd like to have another file, or a way that a developer using this wrapper would only have to import one thing, then be able to call all functions from the above files from that one import.
Something like this:
import * as qb from './unifiedQbFile.js';
qb.thisIsATaxFunc();
qb.thisIsAnAccountsFunc();
qb.thisIsAnAuthFunc();
What is the best way to approach this?
The only idea I have at the moment is to write prototypes in a file (unifiedQbFile.js for instance) and export those. I'd import all the functions from my other files in that unified file then call them in my new prototypes. That seems messy though.
you can have one index.js file that exports all files then you can import that index.js file. I would personally go with this method.
// index.js
export { qbTaxFunc } from 'QBTax';
export { qbAccountsFunc } from 'QbAccounts';
export { qbAuthFunc } from 'QbAuth';
Now in some other script to import it you can do.
import qb from 'path-to-index.js';
// All functions should now be available
qb.qbTaxFunc();
qb.qbAccountsFunc();
qb.qbAuthFunc();

Import Vs Require Node issue. Cant we require any module using import?

const csv = require('csvtojson') this works
import { csv } from 'csvtojson' but this dont.
Can anyone help what the issue here ?
The {} is to import partially from the csvtojson lib, and require is used to import every exported object from lib.
What kind of error do you get? Could it be that later in your code you depend on something else from csvtojson and that is why you get an error.
Consider the example below:
// hello.js
function hello1() {
return 'hello1'
}
function hello2() {
return 'hello2'
}
export { hello1, hello2 }
// app.js
import { hello1, hello2 } from './hello'
hello1() // returns hello1
hello2() // returns hello2
You would have to use .mjs file extention instead of .js.
Read about ECMAScript modules enabling - it is still experimental so you may want to be sure before using it.
Another way would be to use babel to compile code to commonJS

How to best import "server-only" code in Next.js?

In the getServerSideProps function of my index page, I'd like to use a function foo, imported from another local file, which is dependent on a certain Node library.
Said library can't be run in the browser, as it depends on "server-only" modules such as fs or request.
I've been using the following pattern, but would like to optimize it. Defining foo as mutable in order to have it be in scope is clunky and seems avoidable.
let foo;
if (typeof window === "undefined") {
foo = require("../clients/foo");
}
export default function Index({data}) {
...
}
export async function getServerSideProps() {
return {
props: {data: await foo()},
}
}
What would be the best practice here? Is it somehow possible to leverage ES6's dynamic import function? What about dynamically importing within getServerSideProps?
I'm using Next.js version 9.3.6.
Thanks.
UPDATE:
It seems as if Next.js's own dynamic import solution is the answer to this. I'm still testing it and will update this post accordingly, when done. The docs seem quite confusing to me as they mentionn disabling imports for SSR, but not vice versa.
https://nextjs.org/docs/advanced-features/dynamic-import
When using getServerSideProps/getStaticProps, Next.js will automatically delete any code inside those functions, and imports used exclusively by them from the client bundle. There's no risk of running server code on the browser.
However, there are a couple of considerations to take in order to ensure the code elimination works as intended.
Don't use imports meant for the server-side inside client-side code (like React components).
Ensure you don't have unused imports in those files. Next.js won't be able to tell if an import is only meant for the server, and will include it in both the server and client bundles.
You can use the Next.js Code Elimination tool to verify what gets bundled for the client-side. You'll notice that getServerSideProps/getStaticProps gets removed as do the imports used by it.
Outside of getServerSideProps/getStaticProps, I found 2 fairly similar solutions.
Rely on dead code elimination
In next.config.js:
config.plugins.push(
new webpack.DefinePlugin({
'process.env.RUNTIME_ENV': JSON.stringify(isServer ? 'server' : 'browser'),
}),
);
export const addBreadcrumb = (...params: AddBreadcrumbParams) => {
if (process.env.RUNTIME_ENV === 'server') {
return import('./sentryServer').then(({ addBreadcrumb }) => addBreadcrumb(...params));
}
return SentryBrowser.addBreadcrumb(...params);
};
Note that some for reason I don't understand, dead code elimination does not work well if you use async await, or if you use a variable to store the result of process.env.RUNTIME_ENV === 'server'. I created a discussion in nextjs github.
Tell webpack to ignore it
In next.config.js
if (!isServer) {
config.plugins.push(
new webpack.IgnorePlugin({
resourceRegExp: /sentryServer$/,
}),
);
}
In that case you need to make sure you will never import this file in the client otherwise you would get an error at runtime.
You can import the third party library or a serverside file inside getServerSideProps or getInitialProps since these functions run on server.
In my case I am using winston logger which runs on server only so importing the config file only on server like this
export async function getServerSideProps (){
const logger = await import('../logger');
logger.info(`Info Log ->> ${JSON.stringify(err)}`);
}
You can also import library/file which has default export like this
export async function getServerSideProps(context) {
const moment = (await import('moment')).default(); //default method is to access default export
return {
date: moment.format('dddd D MMMM YYYY'),
}
}

ES6 import syntax imports whole file instead of function only

I have a couple of JS files with quite a few functions. In one of the files, I have a function written that I wish to export and use in another file. Here is the function:
export default function updateMinimumAmountNotice(subtotal) {
let parsedSubtotal = parseFloat(subtotal);
let minimumOrderAmount = parseFloat(minimum_order_amount);
if (parsedSubtotal < minimumOrderAmount) {
minimumOrderNotice.find('#checkout-amount').text((minimumOrderAmount - parsedSubtotal).toFixed(2));
} else if (parsedSubtotal >= minimumOrderAmount) {
minimumOrderNotice.hide();
}
}
In my other file, I am importing it like so:
import updateMinimumAmountNotice from './single-product';
When I import the function updateMinimumAmountNotice, I get errors on the page that are from non-imported functions in the same file of the function that I am importing. None of those functions are exported and the file is not loaded on the page. Most of the JS files are page-specific and only load on the page they have logic for.
If it matters, I am using Webpack as a build tool with BrowserSync.
So, is this normal behavior for importing/exporting modules, or is there something else going on?

Categories

Resources