How to import absolute paths in a #nrwl/nx monorepo? - reactjs

I'm working on a #nrwl/nx monorepo. I want to import the folders inside the project src by the absolute paths. I tried specifying the baseUrl but didn't work. The only solution worked is, adding the path to the monorepo root tsConfig.json file as follows.
"paths": {
"*": ["apps/my-app/src/*"]
}
But, the problem is, if I have another project, I will have to add that project as well to this path. I tried something as follows.
"paths": {
"*": ["apps/*/src/*"]
}
But, this doesn't work anymore. It doesn't match the project folder name.
How can I solve this? Or, is there any better way to import by absolute paths?

I'm facing the same problem, due to organizing common DTOs and Event.ts files in the nx monorepo. I found useful to update the tsconfig.base.json with a simpler path shortcut, that allow cross app imports and at the same time mantains the options of setting an absolute path in the single apps tsconfig.json file.
Here's my base.json:
"baseUrl": ".",
"paths": {
"libs": [
"libs/"
],
"app1: [
"apps/app1/"
],
"app2": [
"apps/app2/"
],
}
Now I have a sort of absolute imports that point to app names as base:
import {CreateUserEvent} from 'libs/events/create-user.event';
This is a random file in the app1/src/app/ folder that import a file in libs folder
Folder structure is:
root ('.')
|__ app1/src/app/file_with_import.ts
|__ ...
|__ ...
|__ libs/events/create_user.event.ts
Hope it helps

Related

Absolute paths with parcel and react

