React & Webpack

This quick start guide will teach you how to wire up TypeScript withReactandwebpack.

We assume that you’re already usingNode.jswithnpm.

布局项目

Let’s start out with a new directory. We’ll name itprojfor now, but you can change it to whatever you want.

mkdir proj
cd proj

To start, we’re going to structure our project in the following way:

proj/
├─ dist/
└─ src/
   └─ components/

TypeScript files will start out in yoursrcfolder, run through the TypeScript compiler, then webpack, and end up in abundle.jsfile indist. Any components that we write will go in thesrc/componentsfolder.

Let’s scaffold this out:

mkdir src
cd src
mkdir components
cd ..

Webpack will eventually generate thedistdirectory for us.

初始化项目

Now we’ll turn this folder into an npm package.

npm init

You’ll be given a series of prompts. You can use the defaults except for your entry point. You can always go back and change these in thepackage.jsonfile that’s been generated for you.

安装我们的依赖项

First ensure Webpack is installed globally.

npm install -g webpack

Webpack is a tool that will bundle your code and optionally all of its dependencies into a single.jsfile.

Let’s now add React and React-DOM, along with their declaration files, as dependencies to yourpackage.jsonfile:

npm install --save react react-dom @types/react @types/react-dom

That@types/prefix means that we also want to get the declaration files for React and React-DOM. Usually when you import a path like"react", it will look inside of thereactpackage itself; however, not all packages include declaration files, so TypeScript also looks in the@types/reactpackage as well. You’ll see that we won’t even have to think about this later on.

Next, we’ll add development-time dependencies onawesome-typescript-loaderandsource-map-loader.

npm install --save-dev typescript awesome-typescript-loader source-map-loader

Both of these dependencies will let TypeScript and webpack play well together. awesome-typescript-loader helps Webpack compile your TypeScript code using the TypeScript’s standard configuration file namedtsconfig.json. source-map-loader uses any sourcemap outputs from TypeScript to inform webpack when generating_its own_sourcemaps. This will allow you to debug your final output file as if you were debugging your original TypeScript source code.

Please note that awesome-typescript-loader is not the only loader for typescript. You could instead usets-loader. Read about the differences between themhere

Notice that we installed TypeScript as a development dependency. We could also have linked TypeScript to a global copy withnpm link typescript, but this is a less common scenario.

添加TypeScript配置文件

You’ll want to bring your TypeScript files together - both the code you’ll be writing as well as any necessary declaration files.

To do this, you’ll need to create atsconfig.jsonwhich contains a list of your input files as well as all your compilation settings. Simply create a new file in your project root namedtsconfig.jsonand fill it with the following contents:

{
    "compilerOptions": {
        "outDir": "./dist/",
        "sourceMap": true,
        "noImplicitAny": true,
        "module": "commonjs",
        "target": "es5",
        "jsx": "react"
    },
    "include": [
        "./src/**/*"
    ]
}

You can learn more abouttsconfig.jsonfileshere.

编写一些代码

Let’s write our first TypeScript file using React. First, create a file namedHello.tsxinsrc/componentsand write the following:

import * as React from "react";

export interface HelloProps { compiler: string; framework: string; }

export const Hello = (props: HelloProps) => <h1>Hello from {props.compiler} and {props.framework}!</h1>;

Note that while this example usesstateless functional components), we could also make our example a little_classier_as well.

import * as React from "react";

export interface HelloProps { compiler: string; framework: string; }

// 'HelloProps' describes the shape of props.
// State is never set so we use the 'undefined' type.
export class Hello extends React.Component<HelloProps, undefined> {
    render() {
        return <h1>Hello from {this.props.compiler} and {this.props.framework}!</h1>;
    }
}

Next, let’s create anindex.tsxinsrcwith the following source:

import * as React from "react";
import * as ReactDOM from "react-dom";

import { Hello } from "./components/Hello";

ReactDOM.render(
    <Hello compiler="TypeScript" framework="React" />,
    document.getElementById("example")
);

We just imported ourHellocomponent intoindex.tsx. Notice that unlike with"react"or"react-dom", we used a_relative path_toHello.tsx- this is important. If we hadn’t, TypeScript would’ve instead tried looking in ournode_modulesfolder.

We’ll also need a page to display ourHellocomponent. Create a file at the root ofprojnamedindex.htmlwith the following contents:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>Hello React!</title>
    </head>
    <body>
        <div id="example"></div>

        <!-- Dependencies -->
        <script src="./node_modules/react/dist/react.js"></script>
        <script src="./node_modules/react-dom/dist/react-dom.js"></script>

        <!-- Main -->
        <script src="./dist/bundle.js"></script>
    </body>
</html>

Notice that we’re including files from withinnode_modules. React and React-DOM’s npm packages include standalone.jsfiles that you can include in a web page, and we’re referencing them directly to get things moving faster. Feel free to copy these files to another directory, or alternatively, host them on a content delivery network (CDN). Facebook makes CDN-hosted versions of React available, and you canread more about that here.

创建webpack配置文件

Create awebpack.config.jsfile at the root of the project directory.

module.exports = {
    entry: "./src/index.tsx",
    output: {
        filename: "bundle.js",
        path: __dirname + "/dist"
    },

    // Enable sourcemaps for debugging webpack's output.
    devtool: "source-map",

    resolve: {
        // Add '.ts' and '.tsx' as resolvable extensions.
        extensions: ["", ".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
    },

    module: {
        loaders: [
            // All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
            { test: /\.tsx?$/, loader: "awesome-typescript-loader" }
        ],

        preLoaders: [
            // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
            { test: /\.js$/, loader: "source-map-loader" }
        ]
    },

    // When importing a module whose path matches one of the following, just
    // assume a corresponding global variable exists and use that instead.
    // This is important because it allows us to avoid bundling all of our
    // dependencies, which allows browsers to cache those libraries between builds.
    externals: {
        "react": "React",
        "react-dom": "ReactDOM"
    },
};

You might be wondering about thatexternalsfield. We want to avoid bundling all of React into the same file, since this increases compilation time and browsers will typically be able to cache a library if it doesn’t change.

Ideally, we’d just import the React module from within the browser, but most browsers still don’t quite support modules yet. Instead libraries have traditionally made themselves available using a single global variable likejQueryor_. This is called the “namespace pattern”, and webpack allows us to continue leveraging libraries written that way. With our entry for"react": "React", webpack will work its magic to make any import of"react"load from theReactvariable.

You can learn more about configuring webpackhere.

把它放在一起

Just run:

webpack

Now open upindex.htmlin your favorite browser and everything should be ready to use! You should see a page that says “Hello from TdypeScript and React!”

results matching ""

    No results matching ""