Skip to content

🏷️ Alias and multiple src directory for rewired create-react-app

License

Notifications You must be signed in to change notification settings

mryhchan/react-app-rewire-alias

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

68 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Alias solution for rewired create-react-app

This is more than simple alias. This is also a multi-project src directory. Currently, create-react-app (CRA) does not support more than one src directory in the project. Monorepo, multi-repo and library projects with examples require more than one directories like src.

This is merely an alias and multi-source solution for CRA and this is not a replacement for multi-package management tools like Lerna.

This requires to modify the CRA webpack configuration in runtime (without ejecting) and works with one of:

Npm package Npm downloads Dependency Status Dependency Status Dependency Status

This allows:

  • quality and secure exports from outside src
  • absolute imports
  • any ./directory at root outside of src with Babel and CRA features

This is designed for:

  • monorepo projects
  • multi-repo projects
  • library projects with examples

Advantages over other solutions:

  • provided fully functional aliases and allows the use of Babel, JSX, etc. outside of src (outside of root see section below)

  • provided fully secure aliases and uses the same module scope plugin from the original create-react-app package for modules (instead of removing it), to minimize the probability of including unwanted code

Installation

yarn add --dev react-app-rewired react-app-rewire-alias

or

npm install --save-dev react-app-rewired react-app-rewire-alias

Usage

Current create-react-app and react-scripts v4.0 has a bug which is fixed here: create-react-app #9921 - but it does released yet. Use previous version of create-react-app/react-scripts or wait for new release or check commit referenced in #9 to learn how make it worked using patch-package.

Place for alias foldes is recommended near to src. Alias folders outside of the root of project is not recommended.

There two approach to configure: simple - only with js projects. Another is with ts/js config - for both js and typescript projects.

The simple way is just configure create-app-rewired (see below or its docs) and create config-overrides.js like this:

const {alias, aliasJest} = require('react-app-rewire-alias')

const aliasMap = {
  example: 'example/src',
  '@library': 'library/src',
}

module.exports = alias(aliasMap)
module.exports.jest = aliasJest(aliasMap)

Using with ts/js config includes these steps:

  • configure create-app-rewired if not yet (short brief below)
  • modify config-overrides.js to add react-app-rewire-alias
  • add extends section to jsconfig.json or tsconfig.json
  • configure alias in jsconfig.paths.json or tsconfig.paths.json

Modify config-overrides.js to add react-app-rewire-alias

const {alias, aliasJest, configPaths} = require('react-app-rewire-alias')

const aliasMap = configPaths('./tsconfig.paths.json')

module.exports = alias(aliasMap)
module.exports.jest = aliasJest(aliasMap)

Add extends section to jsconfig.json or tsconfig.json

The paths section must not be configured directly in jsconfig.json or tsconfig.json but in separated extends file.

Specify extends section

// jsconfig.json or tsconfig.json
{
  "extends": "./tsconfig.paths.json", // or "./tsconfig.paths.json"
  "compilerOptions": {
    // ...
  }
}

Configure alias in jsconfig.paths.json or tsconfig.paths.json

Create separated file jsconfig.paths.json or tsconfig.paths.json, like this:

// jsconfig.paths.json or tsconfig.paths.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "example/*": ["example/src/*"],
      "@library/*": ["library/src/*"]
    }
  }
}

Using react-app-rewired

Integrating react-app-rewired into your project is very simple (see its documentation): Create config-overrides.js mentioned above in the project's root directory (the same including the package.json and src directory) and rewrite the package.json like this:

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

That is all. Now you can continue to use yarn or npm start/build/test commands as usual.

Using craco

// craco.config.js

const {CracoAliasPlugin, configPaths} = require('react-app-rewire-alias')

module.exports = {
  plugins: [
    {
      plugin: CracoAliasPlugin,
      options: {alias: configPaths('./tsconfig.paths.json')}
    }
  ]
}

Or for dangerious mode (see outside of root section):

