Create React App: import modules using aliases with Webpack and Typescript
Tags: react, typescript, webpack, wavelop
Published: 2020-08-28 13:53:07

You can find the code of this tutorial [here](https://github.com/Wavelop/cra-with-module-alias), and follow the guide, step by step, in this [PR](https://github.com/Wavelop/cra-with-module-alias/pull/1).

You can take a look at a demo [here](https://cra-module-import-aliasing.web.app/).

## Initialize project using Create React App

Execute the following commands:

```
npx create-react-app cra-with-module-alias --template typescript
cd cra-with-module-alias
```

## Setup the environment and install dependencies

Execute:

```
npm run eject
```

To the below question, answer with `yes`:

```
? Are you sure you want to eject? This action is permanent.
```

You will have the following structure:

```
cra-with-module-alias
├── README.md
├── node_modules
├── package.json
├── package-lock.json
├── .gitignore
├── config
│   ├── webpack.config.js
│   ├── ...
│   └── Other folder and files
├── scripts
│   ├── build.js
│   ├── start.js
│   └── test.js
├── public
│   ├── favicon.ico
│   ├── index.html
│   ├── logo192.png
│   ├── logo512.png
│   ├── manifest.json
│   └── robots.txt
└── src
    ├── App.css
    ├── App.tsx
    ├── App.test.tsx
    ├── index.css
    ├── index.tsx
    ├── logo.svg
    ├── react-app-env.d.ts
    ├── serviceWorker.ts
    └── setupTests.ts
```

Install the dependencies:

```
npm i
```

## Create the architecture folders

Create the following folders inside the **src** one:

- **assets**;
- **components**;
- **pages**;
- **services**.

and inside of all of these folders, create an `index.ts` file. 
Inside of every `index.ts` file, we are going to **export the contained subfolders**. The syntax that we are going to use will be something like:

```javascript
export { default as ComponentName } from "./ComponentName/ComponentName";
```

## Update Webpack configuration to use aliases instead of relative paths

Add to **[config/webpack.config.js](https://github.com/Wavelop/cra-with-module-alias/blob/master/config/webpack.config.js)** file - in particular in the **[resolve.alias](https://github.com/Wavelop/cra-with-module-alias/blob/master/config/webpack.config.js#L291)** variables of the return object - the following lines:

```javascript
// config/webpack.config.js
...
module.exports = {
    ...
    resolve: {
      ...
      alias: {
        ...
        'Assets': path.resolve(__dirname, '../src/assets/'),
        'Components': path.resolve(__dirname, '../src/components/'),
        'Pages': path.resolve(__dirname, '../src/pages/'),
        'Services': path.resolve(__dirname, '../src/services/'),
      },
      ...
    },
    ...
};
```

in this way we are able to do inside every component:

```javascript
import { ComponentName } from 'Components';
import { ServiceName } from 'Services';
...
```

## Update Typescript configuration to use aliases instead of relative paths

The second step, to use **aliasing**, is to update the **Typescript configuration**. Add to **[tsconfig.json](https://github.com/Wavelop/cra-with-module-alias/blob/master/tsconfig.json)** file the following lines:

```json
// tsconfig.json
{
  "compilerOptions": {
    ...
    "baseUrl": "./",
    "paths": {
      "Assets": [ "src/assets"],
      "Components": [ "src/components"],
      "Pages": [ "src/pages"],
      "Services": [ "src/services"],
    }
  },
  ...
}
```

in this way, the Typescript compiler will be able to **resolve paths**.

## Reorganize the files

Now we are going to re-organize the file generated by the `npm run eject` command.

Starting from the **assets** folder, we move **logo.svg** inside a new **images** folder. And inside the index file, we export the file:

```javascript
export { default as Logo } from './images/logo.svg';
```

Now, for components, we move the **App.css**, **App.tsx** and **App.test.ts** inside a new folder called **App**. 
Inside **App/App.tsx** file we update the import line `import logo from './logo.svg';` in `import { Logo as logo } from 'Assets';`.

And inside the index file, we export the file:

```javascript
export { default as Logo } from './images/logo.svg';
```

In the end, we need to update `src/index.tsx` as the following:

```javascript
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import { App } from 'Components'; // <-- New way to import Components
import * as serviceWorker from './serviceWorker';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
```

## Update config in package.json for running test via Jest

To execute the test with modules as aliases, we need to update the jest configuration in `package.json` as follow: 

```json
// package.json
{
  ...
  "jest": {
    ...
    "moduleDirectories": [
      ".",
      "src",
      "node_modules"
    ],
    "moduleNameMapper": {
      ...
      "^Assets(.*)$": "<rootDir>/src/assets/$1",
      "^Components(.*)$": "<rootDir>/src/components/$1",
      "^Pages(.*)$": "<rootDir>/src/pages/$1",
      "^Services(.*)$": "<rootDir>/src/services/$1"
    },
  }
}
```

## Visual Studio Code Tips

Using Visual Studio Code as editor, you can get component names via **autocomplete** using `CTRL+Space` (or using your combinations).

![Visual Studio Code](https://dev-to-uploads.s3.amazonaws.com/i/jvyg5usb1b4ma6a3cdlz.gif)

## Reference

- https://reactjs.org/docs/create-a-new-react-app.html
- https://create-react-app.dev/
- https://create-react-app.dev/docs/available-scripts#npm-run-eject
- https://www.typescriptlang.org/
- https://webpack.js.org/configuration/resolve/
- https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping

## Conclusion

Doing these simple steps you will be able to forget the relative paths and make your folders structure more flexible to the changes. 

You can find the code of this tutorial [here](https://github.com/Wavelop/cra-with-module-alias), and follow the guide, step by step, in this [PR](https://github.com/Wavelop/cra-with-module-alias/pull/1).

You can take a look at a demo [here](https://cra-module-import-aliasing.web.app/).

If you have questions, please write to us an email to [info@wavelop.com](mailto:info@wavelop.com).

Originally published at https://wavelop.com/en/story/create-react-app-module-import-path-aliasing-with-webpack-typescript/ on August 28, 2020.

## Credits

- <span>Photo by <a href="https://unsplash.com/@camwitney?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Cameron Witney</a> on <a href="https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></span>
- <a href='https://www.freepik.com/vectors/light'>Light vector created by stories - www.freepik.com</a>