返回博客

使用webpack打包react应用程序

2019年3月17日
leeguangxing.cn1139 阅读
&& exit 1", "watch": "webpack --watch", "build": "webpack" } // ...... }

往后就可以执行 npm run build 来打包,执行 npm run watch 来监听并实时打包。


安装 babel 相关的开发依赖模块

安装 webpack 的 babel 源码转换器:

yarn add babel-loader --dev

安装 babel 编译器核心模块:

yarn add @babel/core --dev

安装转换 ES2015+ 的预设模块:

yarn add @babel/preset-env --dev

安装转换 React JSX 格式的预设模块:

yarn add @babel/preset-react --dev

安装类属性 babel 插件:

yarn add @babel/plugin-proposal-class-properties --dev

之所以要使用该类属性插件,是因为我想使用属性初始化器语法来避免在 React 组件中使用繁琐的 bind 来绑定 this:

import React from "react";

class ListTabContentUI extends React.Component {
    constructor(props) {
        super(props);
        // this.handleClick = this.handleClick.bind(this);
    }
    // 可以这样以声明方式绑定 this
    handleClick = () => {
        // ......
    };
}

最后,在项目根目录创建一个 .babelrc 配置文件,定义使用以上的预设模块和插件:

{
  "presets": [
    "@babel/preset-env",
    "@babel/preset-react"
  ],
  "plugins": [
    "@babel/plugin-proposal-class-properties"
  ]
}

babel 在不断的发展,以上说明是基于 babel v7.3.4 的步骤。要查看官方的最新安装方式,请点击这里

webpack 配置例子

以下是一个简单的 webpack 配置文件:

// node.js 的 path 模块,后面使用它的 resolve 方法将一系列路径或路径段解析为绝对路径
const path = require('path');

module.exports = {

    // 告知 webpack 使用相应模式的内置优化,可选值为 'development' 和 'production'
    mode: 'development',

    // 这里定义了两个入口
    entry: {
        backstage: ['./server/src/backstage/index.js'],
        front: ['./server/src/front/index.js']
    },

    // 定义了输出文件的动态名称和输出路径
    output: {
        filename: '[name].js',
        path: path.resolve(__dirname, 'server/public/javascripts/dist')
    },

    // 添加模块处理规则
    module: {
        rules: [
            {
                test: /.js$/,
                // 声明加载器作用的路径
                include: [
                    path.resolve(__dirname, "server/src"),
                    path.resolve(__dirname, "server/lib")
                ],
                /*exclude: /(node_modules)/,*/
                loader: 'babel-loader',
                query: {
                    presets: ["@babel/preset-env", "@babel/preset-react"],
                    plugins: ["@babel/plugin-proposal-class-properties"]
                }
            }
        ]
    },

    optimization: {
        // 代码拆分方式,用于优化加载
        // 考虑到共享模块可以缓存共享,并且并行加载,所以作出以下拆分方式
        splitChunks: {
            cacheGroups: {
                // 创建一个commons 块,其中包括入口点之间共享的所有代码。
                commons: {
                    name: 'commons',
                    // 仅作用于共享的静态模块
                    chunks: 'initial',
                    // 至少有两个共享模块才作拆分
                    minChunks: 2
                }
            }
        }
    },

    // 生成 .map 文件实现源文件映射。在生产环境可以去掉这项。
    devtool: 'source-map'
};

本博客并没有使用 import() 进行动态加载。因为经过 Nginx 的 gzip 模块进行数据压缩后,使用 Grunt 合并和压缩的第三方脚本库,还有 webpack 打包的 React 脚本所有加起来不到 200K,再利用缓存,已达到很好的加载体现。