Is it possible to somehow declare a jsx file as a global file or a directory for import? For example instead of:
import { Navigation } from '../../../../../../helpers/NavigationService';
do just:
import { Navigation } from 'NavigationService';
I've seen it's possible in webpack config, but I don't see this file in create-react-app. Can I use somehow package.json for that?
There are three ways to solve your issue:
NODE_PATH (<- probably what you're looking for):
You can define an environment variable NODE_PATH=src/ and then you can import your service like so import { Navigation } from 'helpers/NavigationService';. It'll will work but this is not necessary what's best in my opinion.
No deep nesting:
No nesting, means no issue of deep nesting in the first place. You can try having a file hierarchy similar to this:
src/
/helpers
/components/
/componentA/
componentA
relatedComponent
otherRelatedComponent <- no need for nesting
/componentB/
...
The mono repo approach:
Having an internal helper package and have it imported like import { Navigation } from 'myproject-helpers/NavigationService'; may be a good compromise
You could set NODE_PATH='src' in .env file, using global imports instead, here's my solution, without having to eject.
.env:
NODE_PATH='src'
Create a folder src/services, inside it create the NavigationService, my example:
// src/services/NavigationService.js
export class NavigationService {
static runIt() {
console.log("Running");
}
}
In the App.js file, now you can import the navigation service directly, using global import, as follows:
// src/App.js
// ... import React and others
import { NavigationService } from "services/NavigationService";
class App extends Component {
componentDidMount() {
NavigationService.runIt();
}
// ... render method
}
If using VsCode, to get code completion, create jsconfig.json file, with the following:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"services/*": ["./src/services/*"]
}
}
}
I hope it helps!
Related
I'm trying to set the type of a custom component, which is exposed via the Webpack module federation. The expose and the usage working fine but Typescript is complaining about the type of the component.
I have a "frame"-module which exposes a Sidebar component. This is used inside my "App"-module.
new ModuleFederationPlugin({
name: 'app',
filename: 'remoteEntry.js',
remotes: {
frame: 'frame#http://localhost:3000/remoteEntry.js',
},
import Sidebar from 'frame/Sidebar' //<- Cannot find module 'frame/Sidebar' or its corresponding type declarations.
I've tried several things to declare the type inside the "App"-module. I've created a #types folder inside my src folder. Inside this I've created two more folders "frame/Sidebar" and inside there an index.d.ts
import { VFC } from 'react'
declare module 'frame/Sidebar' {
const Sidebar: VFC
export default Sidebar
}
I've tried to move the file to different levels inside the #types folder, renamed it to frame.d.ts, tried a different declaration
declare module 'frame' {
const Sidebar: VFC
export { Sidebar }
}
But nothings works. I don't know, if typescript even recognizes my declaration, but the documentation states: "By default all visible ”#types” packages are included in your compilation.". So somehow my declaration is wrong.
Can anybody help me to correctly declare the type for this component?
I've found my problem. It seems like imports should be listed inside the declare module and not before. Types on the other hand can be defined outside. So this is the correct notation inside the src/#types/frame/Sidebar/index.d.ts file:
type SidebarProps = {
...
}
declare module 'frame/Sidebar' {
import { VFC } from 'react'
const Sidebar: VFC<SidebarProps>
export default Sidebar
}
I want to set up import path aliasing in a typescript/node/express project WITHOUT using other packages like tsconfig-paths and link-module-alias. I would like to do this with built-in nodejs functionality (the Typscript aliasing is already done).
Basically:
// Change
import { myFn } from '../../../utils';
// To
import { myFn } from '#this/utils';
The glimmer of hope I have is with node's subpath imports. Theoretically, I can just add this to my package.json:
"imports": {
"#this/*": "./dist/*"
}
Here's the problem
This works for explicitly importing the *.js files, but it does fails for implied index.js (i.e. Folders as modules)
// Works
import { myFn } from '#this/utils/index.js';
// Does not work
import { myFn } from '#this/utils';
However, I would expect node to resolve the import like this:
if utils is a directory, the import should resolve to */utils/index.js
if utils is a file, the import should resolve to */utils.js
My first thought would be to update the package.json imports to include all possibilities, but this is not supported:
"imports": {
"#this/*": [
"./dist/*",
"./dist/*.js",
"./dist/*/index.js"
]
}
The other option seems to be to define an exports entry for every directory, but that is not scalable.
With --experimental-specifier-resolution=node flag the code below works for me.
index.js:
import { myFn } from '#this';
package.json:
...
"imports": {
"#this": "./utils"
}
...
What worked for me on a typescript node project using esbuild was to define the path twice, but for the second time don't include /*. That will allow you to import the index.ts using #utils while still allowing you to import other files underneath the directory
{
"paths": {
"#src/*": ["src/*"],
"#src": ["src"],
"#utils/*": ["src/utils/*"],
"#utils": ["src/utils"]
}
}
In React when you wanna import components from other files we use:
import ComponentName from 'somePlace';
That works fine, but I wanna know if there is a way to import the content of a file instead of the exports. I wanna put all import statements for components in a single file (e.g. imports.js) and have a statement like:
import './import.js' to all documents;
so all my components are automatically imported everywhere.
Is there a way to do that?
Globally import modules? Not really, no. And neither should you need to.
A hacky "solution" would be assigning all imports to the global context (e.g. window in the browser) so it's accessible that way. That's possible, but definitely not recommended. It'll also prevent your bundler (most likely Webpack) from optimizing a lot of code.
Apart from the technical aspect, there are other reasons not to do so. If you specify the imports in each file, you know exactly what imports that file needs and under what variables it is imported as for that file.
If you still want to simplify importing the same components over and over again, you can have this setup:
imports.js
// For default exports
import ComponentA from 'wherever';
export { ComponentA };
// For regular exports
//import { ComponentB } from 'wherever';
export { ComponentB } from 'wherever';
// For whole modules
//import * as wherever from 'wherever';
export * as wherever from 'wherever';
someOtherFile.js
// Either import as a namespace
import * as Imports from './imports';
console.log([
Imports.ComponentA,
Imports.ComponentB,
Imports.wherever.someFieldFromTheWhereverModule,
]);
// Or partial import
import { ComponentA, ComponentB } from './imports';
I want to write a javascript library with two files:
snabbpixi.js
export function init() {
}
pixiapi.js
export function createElement() {
}
I want to use this library like this:
import { init } from 'snabbpixi';
import { createElement } from 'snabbpixi/pixiapi';
If I don't do anything and set the package.json for library as:
{
"main": "src/snabbpixi.js"
}
second import doesn't work (import { createElement } from 'snabbpixi/pixiap')
If I compile this library and export as umd format using webpack it also doesn't work.
How can I configure my library so I can import like this:
import { createElement } from 'snabbpixi/pixiap'
I normally do this sort of thing in TypeScript rather than straight JavaScript, but hopefully this works in basically the same way...
Try creating a new file (typically named index.js), with contents like this:
export * from './snabbpixi'; // Adjust paths as needed for your particular case.
export * from './snabbpixi/pixiapi';
Then make index.js your main.
The import you would use would then be flattened-out, however, looking more like:
import { init, createElement } from 'snabbpixi';
When you are using import { Something } from 'somewhere' you are calling on a named export from a given file or directory.
If the two files are in different directories then you can add an index.js file to each directory and then use export { default as function } from './file'
To do this you would have to export the default file from pixiapi and snabbpixi.
If you have both files importing into your index.js then you will still want to export them as defaults. But then you would do the following..
import file1 from './file1'
import file2 from './file2'
export default {
file1,
file2,
}
This will allow you to use the named imports as well and keep them in the same directory
I recently started using a Node library called bpmn-js (npmjs.com).
It is written in JavaScript, and I'd like to have typings. Thus, I've began reading about d.ts files.
I created this folder structure
webapp
#types
bpmn-js
index.d.ts
With a simple content
declare module 'bpmn-js' {
export class BpmnJS {
constructor();
}
}
But this doesn't seem to work.
"Before" typings, I was able to import the object I needed using
import BpmnJS from 'bpmn-js';
And I was able to instantiate it using
new BpmnJS();
How can I get the typings file to be recognized?
I'm using WebStorm 2019.1.*.
Pretty simple, I was missing export default, or better, the default part.
declare module 'bpmn-js' {
export default class BpmnJS {
constructor(param?: { container: string });
...
}
}
Now this works too
import BpmnJS from 'bpmn-js';