一、介绍

之前写过一篇文章已经介绍过如何在 gulp 项目中使用 typescript,并且 browserify 和 babel 是如何与 typescript 一起工作的,文章地址:http://ptbird.cn/gulp-typescript.html

这篇文章主要尝试在 webpack 中是如何打包 typescript 文件,以及 react 项目如何去使用。

二、准备 webpack 基本环境

这里不再重复 webpack + react 的基本配置是如何做的,之前我也配过一个 webpack 开发 react 的脚手架,虽然比较烂(挺久之前的了),不过可以拿来直接改改,基础的东西就不想再写了。

项目地址:https://github.com/postbird/webpack-react-development

对于 webpack 来说,可以使用 awesome-typescript-loader 来读取标准的 tsconfig.json 配置文件,从而来编译 TypeScript 。

这里并没有借助 babel 以及 @babel/preset-typescript,直接是通过 loader 去处理 .tsx 文件:

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

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

完整的 webpack.config.js

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

// 公共目录
const website = {
    publicPath: '/'
}
module.exports = {
    mode: 'development',
    devtool: 'source-map',
    entry: {
        bundle: path.resolve(__dirname, 'src/main.tsx')
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'js/[name].js',
        publicPath: website.publicPath
    },
    externals: {
        "react": "React",
        "react-dom": "ReactDOM"
    },
    resolve: {
        extensions: ['.js', '.jsx', '.json', '.coffee', '.tsx']
    },
    module: {
        rules: [
            {
                test: /\.(tsx)/,
                exclude: /node_modules/,
                use: [
                    {
                        loader: 'awesome-typescript-loader'
                    }
                ]
            },
            { enforce: "pre", test: /\.js$/, loader: "source-map-loader" }
        ]
    },
    // 插件
    plugins: [
        new HtmlWebpackPlugin({
            title: 'Webpack-React-Development By Postbird',
            template: 'src/index.html'
        }),
    ],
    devServer: {
        contentBase: path.resolve(__dirname, 'dist'),
        host: '0.0.0.0',
        compress: true,
        port: 8080,
        inline: true,
        open: 'http://127.0.0.1:8080'
    }
}

三、配置 tsconfig.json

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

四、html 模板文件

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Webpack4 React16 Development - By Postbird</title>
  <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>

<body>
  <div id="app"></div>
  <!-- Dependencies -->
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
</body>
</html>

五、运行结果

111.jpg

六、只使用 babel 进行处理

上面的示例中还是使用了 awesome-typescript-loader 来读取 tsconfig,编译 typescript,但是对于 .tsx 文件,可以直接通过强大的 babel-loader 来处理,并不一定需要借助其他的 loader。

安装 @babel presets

如果要处理 .tsx 需要 3 个 preset,分别是 @babel/preset-react,@babel/preset-env@babel/preset-typescript

修改 webpack.config.js

修改后的 webpack 配置文件:

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

// 公共目录
const website = {
    publicPath: '/'
}
module.exports = {
    mode: 'development',
    devtool: 'source-map',
    entry: {
        bundle: path.resolve(__dirname, 'src/main.tsx')
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'js/[name].js',
        publicPath: website.publicPath
    },
    externals: {
        "react": "React",
        "react-dom": "ReactDOM"
    },
    resolve: {
        extensions: ['.js', '.jsx', '.json', '.coffee', '.tsx']
    },
    module: {
        rules: [
            {
                test: /\.(tsx)/,
                exclude: /node_modules/,
                use: [
                    {
                        loader: 'babel-loader'
                    }
                ]
            },
            { enforce: "pre", test: /\.js$/, loader: "source-map-loader" }
        ]
    },
    // 插件
    plugins: [
        new HtmlWebpackPlugin({
            title: 'Webpack-React-Development By Postbird',
            template: 'src/index.html'
        }),
    ],
    devServer: {
        contentBase: path.resolve(__dirname, 'dist'),
        host: '0.0.0.0',
        compress: true,
        port: 8080,
        inline: true,
        open: 'http://127.0.0.1:8080'
    }
}

可以看到只需要一个 babel-loader 就可以解决所有问题,babel 才是王道!

运行结果:

222.jpg

七、代码示例

https://github.com/postbird/demo-typescript/tree/dev/20190314