Here is my test file
// /imports/components/main.test.js
import React from 'react'
import { shallow, mount } from 'enzyme'
import Main from './main'
import TextInput from "/imports/ui/textInput"
...
and the main.js has
// /imports/components/main.js
import { action1 } from "/imports/actions/myAction"
but it throws an error when I run the test, saying
Cannot find module '/imports/actions/myAction' from 'main.js'
If I comment the import './main', same thing happen with importing TextInput. I have no issue with importing modules in node_modules.
How can I tell Jest or webpack to import the component using absolute path from project directory (i.e import Foo from /imports/...)?
Better way to solve relative path import issue, is by creating jsconfig.json file adjacent to package.json file.
{
"compilerOptions": {
"baseUrl": "src"
}
}
then import { action1 } from "actions/myAction"; will work
If you're using Create React App, you can set up the absolute imports path in a jsconfig.json (need to create in a fresh JavaScript template) or tsconfig.json (already created in the TypeScript template) at the root of your project to serve your usage.
Example:
{
"compilerOptions": {
"baseUrl": "src"
},
"include": ["src"]
}
Official docs: https://create-react-app.dev/docs/importing-a-component/#absolute-imports
Another solution is to create an .env file within the root directory of your project.
Within it you will add NODE_PATH=src/
Thats all
Save the file and restart your dev environment in terminal.
Afterwards, you will go through your project and update some import statements accordingly.
My file structure follows exactly the same pattern as yours. To teach Jest into using imports beginning with a /, I use babel-plugin-module-resolver and its handy root option. My .babelrc for Jest looks like this:
{
"presets": ["es2015", "meteor"],
"plugins": [
"transform-class-properties",
"transform-react-constant-elements",
"transform-react-inline-elements",
"transform-react-remove-prop-types",
["module-resolver", {
"root": ["../"],
"alias": {
"react-router-dom": "react-router-dom/umd/react-router-dom.min.js",
"redux": "redux/dist/redux.min.js",
"react-redux": "react-redux/dist/react-redux.min.js"
}
}]
]
}
As I'm using Meteor which customized its root imports, I hide my Jest usage and configuration into a .jest directory at the root of my repository allowing me to have a specific .babelrc without risking conflicts with Meteor's one.
With webpack(v4) and babel, you can provide absolute paths in your directory.
Follow these steps
In your .babelrc file, make this entry for plugins.Make sure you have babel-plugin-root-import in your package.json as well.
"plugins": [
[
"babel-plugin-root-import",
{
"paths": [
{
"rootPathPrefix": "~",
"rootPathSuffix": "./"
},
{
"rootPathPrefix": "#src",
"rootPathSuffix": "src"
},
{
"rootPathPrefix": "#any-other-folder",
"rootPathSuffix": "src/client/../any-other-folder"
}
]
}
]
]
Now if you run into eslint issue, you can add these lines in your eslintrc:
"settings": {
"import/resolver": {
"babel-plugin-root-import": [
{
"rootPathPrefix": "#src",
"rootPathSuffix": "src"
},
{
"rootPathPrefix": "#any-other-folder",
"rootPathSuffix": "src/client/../any-other-folder"
}
]
}
}
Now to make your editor recognize these paths, you can create this entry in jsconfig file.
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"~/*": ["/*"],
"#src/*": ["src/*"],
"#any-other-folder/*": ["src/client/../any-other-folder/*"] ==> absolute path to any other folder
}
},
"exclude": ["node_modules"]
}
Hope these entries help.
I had jest configs in package.json file (under "jest" key). So I just have added there this row:
"modulePaths": ["<rootDir>/src/"]
And this works for me. I hope it can help somebody else.
Related
I was able to import modules using # but I upgraded a few components including react and nextjs.
this used to work
import { ValidateProps } from '#/api-lib/constants';
Now getting error:
Module not found: Can't resolve '#/api-lib/constants'
It works if I give it a path
import { ValidateProps } from '../../api-lib/constants';
Personally, I use a jsconfig.json file. It contains:
{
"compilerOptions": {
"baseUrl": "src"
},
"include": ["src"]
}
Then I am able to import like so:
import Loadable from "components/ui/Loadable";
I just figured I no longer had jsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"#/api-lib/*": ["api-lib/*"],
}
}
}
I'm struggling to get absolute path to work in a Vite react-ts project.
Here's how I created the project
npm init #vitejs/app
npx: installed 6 in 1.883s
√ Project name: ... test-vite
√ Select a framework: » react
√ Select a variant: » react-ts
Then I added baseUrl to tsconfig.json
based on the TS official doc:
{
"compilerOptions": {
"baseUrl": "./src",
...
followed by adding a simple component (T:\test-vite\src\components\Test.tsx)
import React from "react";
const Test = () => <h1>This is a Test.</h1>;
export default Test;
Finally I import the Test component in App.tsx
but it won't let me use absolute path:
import Test from "components/Test";
I get this error
whereas if I use relative path, the app works in dev & build mode without any error:
import Test from "./components/Test";
How can I make absolute path work in the project?
There are two problems here:
Tell typescript how to resolve import path
Tell vite how to build import path
You only tell typescript how to resolve, but vite don't konw how to build. So refer to the official document resolve.alias, maybe this is what you want:
// vite.config.ts
{
resolve: {
alias: [
{ find: '#', replacement: path.resolve(__dirname, 'src') },
],
},
// ...
}
You can import path like this (or any module under ./src):
import Test from "#/components/Test";
import bar from "#/foo/bar"
Moreover, you can use vite plugin vite-tsconfig-paths directly, it makes you don't have to manually configure resolve.alias
Follow the instructions below:
Install vite-tsconfig-paths as dev dependency
Inject vite-tsconfig-paths using the vite.config.ts module
import { defineConfig } from 'vite'
import tsconfigPaths from 'vite-tsconfig-paths'
export default defineConfig({
plugins: [tsconfigPaths()],
})
I came here through search results, I was looking for something different, namely, how to do a simple absolute import like import { foo } from 'src/lib/foo.ts'
So if you have a /src directory that contains all code and want to use an absolute import path.
vite.config.ts
export default defineConfig({
...
resolve: {
alias: {
src: path.resolve('src/'),
},
}
})
tsconfig.json
{
"compilerOptions": {
...
"baseUrl": "./"
}
}
Note that this is a trick: src is an alias, so it appears like the path is absolute in Vite. If you have another directory in the root dir, adjacent to /src, you will need to add another alias for that directory.
#Yuns solutions works, but it shows error in vscode. And it was breaking auto-import in vs code.
To make it work in vscode and vite both, I added alias in both tsconfig and vite.config.
// tsconfig.json
{
"paths": {
"#/*": ["src/*"]
}
// ...
}
// vite.config.ts
{
resolve: {
alias: [{ find: '#', replacement: '/src' }],
},
// ...
}
Then, I could import like below (svelte app is in src directory)
import Header from '#/components/Header.svelte
Looking for import {...} from "src/foo/bar";?
I also came here through search results like user Maciej Krawczyk, but the # part also wasn't what I was interested in. That user's answer helped me, but I had trouble with the path.resolve part (ReferenceError because path wasn't defined), so I used a slightly different approach:
vite.config.ts
export default defineConfig({
...
resolve: {
alias: {
src: "/src",
},
},
...
})
Vite's resolver considers the absolute path /src to be from where the server is serving (see GH issue). So if you're running/building from the root of your project with src as a top level directory -- which is pretty common -- this alias points Vite in the right direction.
tsconfig.json
{
"compilerOptions": {
...
"baseUrl": "./",
"paths": {
"src/*": [
"./src/*"
]
}
}
}
This is basically blindly following this StackOverflow answer. TypeScript needs to know that we have special resolving going on as well, otherwise TS will be freaked out about your non-existent src package and not know where it should go looking. (Note: After I changed my TS config, VSCode didn't immediately pick up the change, so I was still getting warnings. I quit, re-opened, and had to wait ~15sec for the warnings to go away.)
1) You need to install these packages:
npm i path
yarn add path
npm i #types/node
yarn add #types/node
npm i vite-tsconfig-paths
yarn add vite-tsconfig-paths
2) Then in the vite.config file:
import { defineConfig } from 'vite';
import react from '#vitejs/plugin-react';
import tsconfigPaths from 'vite-tsconfig-paths';
import path from 'path';
export default defineConfig({
base: './',
resolve: {
alias: {
Components: path.resolve(__dirname, './src/components'),
Assets: path.resolve(__dirname, './src/assets'),
},
},
plugins: [react(), tsconfigPaths()],
});
3) And now we have to tell TS those same paths that we defined in the alias:
{
"compilerOptions": {
...,
"baseUrl": "./",
"paths": {
"src/*": [ "./src/*" ],
// We define this path for all files/folders inside
// components folder:
"Components/*": [ "./src/components/*" ],
// We define this path for the index.ts file inside the
// components folder:
"Components": [ "./src/components" ],
"Assets/*": [ "./src/assets/*" ],
"Assets": [ "./src/assets" ]
}
},
...
}
4) reload vscode: As the comment above said, press Fn1 and type "reload with extensions disabled", re-enabling extensions from the popup.
Now try to import
import Test from "components/Test";
it should work.
For anyone looking specifically to add the nice import "#/something-in-src" syntax like Vue has with the latest (as of posting this answer) version of Vite + React + TypeScript, here's how I did it:
Make sure #types/node is installed as a dev dependency. This didn't come with the latest version of Vite for me, and it will make "path" and __dirname throw an undefined error.
vite.config.ts
import { defineConfig } from "vite";
import react from "#vitejs/plugin-react";
import path from "path";
// https://vitejs.dev/config/
export default defineConfig({
resolve: {
alias: [{ find: "#", replacement: path.resolve(__dirname, "src") }],
},
plugins: [react()],
});
tsconfig.json
Add:
{
"compilerOptions": {
"paths": {
"#/*": ["./src/*"]
}
}
}
For anyone who stucks after all required changes, you need to reload vscode.
My config files:
tsconfig.json
"baseUrl": "./",
"paths": {
"#/*": ["src/*"]
}
vite.config.ts
import { defineConfig } from 'vite';
import react from '#vitejs/plugin-react';
import path from 'path';
// https://vitejs.dev/config/
export default defineConfig({
resolve: {
alias: { '#': path.resolve(__dirname, './src') },
},
plugins: [react()],
});
In above code you need to have 2 libraries installed:
'path': npm i path
'#types/node': npm i #types/node
After configure your project files you need to reload vscode. To do that press ctrl + P and type ">reload with extensions disabled", after that you will get popUp to activate extensions again click it, and your absoulte path should work
If someone installed vite-tsconfig-paths library, you also need to reload the vscode, remember to import given library to vite.config.ts
export default defineConfig({ plugins: [react(), tsconfigPaths()] });
With package you get default 'components/File' import instead of '#components/File' import.
I have created an app by Create React App and to be more specific I'm also using typescript.
I can't figerout how to set absolute paths to access to my components, pages, etc..
In a different scenario I would update my tscongig with something like:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"#components/*": ["src/components/*"]
}
}
}
but I have no idea how to implement this as I'm using react-scripts
any idea?
Create a tsconfig.json file and add the code below.
{
"compilerOptions": {
"baseUrl": "src"
},
"include": [
"src"
]
}
Then you can import your components as
import Header from 'components/Header';
You should be able to use the same approach if create a jsconfig.json file in your solution, which supports the same baseUrl and rootPath properties as tsconfig.
Alternative is adding an .env file in your solution with the following line:
NODE_PATH=src/
Also, apart from the env file add this to your jsconfig.json
{
"rootDir": "src",
"compilerOptions": {
"baseUrl": "src",
"paths": {
"*": ["*"]
}
}
}
This should resolve both the compiler being able to find your absolute imports, and linter handling them properly.
See Building Your App / Importing a Component / Absolute Imports in the Create React App docs.
You can configure your application to support importing modules using absolute paths. This can be done by configuring a jsconfig.json or tsconfig.json file in the root of your project. If you're using TypeScript in your project, you will already have a tsconfig.json file.
Below is an example jsconfig.json file for a JavaScript project. You can create the file if it doesn't already exist:
{
"compilerOptions": {
"baseUrl": "src"
},
"include": ["src"]
}
If you're using TypeScript, you can configure the baseUrl setting inside the compilerOptions of your project's tsconfig.json file.
Now that you've configured your project to support absolute imports, if you want to import a module located at src/components/Button.js, you can import the module like so:
import Button from 'components/Button';
I'm having issues setting up an React project with yarn workspaces and typescript.
My folder structure is:
-root
-package.json
-workspaces
-web
-common
and my package.json file is:
{
"name": "my-project-name",
"private": true,
"workspaces": [
"workspaces/web",
"workspaces/common"
],
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx",
"json",
"node"
]
}
My issue is: when I import files on web from the common project, it works fine if it's a .js file, but fails with TypeError: Object(...) is not a function when using .ts or .tsx files.
Any ideas on what I might be missing?
I recommend adopting the following file hierarchy:
- root
- package.json
- tsconfig.json
- packages
- common
- package.json
- tsconfig.json
- services
- web
- package.json
- tsconfig.json
Everything in the packages folder can be imported. Services are "leaf" projects that you don't want to import in other projects.
With that as a base, your root package.json should be setup like that:
{
"name": "my-project-name",
"private": true,
"workspaces": [
"packages": [
"packages/*",
"services/**/*"
],
],
}
Then, you also need to tell typescript how to resolve the imports.
In the root tsconfig.json, set the following:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"#myproject/*": ["packages/*/src"]
},
}
Make sure that every tsconfig extends this base with "extends": "../../tsconfig.json"
Inside web/package.json or any package that needs to import common, define common as a dependency:
{
[...]
"dependencies": {
"#myproject/common": "*",
}
}
Now if your common package.json has a name set to `"#myproject/common", you can import your code inside web with :
import { myUtilFunction } from "#myproject/common";
I would advise you to also use learn with a setup like this.
You will also need to modify a bit your build pipeline, since you're importing files inside /web that are outside the /web folder. For a more complete example, you can check out this repo: https://github.com/NiGhTTraX/ts-monorepo
I've been using create-react-app package for creating a react website. I was using relative paths throughout my app for importing components, resources, redux etc. eg, import action from '../../../redux/action
I have tried using module-alis npm package but with no success. Is there any plugin that I can use to import based on the folder name or alias i.e. an absolute path?
Eg., import action from '#redux/action' or import action from '#resource/css/style.css'
Create a file called .env in the project root and write there:
NODE_PATH=src
Then restart the development server. You should be able to import anything inside src without relative paths.
Note I would not recommend calling your folder src/redux because now it is confusing whether redux import refers to your app or the library. Instead you can call your folder src/app and import things from app/....
We intentionally don't support custom syntax like #redux because it's not compatible with Node resolution algorithm.
The approach in the accepted answer has now been superseded. Create React App now has a different way to set absolute paths as documented here.
To summarise, you can configure your application to support importing modules using absolute paths by doing the following:
Create/Edit your jsconfig.json/tsconfig.json in the root of your project with the following:
{
"compilerOptions": {
"baseUrl": "src"
},
"include": ["src"]
}
Once you have done this you can then import by specifying subdirectories of "src" (in the following example, components is a subdirectory of src) e.g.
import Button from 'components/Button'
We can use webpack 2 resolve property in the webpack config.
Sample webpack config using resolve :
Here component and utils are independent folder containing React components.
resolve: {
modules: ['src/scripts', 'node_modules'],
extensions: ['.jsx', '.js'],
unsafeCache: true,
alias: {
components: path.resolve(__dirname, 'src', 'scripts', 'components'),
utils: path.resolve(__dirname, 'src', 'scripts', 'utils'),
}
}
After that we can import directly in files :
import UiUtils from 'utils/UiUtils';
import TabContent from 'components/TabContent';
Webpack 2 Resolve Reference
After you try Ben Smith's solution above if you find eslint complains about importing absolute path add the following line to your eslint config:
settings: {
'import/resolver': {
node: {
paths: ['src'],
},
},
},
replace 'src' with your folder if you use your own boilerplate with your folder's name.
Feb 2010
Wasted about an hour on this.
An example is below:
Goal: Import App.css in HomePage.js
myapp\src\App.css
myapp\src\pages\HomePage.js
File: jsconfig.json
{
"compilerOptions": {
"baseUrl": "src"
}
}
File: src\pages\HomePage.js
import "App.css";
The alias solution for craco or rewired create-react-app is react-app-alias for systems as: craco, react-app-rewired, customize-cra
According docs of mentioned systems replace react-scripts in package.json and configure next:
react-app-rewired
// config-overrides.js
const {aliasWebpack, aliasJest} = require('react-app-alias')
const options = {} // default is empty for most cases
module.exports = aliasWebpack(options)
module.exports.jest = aliasJest(options)
craco
// craco.config.js
const {CracoAliasPlugin} = require('react-app-alias')
module.exports = {
plugins: [
{
plugin: CracoAliasPlugin,
options: {}
}
]
}
all
Configure aliases in json like this:
// tsconfig.paths.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"example/*": ["example/src/*"],
"#library/*": ["library/src/*"]
}
}
}
And add this file in extends section of main typescript config file:
// tsconfig.json
{
"extends": "./tsconfig.paths.json",
// ...
}
I am using babel-plugin-module-resolver for my project to resolve that problem.
babel-plugin-module-resolver also is the same as module-alis. So I think you should just resolve using module-alis problem.
Because you didn't tell us why using module-alis was fail? So i cant show you how to fix it.
Dont give up your solution while you dont know the reason!
in package.json file,
eject this code in the scripts object like this..
"scripts": {
"start": "node scripts/start.js",
"build": "node scripts/build.js",
"test": "node scripts/test.js --env=jsdom",
"eject": "NODE_PATH=src/ react-scripts eject"
},
this will enable the absolute path imports in your app
None of the answers worked for me. Some didn't work at all and others worked but the import was already inside src, for example:
import something from 'path/to/file'.
Whereas I wanted to be able to do:
import something from 'src/path/to/file'
Here is how I solved it:
tsconfig.json
{
"compilerOptions": {
// ...
"baseUrl": ".",
"rootDirs": [
"src"
]
},
"include": [
"src"
]
}