react typescript webpack starter

Start your react typescript project with manual webpack config in seconds

Flexible to control webpack, easy to deploy
Keywords: React Starter, Webpack, Typescript, React.js, Redux, Babel, jest, react-router, sass, redux-thunk, pm2

Created with by đŸ‘» Aldenn

Overview

React-Typescript-Webpack was config with React, Typescript and Webpack without CRA. Faster to start your next react project.


Quick Start

For Development:

  1. Clone this repo to your local machine using:

    git clone git@github.com:thaind97git/react-typescript-webpack.git
  2. Change the current working directory to the project:

    cd react-typescript-webpack
  3. Install dependencies:

    [ yarn or npm install ]
  4. At this point you can run npm run dev or yarn dev to run project with development mode

    Now, your browser will auto open at http://127.0.0.1:3000

For Production:

  1. Run command to build:

    [ yarn or npm run ] build
  2. Setup env for production mode by create new file .env.production

  3. Run project at build directory

    • Using pm2: [ yarn or npm run ] start-pm2
    • Run with terminal: [ yarn or npm run ] start

Features

  • React hook
  • Webpack 5
  • Typescript
  • Sass
  • Redux-thunk
  • Redux-saga
  • Jest
  • Axios
  • I18n
  • React-router
  • Alias
  • Hot reload
  • Eslint
  • Prettier and Husky

How to using

  • Router:

    • Create new feature at src/features/<feature-name/>

    • Create a route.ts inside src/features/<feature-name/> and export default an array match with rules:

      import { lazy } from 'react';
      const Component = lazy(() => import('./path-to-component'));
      
      export default [
        {
          /*
           * name of a route
           * using to apply key react when generate routes
           * required for declare
           */
          name: 'name',
          /*
           * path of route
           */
          path: '/path-name',
          /*
           * using as exact in react-router
           */
          exact: true,
          /*
           * dynamic render layout for each route
           * header: false -> route will auto hide header
           * if this rendered, don't need to declare
           * control this inside `src/store/slices/layoutSlice` with more section
           */
          layout: {
            header: false,
            footer: false,
          },
          /*
           * component rendered inside route
           */
          component: Component,
        },
      ];

      – You don’t need do anything else after create and modify route.ts because i’m using import-glob to auto import (check at webpack/webpack.common.js for plugin, src/router/index.ts and src/layouts/main/index.tsx for using).

      – If you don’t want to use auto import or using project with jest, just using the code that i’m commented. Because i’m not yet support auto import for jest.

  • Write new component

    • Create new folder at src/components/<component-name/>

    • Create an index.tsx and <any-name>.scss

      Don’t need import scss into component, It will already merged into App.scss after you restart server.

      – This is a feature by using import-glob (check at webpack/webpack.common.js for plugin and src/styles/App.scss for using)

      – You should use BEM to write css without conflict

  • Using i18n

    • Create new json file at src/locales/resources/<file-name/>.json

    • Add content follow this format into json file

      {
        "en": {
          "name": "Name"
        },
        "vi": {
          "name": "TĂȘn"
        }
      }
    • update src/locales/resources/index.ts like this:

      /*
       * you can use other name instead `user`
       * this name will be used as path to key
      */
      import user from './<file-name/>.json
      
      const mergeResource: IResource = {
        ..., // others json
        user
      };
    • Now inside any where, you can access to key like this:

        const { t } = useTranslation()
      
        t('user.name') will be render "Name" for `en` and "TĂȘn" for `vi`
  • Call API with axios

    import { getUser } from '@/apis/user.ts';
    import { setLoading } from '@/store/slices/appSlice';
    import { errorHandler } from '@/helpers/axios';
    
    const dispatch = useDispatch();
    
    // Use useCallback to memorize create func (just one time)
    const fetchUser = useCallback(async () => {
      try {
        // Star loading spinner
        dispatch(setLoading(true));
    
        // fetch user
        const resp = await getUser();
        console.log(resp);
      } catch (error) {
        // display toast when error
        errorHandler(error);
      } finally {
        // End loading spinner
        dispatch(setLoading(false));
      }
    }, []);
    
    useEffect(() => {
      // Trigger function
      fetchUser();
    }, [fetchUser]);

Tips

  • Go to .huskyinstall, remove comment at line 37 and run [yarn or npm install] again to apply run test when using git push origin [ branch ]
  • Go to config/@types/[any-file-name].d.ts to declare global type of typescript
  • Go to pm2/prod.json and change “name: react-webpack-typescript-starter ->[other-name]” to config pm2 app name
  • Go to components/spinner/index.tsx and modify jsx + css to use another loading

Carefully

  • Don’t create folder with the PascalCase. Because it will throw error when build prod at ubuntu. I will fix it later or happy if you have a PR to fix it.

    Module not found: Error: Can't resolve '@/path-to-pascal-case' in '/path-to-lower-case'

Other References

License

This project is licensed under the MIT license, Copyright (c) 2021 Aldenn.
For more information see LICENSE.md.

GitHub

https://github.com/thaind97git/react-typescript-webpack