【译】如何从头开始搭建React,Webpack4,Babel7工程

这是一篇非常适合新手的教程。

How to set up React, webpack 4, and Babel (2018)

目录:

  1. 你将会学习到的知识
  2. 建立项目
  3. 配置webpack
  4. 配置Babel
  5. 编写React组件
  6. HTML webpack plugin
  7. webpack dev server
  8. 总结


你将会学习到的知识

  • 如何安装及配置webpack
  • 如何安装及配置Babel
  • 如何安装React
  • 如何编写React组件
  • 如何在HTML页面中引入打包文件
  • 如何安装及配置webpack dev server


建立项目

首先,创建工程目录:

mkdir webpack-react-tutorial && cd $_复制代码

创建工程的基础目录结构:

mkdir -p src复制代码

初始化项目:

npm init -y复制代码


配置webpack

webpack是一款非常强大的工具,学习webpack不仅可以用于搭建React项目,它适用于任何前端工程。

webpack提取原始的React组件,用于生成(几乎)每个浏览器都能理解的JavaScript代码。

安装webpack:

npm i webpack --save-dev复制代码

同时需要安装webpack-cli:

npm i webpack-cli --save-dev复制代码

下一步,在package.json中添加webpack命令:

"scripts": {
    "build": "webpack --mode production"
}复制代码

现在你不需要为webpack定义配置文件。

老版本的webpack不会自动查找配置文件,但从webpack4开始,不需要配置文件就可以直接进行开发。

接下来我将安装并配置Babel来编译我们的代码。


配置Babel

React组件大多是由ES6语法编写。ES6是对语法的一次很好的改进,但老版本浏览器往往不能解析新的ES6语法。有状态的React组件被生命为class,因此,为了让ES6在旧版浏览器中运行,我们需要进行某种转换。我们把这种转换成为编译

webpack并不知道如何将ES6语法转换为ES5,不过webpack可以使用loader来完成。即webpack加载器将一些东西作为输入,并将其转换为其他东西输出。

webpack中的babel-loader便担任着将ES6语法转换为浏览器所能理解语法的工作。

  1. babel preset env 负责将ES6语法转换成ES5
  2. babel preset react 负责将JSX语法转化为JavaScript

安装依赖:

npm i @babel/core babel-loader @babel/preset-env @babel/preset-react --save-dev复制代码

不要忘记配置Babel。在工程根目录下创建.babelrc文件,配置如下:

{
  "presets": ["@babel/preset-env", "@babel/preset-react"]
}复制代码

现在,我们需要编写一个简短的webpack配置文件。

创建webpack.config.js文件,配置如下:

module.exports = {
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      }
    ]
  }
};复制代码

对于每个带有js或jsx扩展名的文件,Webpack通过babel-loader管理代码,将ES6转换为ES5。

有了这个,我们就可以编写React组件了。


编写React组件

首先按照Container/Presentation原则,创建两个React组件。

容器组件是承载所有逻辑的组件:用于处理状态更改的函数,内部组件状态等。 相反,展示组件仅用于展示。 展示组件是普通的JavaScript函数,它从容器组件接收数据作为props。

下面,我将构建一个简单的带文本框的React表单。

编写代码之前,需要安装React:

npm i react react-dom --save-dev复制代码

接着,创建组件的目录结构:

mkdir -p src/js/components/{container,presentational}复制代码

下面我们创建容器组件,需满足以下条件:

  • 有自己的state
  • 渲染出来是一个HTML表单

创建组件:

touch src/js/components/container/FormContainer.jsx复制代码

代码如下:

import React, { Component } from "react";
import ReactDOM from "react-dom";

class FormContainer extends Component {
  constructor() {
    super();

    this.state = {
      title: ""
    };
  }

  render() {
    return (
      <form id="article-form">
      </form>
    );
  }
}

export default FormContainer;复制代码

这个组件目前没有完成任何工作,它只是一个用于包含子组件的框架。

下面创建子组件:

touch src/js/components/presentational/Input.jsx复制代码

我们的展示组件是一个文本框。一个HTML文本框拥有以下属性:

  • type
  • class
  • id
  • value
  • required

所有的这些属性都应该由父容器组件传入子组件。

如果input拥有自己的state,在使用时一定要注意,确保HTML input是一个受控的React组件。

安装如下依赖:

npm i prop-types --save-dev复制代码

回到React组件,展示组建代码如下:

