Monday, May 8, 2017

Integrating ReactJS, Typescript, and Webpack Part 2

For those of you who want to dive in and see the final version of the code, check it out here!

ReactJS is a library released by Facebook and unlike other JavaScript frameworks out there (i.e. Angular, Backbone, Ember, etc), it’s goal is to simply represent the 'View' layer in the traditional Model View Controller (MVC) paradigm.

ReactJS, Typescript, and Webpack
Now that we have a Typescript and Webpack integrated on previous chapter Part 1, let's go ahead and throw ReactJS into the mix as well. Let's first NPM install ReactJS as a dependency.
  npm install --save react react-dom
Since we're using a 3rd party library with Typescript, we're going to need to NPM install Typings as well. You might be asking, "what is Typings?". Typings is simply the tool we use to manage all of the Typescript definition files. It’ll allow us to easily download and use all of our 3rd party Typescript definition files.
 npm install --save-dev typings
Here’s how our package.json file looks now:
{
  "name": "typescript-webpack-react",
  "version": "1.0.0",
  "scripts": {
    "build": "webpack"
  },
  "devDependencies": {
    "ts-loader": "^2.0.3",
    "typescript": "^2.3.2",
    "typings": "^2.1.1",
    "webpack": "^2.1.0-beta.22"
  },
  "dependencies": {
    "react": "^15.5.4",
    "react-dom": "^15.5.4"
  }
}
Let's download the Definitely Typed files for React and ReactDOM. We'll use Typings to do the installation:
 node_modules/.bin/typings install --save react react-dom

Note: The preferred method for installing typings for Typescript >2.0 is now
npm install --save-dev @types/react @types/react-dom

A couple of things to notice:
1. Because we didn't install Typings globally, we had to prefix the command with where the Typings module is located: node_modules/.bin/typings.
2. The "--save" flag indicates that we want to save the React and ReactDOM definition files.
3. Notice that our directory now has a typings directory as well as a "typings.json" file. The typings.json file specifies all of the definition files we have installed, and the typings directory contains the actual definition files.

Now that we're trying to use React with Typescript, we should update a Typescript configuration file tsconfig.json which we have set up on Part 1.
{
    "compilerOptions": {
        "jsx": "react",
        "module": "commonjs",
        "noImplicitAny": true,
        "outDir": "./build/",
        "preserveConstEnums": true,
        "removeComments": true,
        "target": "ES5"
    },
        "exclude": [
         "node_modules"        
    ]
}

A couple of things to note here:
1. Make sure that tsconfig.json is located in the root directory.
2. If you want to learn more about the tsconfig.json file, check this out. Of particular importance to us is the "jsx" key which tells Typescript to accept React’s JSX syntax whenever we create a file with a ".tsx" extension.
3. Notice that we’re specifying files and directories to include from going through the Typescript compiler.

Since we're using React now, let’s rename our src/some_module.ts file to src/Hello.tsx, and create a simple Hello component:
// Remember to rename your file to Hello.tsx and
// place it within your src/ directory

import * as React from "react";

interface HelloProps {
  name: string;
}

class Hello extends React.Component<HelloProps, {}> {
  render() {
    return <div>Hello, {this.props.name}</div>;
  }
}

export default Hello;
Let’s also rename our src/app.ts file to src/app.tsx, and change the content to the following:

// Remember to rename the file from app.ts to app.tsx
// and to keep it in the src/ directory.

import * as React from "react";
import * as ReactDOM from "react-dom";
import Hello from "./Hello";

ReactDOM.render(
  <Hello name="Willson" />,
  document.getElementById("root")
);
Since we’re injecting our rendered Hello component into the DOM, we’ll need to modify our index.html file as well.
<--index.html -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Getting Started with Typescript, Webpack, and ReactJS </title>
  </head>
  <body>
<!-- this is where our Hello component will get rendered into -->
    <div id="root"></div>

    <script src="build/bundle.js"></script>
 </body>
</html>
We’ve renamed our application's entry point, which means we'll need to modify our webpack.config.js file as well. It's a minor change — we just need to change it to the correct file extension.
var path = require("path");

var config = {
  /*
   * app.tsx represents the entry point to your web application. Webpack will
   * recursively go through every "require" statement in app.ts and
   * efficiently build out the application's dependency tree.
   */
  entry: ["./src/app.tsx"],

  /*
   * The combination of path and filename tells Webpack what name to give to
   * the final bundled JavaScript file and where to store this file.
   */
  output: {
    path: path.resolve(__dirname, "build"),
    filename: "bundle.js"
  },

  /*
   * resolve lets Webpack now in advance what file extensions you plan on
   * "require"ing into the web application, and allows you to drop them
   * in your code.
   */
  resolve: {
    extensions: [".ts", ".tsx", ".js"]
  },

  module: {
    /*
     * Each loader needs an associated Regex test that goes through each
     * of the files you've included (or in this case, all files but the
     * ones in the excluded directories) and finds all files that pass
     * the test. Then it will apply the loader to that file. I haven't
     * installed ts-loader yet, but will do that shortly.
     */
    loaders: [
      {
        test: /\.tsx?$/,
        loader: "ts-loader",
        exclude: /node_modules/
      }
    ]
  }
};

module.exports = config;
And if you run "npm run build" in your terminal again, you should see Webpack do its thing and generate a new bundle.js file. If we open our index.html in the browser, you'll see the fruits of your labor!

Conclusion
Hopefully you've found this tutorial helpful for getting you started using these 3 technologies together. There’s tons more you can do (i.e. use webpack-dev-server, set up source maps in Typescript, etc) but I’ll leave it for you to continue exploring!

Source: Getting Started with ReactJS, Typescript, and Webpack

2 comments:

  1. Hi there,

    Your app.tsx file is missing a parameter in the ReactDOM.render function. I used ``.

    Also, in the latest version of webpack, in the webpack.config.js file, in the resolve.extensions array property, including an empty string will result in an error on build and should be removed.

    Finally, the typings module's react typings are out-dated and will not work. The preferred method for installing typings for Typescript >2.0 is now `npm install --save-dev @types/react @types/react-dom`.

    With these changes, I was able to get everything to work. Thanks!

    ReplyDelete
    Replies
    1. Hello Babin,

      Thank you for sharing a solution to a problem. :)


      Delete