React + Webpack + TypeScript Project Setup

React + Webpack + TypeScript Project Setup

React + Webpack + TypeScript Project Setup: Let's get React and TypeScript setup, its a lot easier than you think!

React + Webpack + TypeScript Project Setup: Let's get React and TypeScript setup, its a lot easier than you think!

TL;DR: Can’t possibly summarize this in a single sentence but there is a repo that you can fork which has all of the boilerplate setup.

Let’s Get Started!!

Firstly you will need to create a directory/repo for your project, once you have done this you will need to initialize the project. Run one of the following snippets in your terminal to do so:

//If you want to use npm 
npm init
//If you want to use yarn 🧶
yarn init

Just follow along with the prompts in the terminal, once the initialization is complete you should see a package.json file in the directory. If you don’t know what a package.json file is then this post is not for you, I would recommend that you play with React and npm more before continuing.

Add Some Dependencies 😵

The 3 dependencies that you’ll need are react, react-dom, and typescript which are all pretty straightforward, but you’ll also need 24 devDependencies.

To install the 3 dependencies run the following

//Optionally you can install styled-components
//npm
npm install react react-dom typescript
//yarn 🧶
yarn add react react-dom typescript

For this post, we’ll be using babel so you’ll need to install babel-loader, a couple of babel plugins, and some babel presets.

Something to note is that as of babel v7, babel ships with Typescript support so we don’t need a separate TypeScript loader 😃.

//npm
npm install babel-loader @babel/plugin-external-helpers @babel/plugin-proposal-class-properties @babel/plugin-proposal-object-rest-spread @babel/preset-env @babel/preset-react @babel/preset-typescript --save-dev
//yarn 🧶
yarn add babel-loader @babel/plugin-external-helpers @babel/plugin-proposal-class-properties @babel/plugin-proposal-object-rest-spread @babel/preset-env @babel/preset-react @babel/preset-typescript -D

Ok on to installing the testing specific devDependencies. We’ll be using Jest and Enzyme along with some enzyme specific dependencies.

//npm
npm install enzyme enzyme-adapter-react-16 enzyme-to-json jest ts-jest --save-dev
//yarn 🧶
yarn add enzyme enzyme-adapter-react-16 enzyme-to-json jest ts-jest -D

Ok just a couple more dependencies, obviously we need Webpack, Wepback plugins, and the types for the various dependencies

//npm
npm install @types/enzyme @types/enzyme-adapter-react-16 @types/jest @types/react @types/react-dom html-webpack-plugin source-map-loader webpack webpack-cli webpack-dev-server webpack-hot-middleware --save-dev
//yarn 🧶
yarn add @types/enzyme @types/enzyme-adapter-react-16 @types/jest @types/react @types/react-dom html-webpack-plugin source-map-loader webpack webpack-cli webpack-dev-server webpack-hot-middleware -D

Oof ok we’re done with the dependencies finally… 🎊

Webpack Config 🛠

You should be somewhat familiar with Webpack configs but all we’re doing is checking the mode and adjusting the config based on the environment mode (production or development). Since I’m using styled-components the only loader I need is babel-loader with the various plugins and presets, but if you have CSS in your project you’ll need a CSS loader.

const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = (env, { mode = 'development' }) => {
  const config = {
    mode,
    entry: {
      app: './src/index.tsx',
    },
    devtool: '',
    resolve: {
      extensions: ['.js', '.jsx', '.ts', '.tsx'],
    },
    module: {
      rules: [
        {
          test: /\.(js|jsx|tsx|ts)$/,
          exclude: /node_modules/,
          use: {
            loader: 'babel-loader',
            options: {
              presets: [
                '@babel/preset-env',
                '@babel/preset-react',
                '@babel/preset-typescript',
              ],
              plugins: [
                '@babel/plugin-external-helpers',
                'babel-plugin-styled-components',
                '@babel/plugin-proposal-class-properties',
                '@babel/plugin-proposal-object-rest-spread',
              ],
            },
          },
        },
      ],
    },
    output: {
      path: path.resolve(__dirname, 'dist'),
      filename: 'index.js',
      libraryTarget: 'umd',
      publicPath: '/dist/',
      umdNamedDefine: true,
    },
    optimization: {
      mangleWasmImports: true,
      mergeDuplicateChunks: true,
      minimize: true,
      nodeEnv: 'production',
    },
    plugins: [
      new webpack.DefinePlugin({
        'process.env.NODE_ENV': '"production"',
      }),
    ],
  };

  /**
   * If in development mode adjust the config accordingly
   */
  if (mode === 'development') {
    config.devtool = 'source-map';
    config.output = {
      filename: '[name]/index.js',
    };
    config.module.rules.push({
      loader: 'source-map-loader',
      test: /\.js$/,
      exclude: /node_modules/,
      enforce: 'pre',
    });
    config.plugins = [
      new webpack.DefinePlugin({
        'process.env.NODE_ENV': '"development"',
      }),
      new HtmlWebpackPlugin({
        filename: path.resolve(__dirname, 'dist/index.html'),
        template: path.resolve(__dirname, 'src', 'index.html'),
      }),
      new webpack.HotModuleReplacementPlugin(),
    ];
    config.devServer = {
      contentBase: path.resolve(__dirname, 'dist'),
      publicPath: '/',
      stats: {
        colors: true,
        hash: false,
        version: false,
        timings: true,
        assets: true,
        chunks: false,
        modules: false,
        reasons: false,
        children: false,
        source: false,
        errors: true,
        errorDetails: true,
        warnings: false,
        publicPath: false,
      },
    };
    config.optimization = {
      mangleWasmImports: true,
      mergeDuplicateChunks: true,
      minimize: false,
      nodeEnv: 'development',
    };
  }
  return config;
};

