I've found at least two ways to import functions in from a module like Ramda for example. There are probably a few more ways to do something very similar like const R = require('ramda');
Option 1 is to import certain functions:
import { cond, T, always, curry, compose } from 'ramda';
Option 2 is to import the whole module like:
import * as R from "ramda";
I would prefer to reference the module from which the function is being called like so:
R.T();
But if the 2nd option is used, does it bring in every Ramda function not just the ones used in a module I'm working in? Are there any impacts on actual memory use, or bandwidth use as far as what gets sent to the browser if option 2 is used?
Is it possible to somehow do this:
// invalid syntax below:
import R { cond, T, always, curry, compose } from 'ramda';
R.T();
My question is kinda related to this one, but it's a bit different
import R (ramda) into typescript .ts file
TL;DR: It does not matter.
import * as … from 'ramda';
import { … } from 'ramda';
will both by default always bring in the complete Ramda module with all its dependencies. All code inside the module would be run, and which syntax was used to reference the exported bindings doesn't matter. Whether you use named or namespaced imports comes down to preference entirely.
What can reduce the file size to download and the used memory is static analysis. After having evaluated the module, the engine can garbage-collect those bindings that are referenced from nowhere. Module namespace objects might make this slightly harder, as anyone with access to the object can access all exports. But still those objects are specified in a way (as immutable) to allow static analysis on their usage and if the only thing you're doing with them is property access with constant names, engines are expected to utilise this fact.
Any size optimisation involves guessing which parts of the module need to be evaluated and which not, and happens in your module bundler (like Rollup or WebPack). This is known as Tree Shaking, dropping parts of the code and entire dependencies when not needed (used by anything that got imported). It should be able to detect which imports you are using regardless of the import style, although it might have to bail out when are doing unusual things with the namespace object (like looping it or using dynamic property access).
To learn about the exact guesses your bundler can make, contact its documentation.
#Bergi is right in his comment, which I think should be the answer. I would also like to point out you can always try things out in Babel to see what it compiles to: click here to see what an example destructuring actually does
So basically even if you destructure just one function from the module, the whole module will be required. In the Babel example I gave, I just extracted Component from the 'react' module, but the compiled code actually just required the whole thing. :)
Adding to #Bergi, Also just for future reference if you want to shed unused functions and import only the desired function, use selective import like below
import isEmpty from 'ramda/src/isEmpty';
This way you can complement it with Webpack and get a better tree shaking. Hope it helps
Related
// add.js
const add = (a, b) => a +b;
How can I test the add function? I want to test add function logic. But I don't know how to test it. Because the function is not exported. I want this function to be called only on add.js.
Do I have to export this add function for testing with jest?
There's a lot of debate on this topic. If your add function is not exported, it is considered "private/internal" to your module and is not part of the public API. Many people argue that you should only test your public API, others argue that you will need to export your private functions if you wish to test them. Both sides make great points and it boils down to a matter of preference.
My preferred technique is to put these types of helper functions in a separate module which is tested separately and imported wherever you need it. These methods become "public", but in practice I have found that it doesn't hurt anything and you might actually end up reusing the code somewhere else without needing to refactor anything.
You can also try exporting your methods but mark them as #private using the popular JSDoc syntax. This is merely a hint to developers that they shouldn't import or use the method, and some editors/IDEs might even hide the method from intellisense.
/** #private */
export const add = (a, b) => a + b;
At the end of the day you can't really test private (non-exported) methods without using some tool like rewire. I used to use rewire a lot, however, I don't recommend it any more as it makes your tests more complex and brittle. I have found that good tests are simple and easy to read, which is not the case when you use things like rewire. Don't get caught in the trap of "developers shouldn't be able to see or use this private function" - it's a toxic way to think about your code IMO.
I am new to React and I've come across two bits of code that I think do the same thing, but I am not entirely sure.
import React from 'react'
export default function TestComponent() {
return (
<div>
</div>
)
}
as well as
import React from 'react'
function TestComponent() {
return (
<div>
</div>
)
}
export default TestComponent
The only difference that I can see between the two is that the export is just put at the end in one of them but they should both behave the same if my understanding is correct. Does this have any real effect on the behaviour of the code?
As several in the comments have already said, those two code blocks are practically equivalent (ie. they are the same). In theory you could add code to make them different (eg. you could re-assign the function before exporting it in the second example) ... but it would be pretty contrived.
Does this have any real effect on the behaviour of the code?
No. What matters is just that you name your exported functions at all (and in fact the Create React App rules will fail if you don't, because it could make your debugging harder).
It's the same thing in your case because you are creating your React component by using a 'classic' Javascript function.
I personnally use the first code to save a line but the second code is usefull when you have a React.js component written in arrow function like as is :
const yourComponent = () => {};
export default yourComponent;
In this case, you must use this line at the end of your file :)
Both code blocks are functionally the same but I personally favor the second.
Both use a function declaration but the second one permits you to swap the declaration out for a function expression or class declaration without modifying the export.
Also, in cases where you can have multiple exports from a single file, it's a useful convention to declare the default export at the bottom of the file.
All in all, that's not a matter for React or components, but for coding in general and JavaScript modules especially.
It might be matter of scalability on the dev side, i.e. how you yourself will be able to manage your code if it grows. If you have to add and maintain more functions / classes / variables, it's a benefit to separate the place in code where you define the functions / classes / variables from that where you define wich to export and from that where you define your default export because you can only have one default export, but many non-default exports - imagine you decided to re-declare which export is the default one, labeling the new one as "default" and forget to "de-label" the old one, then with defining "default" somewhere in your code the old default might outrule the new one because being later in the code. Declaring exports at the end of file will give you helpful overview.
As question of personal style might be if you want to use "export" directly where a function / class / variable is defined to see immediately what functions / classes / variables are "public" and which are "private" (i.e. not exported).
If your code grows into something requiring some kind of an API, you might use the option to export as, e.g. maintaining complicated "speaking" functions names inside of your code, but exposing the functionality by "simple" names to the component's consumers. This would be obviously easier if being separated from the definitions of the functions itself.
In general, for your own sake, be as explicit as possible, here: separate "export" instructions. Trying to have short and clever code leads to more complexity than myriads of "stupid simple" code. React and other soft- and hardware is not impressed how cleverly you may have code golfed, very rarely something would be faster or slower, since optimization should not be part of developing, and trying to generalize should be well dosed.
For JavaScript "ES6" modules used by React for components, the 2015 introduction https://hacks.mozilla.org/2015/08/es6-in-depth-modules/ is still the best reference and surely a must-read.
Both are technically same, the only difference is that you add an extra line to export your functional component in second code. I generally prefer second code because it keeps my code clean when compared to first code.
I'm building a large React application that involves processing lots of data, formatting it and outputting to tables. Occasionally these functions are variables (e.g const x = () => etc.)
I'm storing the functions that do this formatting in Typescript files which I import into my React components.
To give an example, I might write a table formatting function like this:
export const buildMainData = (data: any) => {
do stuff
}
I'm placing it inside a file, called functions.ts (for example).
I then have a React component which makes use of the function.
My question is - is this a bad idea? Am I creating loads of functions that are polluting the memory heap? I'm using create-react-app so I'm not sure if Webpack is doing some magic behind the scenes to prevent global variables, or whether everything I write should be placed inside of React components.
It would be great if anyone with more experience / knowledge in this area could help out. If I'm also completely getting the wrong end of the stick that would also be helpful to know. Thanks.
The variables and functions you're exporting aren't globals, they're exports from the module in which you define them. They're used via import. If you have some that aren't used, modern bundlers like Webpack and Rollup can tree-shake the bundle they create, leaving unused functions out (if there are any). More about tree-shaking in Webpack and in Rollup.js.
It's true that top-level declarations in classic scripts are globals, but top-level declarations in modules are scoped to the module (kind of like the module were a function and you were declaring things inside it), and then possibly exported from it.
In implementing the Python module mechanism on top of ES6 modules for the Transcrypt Python to JavaScript compiler, I am faced with the following problem:
There are a large number of standard functions imported from the Python runtime module, like e.g. the Python input function (implemented in JS), which can be made available using named imports (since they shouldn't have to be prefixed with anything in the user code, so input rather than __runtime__.input, to be consistent with Python).
In Python it's allowed to rebind named imports. So I define another function input, which will override the one from the runtime. But if I do so in JS, I get an error:
Identifier 'input' has already been declared
It seems that all imported names are regarded as JS consts, so non-rebindable according to this article. I can think of several clever workarounds, like importing under an alias and then assigning to a module global var rather than const, but like to keep things simple, so my question is:
Am I right that JS named imports are consts, so non-rebindable (and if so, just curious, anyone knows WHY)? Where can I find details on this?
Is there a simple way to circumvent that and still put them in the global namespace of the importing module, but override them at will?
As per the language specification, imported bindings are immutable bindings, so they cannot be changed. The identifiers are reserved as the module gets parsed because of how ES6 modules work: Unlike in Python, imports are not statements that are included as they are executed; instead, all a module’s imports are basically collected during the early compilation and then resolved before the module starts executing.
This makes ES6 modules kind of unsuitable as an implementation for Python’s import system.
As a general way, to avoid losing those names, you can simply give the imported bindings different names. For example an from foo import bar, baz may be compiled to the following:
import { bar as _foo__bar, baz as _foo__baz } from 'foo';
let bar = _foo__bar;
let baz = _foo__baz;
That will only reserve some special names while keeping the bar and baz identifiers mutable.
Another way, which would probably also help you to solve possible import semantics differences would be to simply create a closure:
import { bar, baz } from 'foo';
(function (bar, baz) {
// …
})(bar, baz);
Or even add some other lookup mechanism in between.
Btw. Python’s import is very similar to Node’s require, so it might be worth looking into all those solutions that made Node’s module system work in the browser.
In Webpack 1.x I used to do the following on regular basis:
require.ensure([ './mod2.js' ], ( require ) => {
setTimeout(() => {
// some later point in time, most likely through any kind of event
var data = require( './mod2.js' ); // actual evaluating the code
},1100);
}, 'myModule2');
With this technique, we were able to transfer a webpack-bundle over the wire, but evaluate the actual contents (the JavaScript code) from that bundle at some later point in time. Also, using require.ensure we could name the bundle, in this case myModule2, so we could see the name / alias when bundling happened executing webpack.
In Webpack 2.x, the new way to go is using System.import. While I love receiving a Promise object now, I have two issues with that style. The equivalent of the above code would look like:
System.import( './mod2.js' ).then( MOD2 => {
// bundle was transferred AND evaluated at this point
});
How can we split the transfer and the evaluation now?
How can we still name the bundle?
The Webpack documentation on Github says the following:
Full dynamic requires now fail by default
A dependency with only an expression (i. e. require(expr)) will now
create an empty context instead of an context of the complete
directory.
Best refactor this code as it won't work with ES6 Modules. If this is
not possible you can use the ContextReplacementPlugin to hint the
compiler to the correct resolving.
I'm not sure if that plays a role in this case. They also talk about code splitting in there, but it's pretty briefly and they don't mention any of the "issues" or how to workaround.
tl;dr: System.resolve and System.register do most of what you want. The rest of this answer is why require.ensure cannot and how System.import calls the others.
I think ES6 modules prevent this for working well, although following it through the relevants specs is tricky, so I may be totally wrong.
That said, let's start with a few references:
the WhatWG module loader
the ES6 specification on modules (§15.2)
the CommonJS module specification
the fantastic 2ality article on ES6 modules
The first reference explains more behavior, although I'm not entirely sure how normatize it is. The latter explains the implementation details on the JS side. Since no platforms implement this yet, I don't have references for how it actually work in real life, and we'll have to rely on the spec.
The require that has been available in webpack 1.x is a mashup of the CommonJS and AMD requires. The CommonJS side of that is described in ref#3, specifically the "Module Context" section. Nowhere does that mention require.ensure, nor does the AMD "specification" (such as it is), so this is purely an invention of webpack. That is, the feature was never real, in the sense of being specified somewhere official and fancy looking.
That said, I think require.ensure conflicts with ES6 modules. Calling System.import should invoke the import method from a Loader object. The relevant section in ref#2 does not lay that out explicitly, but §10.1 does mention attaching a loader to System.
The Loader.prototype.import method is not terribly involved, and step 4 is the only one that interests us:
Return the result of transforming Resolve(loader, name, referrer) with a fulfillment handler that, when called with argument key, runs the following steps:
Let entry be EnsureRegistered(loader, key).
Return the result of transforming LoadModule(entry, "instantiate") with a fulfillment handler that, when called, runs the following steps:
Return EnsureEvaluated(entry).
The flow is resolve-register-load-evaluate, and you want to break between load and evaluate. Note, however, that the load stage calls LoadModule with stage set to "instantiate". That implies and probably requires the module has already been translated via RequestTranslate, which does much of the heavy parsing as it tries to find the module's entry point and so on.
This has already done more work than you want, from the sounds of it. Since the basics of module loading require a known entry point, I don't think there's a way to avoid parsing and partially evaluating the module with the calls exposed from System. You already knew that.
The problem is that System.import can't possibly know -- until after parsing -- whether the module is an ES6 module that must be evaluated or a webpack bundle that could be deferred. The parsing must be done to figure out if we need to parse, leading to a chicken-and-egg problem.
Up to this point, we've been following the path from System.import through the Loader. The import call is dictating what stage of import we're at, assuming you want to go through the full end-to-end loading process. The underlying calls, like Loader.prototype.load, provide fine grained control over those stages.
I'm not sure how you would invoke the first two stages (fetch and translate), but if you were able to translate and register a module, later calls should simply evaluate and return it.
If the spec is accurate, this should be exposed (in supporting implementations) through the System.loader property and would have the methods you need to call. There are large parts of the flow you don't have access to, so I would suggest not doing this and instead setting up your code so nothing significant runs when a module is loaded. If that's not possible, you need to recreate the flow up through registering but stop shy of evaluation.