Is it possible to avoid long relative import paths on Flow? - javascript

Could you point me to an example of how to configure Flow so that I could just use the name of a file for imports instead of long relative paths ?. This implies that the name of my files in my entire working directory are unique.
example:
Directories
pages/components/foo.js
common/types/abc.js
Current import statements
import foo from "../../pages/components/foo"
import abc from "../common/types/abc"
Desired import statements
import foo from "foo"
import abc from "abc"

This is very possible. But first hopefully you're setup your bundling tool to also accept parsing absolute path names because remember that flow does not handle logic it simply does code analysis but would throw errors if you haven't setup the pathing in .flowconfig and flow has no idea how to do a file lookup.
The option you're looking for is module.name_mapper which will repoint your written import into something else based on an ocaml regex.
If you are using create react app or have a setup similar for example you can see the adding flow section to see an example of how they've recommended handling it.

Related

Importing js modules by directory name

I'm upgrading a React application and have found that I need to modify the import statements to get them to work.
For example, in the old version, the following import works without errors:
import { User } from '../System'
Note that System is a directory on my file system that contains User, a js file that ends with export default User.
In my upgraded version of the app, the System directory still exists, but the above import gives me Can't resolve '../System' in 'C:\my app\.
It turns out that to get the import working properly now, I need to change it to the following:
import User from '../System/User';
If I understand correctly, this relates to js module system changes made with ES6.
My question, though, is regarding the specification of a directory in the import statement (System above). Why would it be that I was previously able to name a file directory in the import statement instead of the actual js script/module itself? Is that approach of using a directory in the import statement still possible? And if so, is it ever advisable?
Update: based on AKX's comment, I noticed the System directory does indeed contain an index.js, which apparently is what makes the import from the directory itself possible.
When an import points to a directory, and only a file, Webpack (which most React setups use) follows Node's's conventions and will attempt to import index.js from that directory if it exists. That's the only condition under which importing from a path that points to a directory works - your previous build probably had /System/index.js (which would allow importing with from '../System'). If you rename the file you're importing to anything else - such as to User.js - importing using only the directory path will fail.
And if so, is it ever advisable?
Sure, if you want. It's a style choice but is commonly done.

Ignore flowtype error when using specific pattern

I'm trying to use typescript together with flowtype in a transition period where everything is changing to typescript. However, flowtype is giving me an error, when I try to import declarations from a typescript file in a regular js|jsx file. I get the usual Cannot resolve module '*.tsx. Is it possible to ignore this flow error globally without having to use $FlowFixMe above my import statements?
This is giving flow errors, that I want to supress:
import foo from 'foobar.tsx';
That is likewise an error in TypeScript. Depending on your module loader/bundler's extension resolution, use either
import foo from 'foobar';
or
import foo from 'foobar.js';
Since you are using JSX it's worth noting that
import foo from 'foobar.jsx';
is also incorrect.

Webpack, eval certain modules during the compilation

I'd like to create a Webpack loader (or plugin) which would allow to replace a call to a certain method to the result returned by this method during the compilation. For example, let's assume I have a file named transpile_time.js:
import {SomeUsefullStuff} from 'a_very_cool_lib'; //<-- this should be resolved correctly
module.exports = function{
//let's assume that 'a_very_cool_lib' is used somewhere here
return 'console.log(\'tralala\')';
}
And, I have another another file named App.ts:
import {default as tt} from './transpile-time';
....
function someFunc(){
...
tt(); // <------ I want this code to be replaced to
// 'console.log(\'tralala\')'
// during the compilation process
}
For App.js my custom loader is used.
With the help of Esprima and Estraverse and Escodegen I'm able to manipulate the sources, but at some moment I need to resolve the dependency
import {default as tt} from './transpile-time';
dynamically in my loader with respect to the fact that it can have it's own dependencies as well. In the example above,
import {SomeUsefullStuff} from 'a_very_cool_lib';
should be resolved correctly. Webpack Loader API offers loadModule method, this gives the sources and the module object. The latter theoretically contains dependencies with their sources and I can go through them and replace every import statement with the corresponding source code and then use eval. But that is quite ugly, I would prefer to let Webpack doing this job. For example, there is a compilation object, it seems like it is possible to insert some hooks, but this is not described well. Does anyone have an idea?
P.S. I'm going to use it all for template resolving and code generation.
Update:
After doing a small investigation on how Weback works internally (this article was quite helpful), I think that it would be better to use a plugin instead of a loader. And, probably, I don't need Esprima and other tools because Webpack also builds AST at some stage. But still I don't know how to use it.

How to import from '#somefolder' in angular

I was going through someone's code and found this:
import { NGSWUpdateService } from '#ngsw/ngsw-update.service';
The developer has been able to use '#ngsw/ngsw-update.service' instead of original very long path 'src/client/app/shared/ngsw/ngsw-update.service'.
So how to implement the above so that I don't have to import from relatively long paths.
Here's the code.
When you import from a path that is not relative, it'll look into the node_modules folder.
So here, it's just looking for the file ngsw-update.service here: node_modules/#ngsw/ngsw-update.service.
That's the most basic use case but you can only use that those kind of paths with files from your project by defining them into tsconfig.json (within compilerOptions.paths`, see that article for more: https://netbasal.com/sexier-imports-in-typescript-e3c645bdd3c6

Can you import using absolute paths in React?

I am able to use this tutorial for React Native, but it doesn't seem to work with React.
You'll have to do this:
Add a package.json file with { “name”: “FOLDER_NAME” } in it to the folder you’d like to import from.
import Thing from ‘FOLDER_NAME/thing’ or import Thing from ‘./thing’
…except when going “up” in the folder structure.
import Blah from ‘../../../../../blah’
In your React Native project, chances are you keep your code in a single folder, such as “app”.
If you have a directory named “app” this is what an absolute path might look like:
import Thing from ‘AwesomeApp/app/some/thing’
What sucks about this is literally all import statements (or require calls, if you’re still into that) would start with “AwesomeApp/app/”, which is a lot to ask, when the alternative is simple to add a series of “../” (the key strokes are just so close together, it’s too easy).
To alleviate this pain point, you can simply add a package.json file inside the folder from where you want to import. In this case since all our code is under the “app” folder, we’d put the file here:
AwesomeApp/app/package.json
Then, add a “name” property to the json file with the folder name as its value (you can call it whatever you’d like, but really, that’ll just confuse people, including you in 6 months). The shorter, the better.
{ “name”: “app” }
Now, you can import using that name as a reference.
import Thing from ‘app/some/thing’

Categories