I have a react app that uses parcel instead of webpack and I wanted to add absolute paths into the project so I followed this guide and it works perfectly (you can ctr click on the path and it finds it( BUT parcel is not happy with this because it cant resolve the path of the file if you say
/components/thisComponent/thisComponent.jsx
it says this instead
#parcel/resolver-default: Cannot load file '../../../thisComponent/thisComponent' in './src/thisComponent/thisComponent'.
💡 Did you mean '../../thisComponent/thisComponent'?
💡 Did you mean '../../../.thisComponents/thisComponents'?
is I tried using the ~ instead but that doesnt work as well. How can I use absolute paths with parcel ?
This has worked for me:
import {Button} from '../../../../../shared';
// changed to:
import {Button} from '~src/shared';
jsconfig.json:
{
"compilerOptions": {
"baseUrl": "src"
},
"include": ["src"]
}

Typescript + webpack module resolution

I am having an issue with webpack/typescript correctly resolving modules.
Consider the below structure
Project files
src/models/item.ts
Dependencies
node_modules/#common/src/models/item.ts
node_modules/#common/src/models/container.ts
The #common module contains common libraries, that each project can use and extend base on its needs.
What I am trying to accomplish is that when the container.ts imports item.ts as
import item from "models/item";
Webpack should resolve the path to the project's path.
However, I am getting the one from the #common path
Below is the relevant part from CRA's ejected webpack config and the relevant tsconfig
webpack config
resolve: {
// This allows you to set a fallback for where webpack should look for modules.
// We placed these paths second because we want `node_modules` to "win"
// if there are any conflicts. This matches Node resolution mechanism.
// https://github.com/facebook/create-react-app/issues/253
modules: ['node_modules', paths.appNodeModules, "./src", "node_modules/#common/src"].concat(
modules.additionalModulePaths || []
),
tsconfig.json
"paths": {
"*": ["*", "src/*", "../node_modules/#common/src/*"]
},
I would expect this to be possible.
Am I missing something?
Thanks for any help

Typescript library import with sub paths

I have a Typescript library that is being consumed from a React app. I wanted to import the TS library contents with sub-paths like
import {base} from "my-lib"
import {foo} from "my-lib/path1"
import {bar} from "my-lib/path2"
I came across the Github issue which states that this is not yet supported (exports in package.json) by Typescript. I'm using Typescript 4.3.
There is a workaround posted in the same thread - Github repo typescript-subpath-exports-workaround. It uses exports and typeVersions
{
"main": "dist/index.js",
"types": "dist-types/index.d.ts",
"exports": {
".": "./dist/index.js",
"./exported": "./dist/exported.js"
},
"typesVersions": {
"*": {
"exported": ["dist-types/exported"]
}
}
}
I created a new react app (via npx create-react-app command) and tried importing hello from typescript-subpath-exports-workaround and it worked fine. But couldn't import `typescript-subpath-exports-workaround/exported
import {hello} from "typescript-subpath-exports-workaround" //works fine
import {foo} from "typescript-subpath-exports-workaround/exported" //gives "Module not found" error
Full error is below:
./src/App.js
Module not found: Can't resolve 'typescript-subpath-exports-workaround/exported' in '/Users/...../my-react-app/src'
Codesandbox code - https://codesandbox.io/s/create-react-app-forked-5yxd8
UPDATE: The sub-path used in import and the folder structure are different. In the above example, there won't be a folder named path1 or path2.
Look at the Next.JS React Framework. You can see that they use exactly the same approach as you have described. You can create a simple typescript application with their CLI tool like this:
npx create-next-app#latest --typescript
Then pay attention on imports used for instance in ./pages/index.tsx.
Then if you'll look into the ./node_modules/next/package.json you will see that they expose built files in two ways: actual code and type defs are inside ./node_modules/next/dist/* and their re-exports are right in ./node_modules/next/*.
At least this is a real-life example and a good place to start your experiments. It doesn't mean you have to learn the whole their codebase. You just need to mimic the essencial parts of their package.json file (https://github.com/vercel/next.js/blob/canary/packages/next/package.json), specifically main, types and files in your Typescript library.
Update
Just look where absent imports could be imported from:
As you might understand, those are the places, where corresponding *.d.ts files are placed. So you just need to create reexport files in the root folder of you library and mention them in 'files' property of your lib's package.json.
The exactly similar picture I have for my own library.
I think there is no other way to impement imports of your lib the way you want, except of having either reexports or original type definitions right in the lib's root folder
This block in my package.json worked for me:
{
// ...
"files": [
"/dist"
],
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": "./dist/index.js",
"./types": "./dist/types/index.js",
"./generate": "./dist/generate/index.js"
},
"typesVersions": {
"*": {
"types": [
"./dist/types/index.d.ts"
],
"generate": [
"./dist/generate/index.d.ts"
]
}
}
}
My tsconfig.json looks like this:
{
"extends": "#tsconfig/node14/tsconfig.json",
"include": ["src/**/*"],
"compilerOptions": {
"lib": ["es2020", "dom"],
"declaration": true,
"outDir": "dist",
"module": "ESNext"
}
}
And this is my file structure:
package.json
tsconfig.json
dist/ // and all its subfolders
src/
generate/
index.ts
types/
index.ts
index.ts
Separately, I'm using TypeScript 4.7.4. Supposedly the exports field is supported with this version, but it didn't work for me. But this (maybe overly complex) workaround worked for me.
As answered in How to create a local module in TypeScript:
Using module-alias package might solve your problem.
Add this configuration below into package.json:
"_moduleAliases": { "my-module":
"<your_build_folder>/modules/my-module" },
And this code on first line
of your main file (server.ts/index.ts)
import 'module-alias/register';

Creating custom absolute paths with create-react-app

I've created a React project with typescript using create-react-app version 3.4.1.
I'm trying to avoid the use of relative paths in my project. Here's a part of my project tree:
/
|_ public
|_ tests
|_ src
|____ Scenarios
|____ Components
|____c
What I basically want is to be able to to do something like import '#components/c'. I've tried to add this part to my tsconfig.json file:
{
"compilerOptions": {
...
"baseUrl": ".",
"paths": {
"*": ["src/*"],
"tests": ["tests/*"],
"public": ["public/*"],
"#components/*": ["src/Components/*"],
"#Scenarios/*": ["src/Scenarios/*"],
},
...
}
}
But every time I'm starting my app using yarn start my tsconfig deletes this part of my code (eveything but my "baseUrl" part). As far as I know since version 3 of react-create-app, solved this problem partially with enabling baseUrl property to affect the imports' root dir. But I couldn't find anywhere a working solution to set absolute paths from tsconfig path directory. The partial solution doesn't work for me as I'm probably going to import stuff from public directory.
I did try this solution from last year but it wouldn't work for me. Did anyone manage to get this or any other solution working?
Ideally the solution will enable me to still use create-react-app and not to use other packages but of course any solution would work.
you can do it with your solution by add tsconfig.extends.json and use craco or any library to custom webpack. This is my craco.config.js:
const path = require('path')
module.exports = {
webpack: {
alias: {
src: path.resolve(__dirname, './src/')
}
}
}

ReactJS - Module not found when specifying "paths" in jsconfig.json

Consider the following settings in jsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"#components/*": ["src/components/*"],
"#constants/*": ["src/constants/*"]
}
}
}
When I attempt to import app-constants.js file in my components through:
import AppConstants from "#constants/app-constants";
I seem to get the following error:
Module not found: Can't resolve '#constants/app-constants'
My app-constants.js file is located directly in the src/constants folder:
Any idea why this is happening?
EDIT
I Tried using this:
{
"compilerOptions": {
"baseUrl": "src"
},
"include": ["src"]
}
And works when calling directly onto the folders like constants/app-constants.js
But doesn't when I try the first method.
It would be great if someone is able to enlighten me of my mistakes.
Your code looks good and you can verify it by intellisense e.g:
import AppConstants from "#constants/";
it will show app-constants in intellisense.
Now the problem is that react is not supporting aliases yet, but will support very soon.
I don't know if we will add support for aliases anytime soon. I
personally don't have time to work on it right now. I think the
current options with setting the baseUrl to . or src is sufficient for
tackling the struggles with relative imports. Beyond that it's just
personal preference like using # instead of src as prefix.
https://github.com/facebook/create-react-app/issues/7795

Resources