import React from "react";
import PropTypes from "prop-types";

const Input = ({ label, text, type, id, value, handleChange }) => (
  <div className="form-group">
    <label htmlFor={label}>{text}</label>
    <input
      type={type}
      className="form-control"
      id={id}
      value={value}
      onChange={handleChange}
      required
    />
  </div>
);

Input.propTypes = {
  label: PropTypes.string.isRequired,
  text: PropTypes.string.isRequired,
  type: PropTypes.string.isRequired,
  id: PropTypes.string.isRequired,
  value: PropTypes.string.isRequired,
  handleChange: PropTypes.func.isRequired
};

export default Input;复制代码

接下来,我们用容器组件包含这个展示组建:

import React, { Component } from "react";
import ReactDOM from "react-dom";
import Input from "../presentational/Input.jsx";

class FormContainer extends Component {
  constructor() {
    super();

    this.state = {
      seo_title: ""
    };

    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(event) {
    this.setState({ [event.target.id]: event.target.value });
  }

  render() {
    const { seo_title } = this.state;
    return (
      <form id="article-form">
        <Input
          text="SEO title"
          label="seo_title"
          type="text"
          id="seo_title"
          value={seo_title}
          handleChange={this.handleChange}
        />
      </form>
    );
  }
}

export default FormContainer;复制代码

webpack默认的入口文件为./src/index.js。我们创建这个文件,并在入口文件中引入容器组件FormContainer

import FormContainer from "./js/components/container/FormContainer.jsx";复制代码

然后,我们就可以执行如下命令进行打包:

npm run build复制代码

打包后的js文件在./dist/main.js

现在让我们将实现将打包文件引入HTML页面。


HTML webpack plugin

要使React form展示出来,我们必须要让webpack创建一个HTML页面,并且将打包后的js文件引入HTML。

Webpacks需要两个额外的组件来处理HTML:html-webpack-pluginhtml-loader

安装依赖:

npm i html-webpack-plugin html-loader --save-dev复制代码

更新webpack配置文件:

const HtmlWebPackPlugin = require("html-webpack-plugin");

module.exports = {
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      },
      {
        test: /\.html$/,
        use: [
          {
            loader: "html-loader"
          }
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebPackPlugin({
      template: "./src/index.html",
      filename: "./index.html"
    })
  ]
};复制代码

创建./src/index.html文件

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

<head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" >
    <title>How to set up React, Webpack, and Babel</title>
</head>

<body>
    <div class="container">
        <div class="row mt-5">
            <div class="col-md-4 offset-md-1">
                <p>Create a new article</p>
                <div id="create-article-form">
                    <!-- form -->
                </div>

            </div>

        </div>
    </div>
</body>

</html>复制代码

最后,将React组件挂在到id为create-article-form的元素上:

const wrapper = document.getElementById("create-article-form");
wrapper ? ReactDOM.render(<FormContainer />, wrapper) : false;复制代码

再次build:

npm run build复制代码

查看dist目录,你将会看到HTML结果文件

使用webpack,不需要手动将js文件引入HTML,打包后的文件将会被自动注入。

打开./dist/index.html,你将会在浏览器中看到刚刚编写的React表单


Webpack dev server

如果你不想每次改变文件的时候都执行npm run build来查看结果,使用简单的三行配置就可以启动本地的开发服务器。配置后,webpack将在浏览器中启动应用程序。 此外,每次修改后保存文件webpack服务器都会自动刷新浏览器的窗口。

安装依赖:

npm i webpack-dev-server --save-dev复制代码

更新package.json

"scripts": {
  "start": "webpack-dev-server --open --mode development",
  "build": "webpack --mode production"
}复制代码

运行命令:

npm start复制代码

你将会在浏览器中看到如下界面:

Webpack Dev Server

并且,每次更新文件webpack dev server都会自动刷新页面。


总结

create-react-app是一种开启React项目的方法,几乎所有东西都是开箱即用。但迟早,你都会想要调整或修改一下原有的webpack配置。

如果你学习了如何手动配置React,webpack和Babel,你就可以根据自己的需要从零开始配置React项目。

这些知识对于不需要完整的SPA但仍希望构建和分发ES6代码的情况也很有用。 通过组合webpack和Babel,可以将一堆React组件转换为适合分发的bundle。


原文链接:https://www.valentinog.com/blog/react-webpack-babel/


猜你喜欢

转载自juejin.im/post/5c622eddf265da2de04a9891