How do I configure absolute paths for imports in TypeScript based React Native apps?

前端 未结 5 1948
生来不讨喜
生来不讨喜 2020-12-29 07:27

In order to avoid \'../../../../\' style relative imports in a TypeScript based React Native app, I would like to configure the app so that I can use absolute imports instea

相关标签:
5条回答
  • 2020-12-29 08:15

    Requirement

    // Meh
    import config from '../../../../../../../config';
    
    // Awesome!
    import config from '@cuteapp/config';
    

    How To

    1. Add this babel plugin package
    yarn add --dev babel-plugin-module-resolver
    
    1. My babel.config.js
    module.exports = {
      presets: ['module:metro-react-native-babel-preset'],
      plugins: [
        [
          require.resolve('babel-plugin-module-resolver'),
          {
            cwd: 'babelrc',
            extensions: ['.ts', '.tsx', '.js', '.ios.js', '.android.js'],
            alias: {
              '@cuteapp': './app'
            }
          }
        ],
        'jest-hoist'
      ]
    };
    
    1. My tsconfig.json
    {
      "compilerOptions": {
        "allowJs": true,
        "allowSyntheticDefaultImports": true,
        "esModuleInterop": true,
        "isolatedModules": true,
        "jsx": "react",
        "lib": ["es2015", "es2015.promise", "es2016.array.include", "dom"],
        "strict": true,
        "moduleResolution": "node",
        "baseUrl": "./",
        "paths": {
          "@cuteapp/*": ["app/*/index", "app/*"]
        },
        "noEmit": true,
        "resolveJsonModule": true,
        "target": "esnext",
        "types": ["jest"]
      },
      "exclude": ["node_modules", "babel.config.js", "metro.config.js"]
    }
    
    1. That's it.
    0 讨论(0)
  • 2020-12-29 08:25

    Summary:

    The npm package babel-plugin-module-resolver is needed, as well as some configuration in tsconfig.json and babel.config.js


    Step by step:

    1. npm install babel-plugin-module-resolver (or yarn add babel-plugin-module-resolver)

    2. tsconfig.json: Add "baseUrl": "." to compilerOptions

    3. babel.config.js: Add a key named plugins with the following value:

    [
        [
          'module-resolver',
          {
            extensions: [
              '.js',
              '.jsx',
              '.ts',
              '.tsx',
              '.android.js',
              '.android.tsx',
              '.ios.js',
              '.ios.tsx'
            ],
            root: ['.']
          }
        ]
      ]
    

    Complete configuration:

    tsconfig.json:

    {
      "compilerOptions": {
        "allowJs": true,
        "allowSyntheticDefaultImports": true,
        "esModuleInterop": true,
        "isolatedModules": true,
        "jsx": "react",
        "lib": ["es6"],
        "moduleResolution": "node",
        "noEmit": true,
        "strict": true,
        "target": "esnext",
        "baseUrl": "."
      },
      "exclude": ["node_modules", "babel.config.js", "metro.config.js", "jest.config.js"]
    }
    

    babel.config.js:

    module.exports = {
      presets: ['module:metro-react-native-babel-preset'],
      plugins: [
        [
          'module-resolver',
          {
            extensions: [
              '.js',
              '.jsx',
              '.ts',
              '.tsx',
              '.android.js',
              '.android.tsx',
              '.ios.js',
              '.ios.tsx'
            ],
            root: ['.']
          }
        ]
      ]
    };
    
    

    This is for a clean new project created using npx react-native init MyTestApp --template typescript on React Native version 0.60.5

    0 讨论(0)
  • 2020-12-29 08:27

    You can solve it using 5 simple steps withou eject:

    Step 1: Adding react-app-rewired into your devDependencies.

    yarn add -D react-app-rewired or npm intall react-app-rewired --save-dev

    Step 2: After installation, you'll be able to change package.json default ReactsJS scripts to:

    "scripts": {  
      "start": "react-app-rewired start",  
      "build": "react-app-rewired build",  
      "test": "react-app-rewired test",  
      "eject": "react-app-rewired eject" 
    }
    

    Step 3: Creates a new file called tsconfig.paths.json on root path, with content like:

    {
      "compilerOptions": {
        "baseUrl": ".",
        "paths": {
          "services/*": ["./src/shared/services/*"],
          "interfaces/*": ["./src/shared/interfaces/*"]
        }
      }
    }
    

    Tip 1: you can choose which path you want to use, like: @services, @interface, @src, ~, @, etc just by changing the keys inside "paths": {}

    The same is applied to it's value: ["src/shared/services/"], ["src/shared/interfaces/"], ["src/*"], use the relative path here.

    Step 4: Into tsconfig.json, before "compilerOptions" you need to extends the tsconfig.paths.json you just created.

    Like this:

    {
      "extends": "./tsconfig.paths.json",
      ...//rest of file infos compilerOptions, include... whatever
    }
    

    Step 5: Creates a new file config-overrides.js, adding your alias and relative paths on it:

    const path = require('path');
    
    module.exports = function override(config) {
      config.resolve = {
        ...config.resolve,
        alias: {
          ...config.alias,
          'services': path.resolve(__dirname, 'src/shared/services'),
          'interfaces': path.resolve(__dirname, 'src/shared/interfaces')
        },
      };
    
      return config;
    };
    

    Tip 2: If you're using eslint, remember to have an .eslintignore file and add config-overrides.js within it.

    Restart your IDE or text editor, in my case VSCode.

    It's DONE!. Now just run yarn start or npm run start

    0 讨论(0)
  • 2020-12-29 08:30

    All of the other answers didn't work for me with a freshly created React Native + Typescript project.

    What worked for me was setting both baseUrl and paths in tsconfig.json:

    {
        "baseUrl": ".",
        "paths": {
          "NAME_IN_PACKAGE_JSON/*": ["./*"]
        }
    }
    

    Replace NAME_IN_PACKAGE_JSON with your package.json's name field. E.g. if the name field is myapp you can do:

    import HomeScreen from "myapp/screens/HomeScreen";

    0 讨论(0)
  • 2020-12-29 08:32

    For anyone who uses TypeScript and just wants to use import with absolute paths without aliases.

    Assuming all of your code folders are inside of src.

    Insert "baseUrl": "src" in compilerOptions object inside tsconfig.json.

    Now you can use absolute paths in imports.

    0 讨论(0)
提交回复
热议问题