TypeScript Config 👨‍💻

Everything in the TypeScript configuration is opinionated, what I mean by that is that you can edit it to your heart’s content and it shouldn’t break your application, what I have in the repo is just what I like as some defaults. Just make sure that the tsconfig.json file is at the root of your project.

{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "jsx": "react",
    "module": "amd",
    "noImplicitAny": true,
    "outDir": "./dist/",
    "preserveConstEnums": true,
    "removeComments": true,
    "sourceMap": true,
    "target": "es6",
    "moduleResolution": "node",
    "strict": true,
    "alwaysStrict": true,
    "strictNullChecks": false,
    "downlevelIteration": true
  },
  "include": [
    "./src/"
  ],
  "exclude": [
    "node_modules"
  ]
}

Jest Config 🧪

The Jest configuration file is used to configure Jest, the testing framework that we’ll be using. Make sure to place the jest.config.json file at the root of your project. Again like the TypeScript config, this is opinionated so please feel free to change it, everything is pretty standard though: (We’ll talk about the setupEnzyme.js file a second)

{
  "roots": [
    "<rootDir>/src"
  ],
  "transform": {
    "^.+\\.tsx?$": "ts-jest"
  },
  "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(ts|tsx)$",
  "testPathIgnorePatterns": [
    "./src/__tests__/setupEnzyme.ts"
  ],
  "collectCoverageFrom": [
    "src/**/*.{js,jsx,ts,tsx}",
    "!/node_modules/"
  ],
  "moduleFileExtensions": [
    "ts",
    "tsx",
    "js",
    "jsx"
  ],
  "snapshotSerializers": [
    "enzyme-to-json/serializer"
  ],
  "setupFilesAfterEnv": [
    "<rootDir>/src/__tests__/setupEnzyme.ts"
  ],
  "moduleNameMapper": { 
    "\\.(css|less|scss|sass)$": "identity-obj-proxy" 
  }
}

Src 🚗

(These emojis mean nothing 😆)

At the root of your project, you’ll want to create a src directory where all of the project code will live. Inside of the src directory, we’ll have 3 directories, __tests__ this is where all of our tests will live (Some people are hella opinionated about where this lives, so it is really up to you), components obviously where your components live, and declerations this is where we will be putting the declaration files for our project. Of course, you can name these directories whatever you want and you can create other directories if you would like as well, this is just a suggested project architecture, just note that you may have to edit the various configurations if you don’t follow this architecture exactly.

Alongside these directories, we have 2 files, index.tsx, which is the entry point for the project, and index.html, which is the template html file used by the HtmlWebpack plugin.

Inside of the __tests__ directory, you’ll need to create a file named setupEnzyme.ts , this file is referenced in the jest.config.json and has a really simple config for Enzyme.

import * as Enzyme from 'enzyme';
import * as Adapter from 'enzyme-adapter-react-16';

Enzyme.configure({
  adapter: new Adapter()
});

Go ahead and create a simple component and use it in the project entry point ( index.tsx ) and run the following command in the terminal:

npx webpack-dev-server -open -colors -hot -mode development

A browser window should pop open and you should see your component (make sure you check your terminal for errors though)!

Yay, you’re done!!! 🍰

You have all you need to get your React TypeScript project up and running. If you want to access all of the source code you can go to the following github repo. If you want to suggest a change make a pull-request!

Why ReactJS is better for Web Application Development?

Why ReactJS is better for Web Application Development?

Web Application Development is the point of contact for a business in today's digital era. It is important to choose the right platform for Web Application Development to build a high end Web

Web Application Development is essential for a business in today’s digital era. Finding the right platform for Web Application Development is important for building an effective Web Application that can enhance the overall customer engagement. Here’s what makes ReactJS a better option for building your next Web Application.

Mobile App Development Company India | Ecommerce Web Development Company India

Mobile App Development Company India | Ecommerce Web Development Company India

Best Mobile App Development Company India, WebClues Global is one of the leading web and mobile app development company. Our team offers complete IT solutions including Cross-Platform App Development, CMS & E-Commerce, and UI/UX Design.

We are custom eCommerce Development Company working with all types of industry verticals and providing them end-to-end solutions for their eCommerce store development.

Know more about Top E-Commerce Web Development Company

Hire PHP Developer and Web Developer for your Online Business

Hire PHP Developer and Web Developer for your Online Business

PHP is widely used open-source scripting language it helps in making dynamically easy your websites and web application. Mobiweb Technology is your best technical partner and offering you solution for any kind of website and application...

PHP is widely used open-source scripting language it helps in making dynamically easy your websites and web application. Mobiweb Technology is your best technical partner and offering you solution for any kind of website and application development. To hire PHP developer and web developer at affordable prices contact Mobiweb Technology via [email protected]