- const { CracoAliasPlugin, configPaths } = require('react-app-rewire-alias');
+ const { CracoAliasPlugin, configPaths } = require('react-app-rewire-alias/lib/aliasDangerous');

API

  • alias(aliasMap)(webpackConfig)

The function alias() accepts aliases declared in form:

{
  example: 'example/src',
  '@library': 'library/src',
}

To make all things worked, aliases must be declared in jsconfig.json or tsconfig.json. However it must beclared in separated extends file (see section Workaround for "aliased imports are not supported" below)

The result is function which modify wepack config

  • configPaths()

The function configPaths() loads paths from file compatible with jsconfig.json or tsconfig.json and returns path in form acceptable for alias() function. The tsconfig.json is prioritized over the jsconfig.json in loading sequence.

  • extendability

As any react-app-rewire or customize-cra rewire extension this can be integrated with another:

module.exports = function override(config) {
  const modifiedConfig = alias(...)(config)
  ...
  return someElse(modifiedConfig)
}
module.exports.jest = function override(config) {
  const modifiedConfig = aliasJest(...)(config)
  ...
  return modifiedConfig
}

Workaround for "aliased imports are not supported"

CRA overwrites your tsconfig.json at runtime and removes paths from the tsconfig.json, which is not officially supported, with this message:

The following changes are being made to your tsconfig.json file:
  - compilerOptions.paths must not be set (aliased imports are not supported)

The suggested workaround is to move the paths to a different .json file, e.g. tsconfig.paths.json, like this:

/* tsconfig.paths.json */
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "example/*": ["example/src/*"],
      "@library/*": ["library/src/*"]
    }
  }
}

with that file's subsequent inclusion in the tsconfig.json using extends:

/* tsconfig.json */
{
  "extends": "./tsconfig.paths.json"
}

Outside of root

The base alias implementation supports aliases near src and in src directory. It provides aliases with same feature set as original create-react-app. As far create-react-app does not supports aliases and additional src-like directories as it does not supports aliases outside of the root project directory.

Aliases outside or project root directory may be implemented with some limitation of feature set. That is solved by disabling ESLint checking.

This mplementation is moved to separated code set named aliasDangerous to be not confused with alias. To use it husr replace import like this:

- const {alias, configPaths, CracoAliasPlugin} = require('react-app-rewire-alias')
+ const {aliasDangerous, configPaths, CracoAliasPlugin} = require('react-app-rewire-alias/lib/aliasDangerous')

And replace alias with aliasDangerous:

module.exports = function override(config) {
  aliasDangerous({
    ...configPaths('tsconfig.paths.json')
  })(config)

  return config
}

Tips

  • keep only one node_modules directory

Confusions in deps versions may bring unclear errors or problems. For example application is not working without any error. Or another example is error in react-router - <Route> component do not see <Router> when actually code is correct and it falls with:

should not use Route or withRouter() outside a Router

This may be a result of some confusions in node_modules folders of multirepo projects. Same take place in plain create-react-app if some how one or more additional node_modulest directory appers in src.

To avoid this problems use only one main project node_modules directory.

  • keep away from working with nested project

Default bundler configuration doesn't assume your configuration and may mix deps from node_modules from different projects (top project and nested project) so this may bring mentioned above confusions with deps versions. To avoid problems: do not install and run within nested project directly when it is nested or integrated in another one - but only independent toplevel configuration Or consider to eject or configure webpack manually.

  • do not relay to deps versions synchronization

Some libraryes uses instanceof and other type comparisions. For example two objects created with same params in same code of same library version but installed in differenent node_modules and bundled separately - will mostly have same data and same behaviour but differen instance type. Such libraries will be unable to recognize its own objects and will lead to unpredictable behaviour. So use only one main project node_modules directory.

About

🏷️ Alias and multiple src directory for rewired create-react-app

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • JavaScript 42.4%
  • TypeScript 25.7%
  • HTML 20.7%
  • CSS 11.2%